From 8645b4c3f1109737f3b304725a162403b0f72cb9 Mon Sep 17 00:00:00 2001 From: Mykhailo Lytvyn Date: Sun, 26 May 2024 17:17:01 +0200 Subject: [PATCH] CCv2: List environment specific data backups --- CHANGELOG.md | 1 + .../plugin/hybris/common/utils/HybrisIcons.kt | 2 + .../plugin/hybris/tools/ccv2/CCv2Service.kt | 27 +++++ .../plugin/hybris/tools/ccv2/api/CCv2Api.kt | 21 +++- .../tools/ccv2/dto/CCv2DataBackupDto.kt | 56 +++++++++ .../tools/ccv2/dto/CCv2EnvironmentDto.kt | 1 + .../ccv2/views/CCv2EnvironmentDetailsView.kt | 111 ++++++++++++++++++ .../toolwindow/ccv2/views/CCv2UiElements.kt | 21 ++++ 8 files changed, 235 insertions(+), 5 deletions(-) create mode 100644 src/com/intellij/idea/plugin/hybris/tools/ccv2/dto/CCv2DataBackupDto.kt diff --git a/CHANGELOG.md b/CHANGELOG.md index bb122484a..e4c36c2a4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ - Show Green deployment information in the Service view [#1129](https://github.com/epam/sap-commerce-intellij-idea-plugin/pull/1129) - Show Initial Passwords in the `hcs_admin` Service view [#1130](https://github.com/epam/sap-commerce-intellij-idea-plugin/pull/1130) - Added possibility to re-fetch Service details [#1132](https://github.com/epam/sap-commerce-intellij-idea-plugin/pull/1132) +- List environment specific data backups [#1136](https://github.com/epam/sap-commerce-intellij-idea-plugin/pull/1136) ### `items.xml` enhancements - Added reference resolution for index `include`:`attribute` [#1134](https://github.com/epam/sap-commerce-intellij-idea-plugin/pull/1134) diff --git a/src/com/intellij/idea/plugin/hybris/common/utils/HybrisIcons.kt b/src/com/intellij/idea/plugin/hybris/common/utils/HybrisIcons.kt index e19db5952..4e4484fc5 100644 --- a/src/com/intellij/idea/plugin/hybris/common/utils/HybrisIcons.kt +++ b/src/com/intellij/idea/plugin/hybris/common/utils/HybrisIcons.kt @@ -249,6 +249,8 @@ object HybrisIcons { val CCV2_SERVICE = AllIcons.Nodes.Services val CCV2_SERVICE_MODIFIED_BY = AllIcons.General.User + val CCV2_DATA_BACKUP_CREATED_BY = AllIcons.General.User + val CCV2_DEPLOYMENT_CREATED_BY = AllIcons.General.User val CCV2_DEPLOYMENT_UPDATE_MODE_NONE = AllIcons.Diff.GutterCheckBox val CCV2_DEPLOYMENT_UPDATE_MODE_UPDATE = ExpUiIcons.General.PluginUpdate diff --git a/src/com/intellij/idea/plugin/hybris/tools/ccv2/CCv2Service.kt b/src/com/intellij/idea/plugin/hybris/tools/ccv2/CCv2Service.kt index ad6a4fab7..0d716aa02 100644 --- a/src/com/intellij/idea/plugin/hybris/tools/ccv2/CCv2Service.kt +++ b/src/com/intellij/idea/plugin/hybris/tools/ccv2/CCv2Service.kt @@ -175,6 +175,33 @@ class CCv2Service(val project: Project, private val coroutineScope: CoroutineSco } } + fun fetchEnvironmentDataBackups( + subscription: CCv2Subscription, + environment: CCv2EnvironmentDto, + onStartCallback: () -> Unit, + onCompleteCallback: (Collection?) -> Unit + ) { + onStartCallback.invoke() + + coroutineScope.launch { + withBackgroundProgress(project, "Fetching CCv2 Environment Data Backups...", true) { + val ccv2Token = getCCv2Token(subscription) ?: return@withBackgroundProgress + var dataBackups: Collection? = null + + try { + dataBackups = CCv2Api.getInstance().fetchEnvironmentDataBackups(ccv2Token, subscription, environment) + .sortedByDescending { it.createdTimestamp } + } catch (e: SocketTimeoutException) { + notifyOnTimeout(subscription) + } catch (e: RuntimeException) { + notifyOnException(subscription, e) + } + + onCompleteCallback.invoke(dataBackups) + } + } + } + fun fetchEnvironmentServiceProperties( subscription: CCv2Subscription, environment: CCv2EnvironmentDto, diff --git a/src/com/intellij/idea/plugin/hybris/tools/ccv2/api/CCv2Api.kt b/src/com/intellij/idea/plugin/hybris/tools/ccv2/api/CCv2Api.kt index 11645c58c..e3c55e7ef 100644 --- a/src/com/intellij/idea/plugin/hybris/tools/ccv2/api/CCv2Api.kt +++ b/src/com/intellij/idea/plugin/hybris/tools/ccv2/api/CCv2Api.kt @@ -18,10 +18,7 @@ package com.intellij.idea.plugin.hybris.tools.ccv2.api -import com.intellij.idea.plugin.hybris.ccv2.api.BuildApi -import com.intellij.idea.plugin.hybris.ccv2.api.DeploymentApi -import com.intellij.idea.plugin.hybris.ccv2.api.EnvironmentApi -import com.intellij.idea.plugin.hybris.ccv2.api.ServicePropertiesApi +import com.intellij.idea.plugin.hybris.ccv2.api.* import com.intellij.idea.plugin.hybris.ccv2.invoker.infrastructure.ApiClient import com.intellij.idea.plugin.hybris.ccv2.model.CreateBuildRequestDTO import com.intellij.idea.plugin.hybris.ccv2.model.CreateDeploymentRequestDTO @@ -52,6 +49,7 @@ class CCv2Api { private val deploymentApi by lazy { DeploymentApi(client = apiClient) } private val buildApi by lazy { BuildApi(client = apiClient) } private val servicePropertiesApi by lazy { ServicePropertiesApi(client = apiClient) } + private val databackupApi by lazy { DatabackupApi(client = apiClient) } suspend fun fetchEnvironments( ccv2Token: String, @@ -101,6 +99,19 @@ class CCv2Api { } } + suspend fun fetchEnvironmentDataBackups( + ccv2Token: String, + subscription: CCv2Subscription, + environment: CCv2EnvironmentDto, + ) = databackupApi.getDatabackups( + subscriptionCode = subscription.id!!, + environmentCode = environment.code, + requestHeaders = createRequestParams(ccv2Token) + ) + .value + ?.map { CCv2DataBackupDto.map(it) } + ?: emptyList() + suspend fun fetchEnvironmentsBuilds( ccv2Token: String, subscription: CCv2Subscription, @@ -122,7 +133,7 @@ class CCv2Api { subscription: CCv2Subscription, environment: CCv2EnvironmentDto, ): CCv2BuildDto? = deploymentApi.getDeployments( - subscription.id!!, + subscriptionCode = subscription.id!!, environmentCode = environment.code, dollarCount = true, dollarTop = 1, diff --git a/src/com/intellij/idea/plugin/hybris/tools/ccv2/dto/CCv2DataBackupDto.kt b/src/com/intellij/idea/plugin/hybris/tools/ccv2/dto/CCv2DataBackupDto.kt new file mode 100644 index 000000000..b5c5a2c3b --- /dev/null +++ b/src/com/intellij/idea/plugin/hybris/tools/ccv2/dto/CCv2DataBackupDto.kt @@ -0,0 +1,56 @@ +/* + * This file is part of "SAP Commerce Developers Toolset" plugin for IntelliJ IDEA. + * Copyright (C) 2019-2024 EPAM Systems and contributors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +package com.intellij.idea.plugin.hybris.tools.ccv2.dto + +import com.intellij.idea.plugin.hybris.ccv2.model.DatabackupDetailDTO +import com.intellij.idea.plugin.hybris.tools.ccv2.CCv2Util +import java.time.OffsetDateTime + +data class CCv2DataBackupDto( + val dataBackupCode: String, + val name: String, + val buildCode: String, + val status: String, + val dataBackupType: String, + val description: String, + var createdBy: String, + val createdTimestamp: OffsetDateTime?, + val canBeRestored: Boolean, + val canBeDeleted: Boolean, + val canBeCanceled: Boolean, +) { + val createdTimestampFormatted + get() = CCv2Util.formatTime(createdTimestamp) + + companion object { + fun map(dto: DatabackupDetailDTO) = CCv2DataBackupDto( + dataBackupCode = dto.databackupCode ?: "N/A", + name = dto.name ?: "N/A", + buildCode = dto.buildCode ?: "N/A", + status = dto.status ?: "N/A", + dataBackupType = dto.databackupType ?: "N/A", + description = dto.description ?: "N/A", + createdBy = dto.createdBy ?: "N/A", + createdTimestamp = dto.createdTimestamp, + canBeRestored = dto.canBeRestored ?: false, + canBeDeleted = dto.canBeDeleted ?: false, + canBeCanceled = dto.canBeCanceled ?: false + ) + } +} diff --git a/src/com/intellij/idea/plugin/hybris/tools/ccv2/dto/CCv2EnvironmentDto.kt b/src/com/intellij/idea/plugin/hybris/tools/ccv2/dto/CCv2EnvironmentDto.kt index 0f61325d6..df05e3ee7 100644 --- a/src/com/intellij/idea/plugin/hybris/tools/ccv2/dto/CCv2EnvironmentDto.kt +++ b/src/com/intellij/idea/plugin/hybris/tools/ccv2/dto/CCv2EnvironmentDto.kt @@ -38,6 +38,7 @@ data class CCv2EnvironmentDto( val link: String?, val mediaStorages: Collection, var services: Collection? = null, + var dataBackups: Collection? = null, ) : CCv2DTO, Comparable { override fun compareTo(other: CCv2EnvironmentDto) = name.compareTo(other.name) diff --git a/src/com/intellij/idea/plugin/hybris/toolwindow/ccv2/views/CCv2EnvironmentDetailsView.kt b/src/com/intellij/idea/plugin/hybris/toolwindow/ccv2/views/CCv2EnvironmentDetailsView.kt index 479019ed8..8317f4f45 100644 --- a/src/com/intellij/idea/plugin/hybris/toolwindow/ccv2/views/CCv2EnvironmentDetailsView.kt +++ b/src/com/intellij/idea/plugin/hybris/toolwindow/ccv2/views/CCv2EnvironmentDetailsView.kt @@ -26,6 +26,7 @@ import com.intellij.idea.plugin.hybris.tools.ccv2.CCv2Service import com.intellij.idea.plugin.hybris.tools.ccv2.actions.CCv2FetchEnvironmentAction import com.intellij.idea.plugin.hybris.tools.ccv2.actions.CCv2ShowServiceDetailsAction import com.intellij.idea.plugin.hybris.tools.ccv2.dto.CCv2BuildDto +import com.intellij.idea.plugin.hybris.tools.ccv2.dto.CCv2DataBackupDto import com.intellij.idea.plugin.hybris.tools.ccv2.dto.CCv2EnvironmentDto import com.intellij.idea.plugin.hybris.tools.ccv2.dto.CCv2ServiceDto import com.intellij.idea.plugin.hybris.ui.Dsl @@ -57,11 +58,14 @@ class CCv2EnvironmentDetailsView( private val showBuild = AtomicBooleanProperty(environment.deployedBuild != null) private val showServices = AtomicBooleanProperty(environment.services != null) + private val showDataBackups = AtomicBooleanProperty(environment.dataBackups != null) private val buildPanel = JBPanel>(GridBagLayout()) .also { border = JBUI.Borders.empty() } private val servicesPanel = JBPanel>(GridBagLayout()) .also { border = JBUI.Borders.empty() } + private val dataBackupsPanel = JBPanel>(GridBagLayout()) + .also { border = JBUI.Borders.empty() } private var rootPanel = rootPanel() override fun dispose() { @@ -105,6 +109,7 @@ class CCv2EnvironmentDetailsView( initBuildPanel() initServicesPanel() + initDataBackupsPanel() } private fun initBuildPanel() { @@ -161,6 +166,33 @@ class CCv2EnvironmentDetailsView( } } + private fun initDataBackupsPanel() { + val dataBackups = environment.dataBackups + if (dataBackups == null) { + CCv2Service.getInstance(project).fetchEnvironmentDataBackups(subscription, environment, + { + showDataBackups.set(false) + environment.dataBackups = null + dataBackupsPanel.removeAll() + }, + { + environment.dataBackups = it + + invokeLater { + showDataBackups.set(it != null) + + if (it != null) { + dataBackupsPanel.add(dataBackupsPanel(it)) + } + } + } + ) + } else { + dataBackupsPanel.removeAll() + dataBackupsPanel.add(dataBackupsPanel(dataBackups)) + } + } + private fun buildPanel(build: CCv2BuildDto) = panel { row { panel { @@ -249,6 +281,70 @@ class CCv2EnvironmentDetailsView( } } + private fun dataBackupsPanel(dataBackups: Collection) = panel { + dataBackups.forEach { dataBackup -> + row { + panel { + row { + contextHelp(dataBackup.description) + label(dataBackup.name) + .comment(dataBackup.dataBackupCode) + } + } + .gap(RightGap.COLUMNS) + + panel { + row { + icon(HybrisIcons.CCV2_DATA_BACKUP_CREATED_BY) + .gap(RightGap.SMALL) + label(dataBackup.createdBy) + .comment("Created by") + } + } + .gap(RightGap.COLUMNS) + + panel { + row { + label(dataBackup.status) + .comment("Status") + } + } + .gap(RightGap.COLUMNS) + + panel { + row { + label(dataBackup.buildCode) + .comment("Build code") + } + } + .gap(RightGap.COLUMNS) + + panel { + row { + label(dataBackup.createdTimestampFormatted) + .comment("Created") + } + } + .gap(RightGap.COLUMNS) + + panel { + ccv2StatusYesNo(dataBackup.canBeRestored, "Can be restored") + } + .gap(RightGap.SMALL) + + panel { + ccv2StatusYesNo(dataBackup.canBeCanceled, "Can be canceled") + } + .gap(RightGap.SMALL) + + panel { + ccv2StatusYesNo(dataBackup.canBeDeleted, "Can be deleted") + } + } + .layout(RowLayout.PARENT_GRID) + } + } + private fun rootPanel() = panel { indent { row { @@ -455,6 +551,21 @@ class CCv2EnvironmentDetailsView( }.align(Align.CENTER) }.visibleIf(showServices.not()) }.expanded = true + + collapsibleGroup("Data Backups") { + row { + cell(dataBackupsPanel) + }.visibleIf(showDataBackups) + + row { + panel { + row { + icon(AnimatedIcon.Default.INSTANCE) + label("Retrieving data backups...") + } + }.align(Align.CENTER) + }.visibleIf(showDataBackups.not()) + }.expanded = true } } .let { Dsl.scrollPanel(it) } diff --git a/src/com/intellij/idea/plugin/hybris/toolwindow/ccv2/views/CCv2UiElements.kt b/src/com/intellij/idea/plugin/hybris/toolwindow/ccv2/views/CCv2UiElements.kt index 4e489d676..b291bd13b 100644 --- a/src/com/intellij/idea/plugin/hybris/toolwindow/ccv2/views/CCv2UiElements.kt +++ b/src/com/intellij/idea/plugin/hybris/toolwindow/ccv2/views/CCv2UiElements.kt @@ -49,6 +49,27 @@ fun Panel.ccv2ServiceStatusRow(service: CCv2ServiceDto) { } } +fun Panel.ccv2StatusYesNo(status: Boolean, comment: String) { + row { + val statusLabel = when(status) { + false -> label("No").also { + with(it.component) { + foreground = JBColor.namedColor("hybris.ccv2.status.no", 0xDB5860, 0xC75450) + } + } + + true -> label("Yes").also { + with(it.component) { + foreground = JBColor.namedColor("hybris.ccv2.status.yes", 0x59A869, 0x499C54) + } + } + } + + statusLabel + .comment(comment) + } +} + fun Panel.ccv2ServiceReplicasRow(service: CCv2ServiceDto) { row { val replicas = if (service.desiredReplicas != null && service.availableReplicas != null)