diff --git a/PluginsAndFeatures/azure-toolkit-for-rider/.idea/misc.xml b/PluginsAndFeatures/azure-toolkit-for-rider/.idea/misc.xml
index f3cfb80af4..96aa33fce9 100644
--- a/PluginsAndFeatures/azure-toolkit-for-rider/.idea/misc.xml
+++ b/PluginsAndFeatures/azure-toolkit-for-rider/.idea/misc.xml
@@ -19,7 +19,7 @@
-
+
diff --git a/PluginsAndFeatures/azure-toolkit-for-rider/azure-intellij-plugin-appservice-dotnet/src/main/kotlin/com/microsoft/azure/toolkit/intellij/appservice/webapp/DotNetRuntime.kt b/PluginsAndFeatures/azure-toolkit-for-rider/azure-intellij-plugin-appservice-dotnet/src/main/kotlin/com/microsoft/azure/toolkit/intellij/appservice/DotNetRuntime.kt
similarity index 74%
rename from PluginsAndFeatures/azure-toolkit-for-rider/azure-intellij-plugin-appservice-dotnet/src/main/kotlin/com/microsoft/azure/toolkit/intellij/appservice/webapp/DotNetRuntime.kt
rename to PluginsAndFeatures/azure-toolkit-for-rider/azure-intellij-plugin-appservice-dotnet/src/main/kotlin/com/microsoft/azure/toolkit/intellij/appservice/DotNetRuntime.kt
index 8d2832a41e..20f7665689 100644
--- a/PluginsAndFeatures/azure-toolkit-for-rider/azure-intellij-plugin-appservice-dotnet/src/main/kotlin/com/microsoft/azure/toolkit/intellij/appservice/webapp/DotNetRuntime.kt
+++ b/PluginsAndFeatures/azure-toolkit-for-rider/azure-intellij-plugin-appservice-dotnet/src/main/kotlin/com/microsoft/azure/toolkit/intellij/appservice/DotNetRuntime.kt
@@ -2,8 +2,9 @@
* Copyright 2018-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the MIT license.
*/
-package com.microsoft.azure.toolkit.intellij.appservice.webapp
+package com.microsoft.azure.toolkit.intellij.appservice
+import com.azure.resourcemanager.appservice.models.FunctionRuntimeStack
import com.azure.resourcemanager.appservice.models.NetFrameworkVersion
import com.azure.resourcemanager.appservice.models.RuntimeStack
import com.microsoft.azure.toolkit.lib.appservice.model.OperatingSystem
@@ -12,5 +13,6 @@ data class DotNetRuntime(
val operatingSystem: OperatingSystem,
val stack: RuntimeStack?,
val frameworkVersion: NetFrameworkVersion?,
+ val functionStack: FunctionRuntimeStack?,
val isDocker: Boolean
)
diff --git a/PluginsAndFeatures/azure-toolkit-for-rider/azure-intellij-plugin-appservice-dotnet/src/main/kotlin/com/microsoft/azure/toolkit/intellij/appservice/webapp/DotNetRuntimeConfig.kt b/PluginsAndFeatures/azure-toolkit-for-rider/azure-intellij-plugin-appservice-dotnet/src/main/kotlin/com/microsoft/azure/toolkit/intellij/appservice/DotNetRuntimeConfig.kt
similarity index 73%
rename from PluginsAndFeatures/azure-toolkit-for-rider/azure-intellij-plugin-appservice-dotnet/src/main/kotlin/com/microsoft/azure/toolkit/intellij/appservice/webapp/DotNetRuntimeConfig.kt
rename to PluginsAndFeatures/azure-toolkit-for-rider/azure-intellij-plugin-appservice-dotnet/src/main/kotlin/com/microsoft/azure/toolkit/intellij/appservice/DotNetRuntimeConfig.kt
index 7a9b75bf07..be2b1e2195 100644
--- a/PluginsAndFeatures/azure-toolkit-for-rider/azure-intellij-plugin-appservice-dotnet/src/main/kotlin/com/microsoft/azure/toolkit/intellij/appservice/webapp/DotNetRuntimeConfig.kt
+++ b/PluginsAndFeatures/azure-toolkit-for-rider/azure-intellij-plugin-appservice-dotnet/src/main/kotlin/com/microsoft/azure/toolkit/intellij/appservice/DotNetRuntimeConfig.kt
@@ -2,8 +2,9 @@
* Copyright 2018-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the MIT license.
*/
-package com.microsoft.azure.toolkit.intellij.appservice.webapp
+package com.microsoft.azure.toolkit.intellij.appservice
+import com.azure.resourcemanager.appservice.models.FunctionRuntimeStack
import com.azure.resourcemanager.appservice.models.NetFrameworkVersion
import com.azure.resourcemanager.appservice.models.RuntimeStack
import com.microsoft.azure.toolkit.lib.appservice.config.RuntimeConfig
@@ -12,4 +13,5 @@ class DotNetRuntimeConfig: RuntimeConfig() {
var isDocker: Boolean = false
var stack: RuntimeStack? = null
var frameworkVersion: NetFrameworkVersion? = null
+ var functionStack: FunctionRuntimeStack? = null
}
\ No newline at end of file
diff --git a/PluginsAndFeatures/azure-toolkit-for-rider/azure-intellij-plugin-appservice-dotnet/src/main/kotlin/com/microsoft/azure/toolkit/intellij/appservice/webapp/DotNetRuntimeExtensions.kt b/PluginsAndFeatures/azure-toolkit-for-rider/azure-intellij-plugin-appservice-dotnet/src/main/kotlin/com/microsoft/azure/toolkit/intellij/appservice/DotNetRuntimeExtensions.kt
similarity index 87%
rename from PluginsAndFeatures/azure-toolkit-for-rider/azure-intellij-plugin-appservice-dotnet/src/main/kotlin/com/microsoft/azure/toolkit/intellij/appservice/webapp/DotNetRuntimeExtensions.kt
rename to PluginsAndFeatures/azure-toolkit-for-rider/azure-intellij-plugin-appservice-dotnet/src/main/kotlin/com/microsoft/azure/toolkit/intellij/appservice/DotNetRuntimeExtensions.kt
index 1467cfe116..9748265935 100644
--- a/PluginsAndFeatures/azure-toolkit-for-rider/azure-intellij-plugin-appservice-dotnet/src/main/kotlin/com/microsoft/azure/toolkit/intellij/appservice/webapp/DotNetRuntimeExtensions.kt
+++ b/PluginsAndFeatures/azure-toolkit-for-rider/azure-intellij-plugin-appservice-dotnet/src/main/kotlin/com/microsoft/azure/toolkit/intellij/appservice/DotNetRuntimeExtensions.kt
@@ -2,7 +2,7 @@
* Copyright 2018-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the MIT license.
*/
-package com.microsoft.azure.toolkit.intellij.appservice.webapp
+package com.microsoft.azure.toolkit.intellij.appservice
import com.azure.resourcemanager.appservice.models.OperatingSystem
import com.azure.resourcemanager.appservice.models.RuntimeStack
@@ -18,6 +18,7 @@ fun WebAppBase.getDotNetRuntime(): DotNetRuntime {
com.microsoft.azure.toolkit.lib.appservice.model.OperatingSystem.LINUX,
null,
null,
+ null,
true
)
} else {
@@ -27,6 +28,7 @@ fun WebAppBase.getDotNetRuntime(): DotNetRuntime {
com.microsoft.azure.toolkit.lib.appservice.model.OperatingSystem.LINUX,
RuntimeStack(stack, version),
null,
+ null,
false
)
}
@@ -35,9 +37,10 @@ fun WebAppBase.getDotNetRuntime(): DotNetRuntime {
com.microsoft.azure.toolkit.lib.appservice.model.OperatingSystem.WINDOWS,
null,
netFrameworkVersion(),
+ null,
false
)
}
}
-fun AppServiceAppBase<*, *, *>.getDotNetRuntime() = getRemote()?.getDotNetRuntime()
\ No newline at end of file
+fun AppServiceAppBase<*, *, *>.getDotNetRuntime() = remote?.getDotNetRuntime()
\ No newline at end of file
diff --git a/PluginsAndFeatures/azure-toolkit-for-rider/azure-intellij-plugin-appservice-dotnet/src/main/kotlin/com/microsoft/azure/toolkit/intellij/appservice/functionapp/CreateOrUpdateDotNetFunctionAppTask.kt b/PluginsAndFeatures/azure-toolkit-for-rider/azure-intellij-plugin-appservice-dotnet/src/main/kotlin/com/microsoft/azure/toolkit/intellij/appservice/functionapp/CreateOrUpdateDotNetFunctionAppTask.kt
new file mode 100644
index 0000000000..c5ac1b878b
--- /dev/null
+++ b/PluginsAndFeatures/azure-toolkit-for-rider/azure-intellij-plugin-appservice-dotnet/src/main/kotlin/com/microsoft/azure/toolkit/intellij/appservice/functionapp/CreateOrUpdateDotNetFunctionAppTask.kt
@@ -0,0 +1,269 @@
+/*
+ * Copyright 2018-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the MIT license.
+ */
+
+package com.microsoft.azure.toolkit.intellij.appservice.functionapp
+
+import com.azure.resourcemanager.resources.fluentcore.utils.ResourceManagerUtils
+import com.microsoft.azure.toolkit.intellij.appservice.DotNetRuntime
+import com.microsoft.azure.toolkit.intellij.appservice.DotNetRuntimeConfig
+import com.microsoft.azure.toolkit.lib.Azure
+import com.microsoft.azure.toolkit.lib.appservice.AzureAppService
+import com.microsoft.azure.toolkit.lib.appservice.function.*
+import com.microsoft.azure.toolkit.lib.appservice.model.DockerConfiguration
+import com.microsoft.azure.toolkit.lib.appservice.plan.AppServicePlan
+import com.microsoft.azure.toolkit.lib.appservice.plan.AppServicePlanDraft
+import com.microsoft.azure.toolkit.lib.common.exception.AzureToolkitRuntimeException
+import com.microsoft.azure.toolkit.lib.common.messager.AzureMessager
+import com.microsoft.azure.toolkit.lib.common.model.Region
+import com.microsoft.azure.toolkit.lib.common.task.AzureTask
+import com.microsoft.azure.toolkit.lib.resource.ResourceGroup
+import com.microsoft.azure.toolkit.lib.resource.task.CreateResourceGroupTask
+import com.microsoft.azure.toolkit.lib.storage.AzureStorageAccount
+import com.microsoft.azure.toolkit.lib.storage.StorageAccount
+import com.microsoft.azure.toolkit.lib.storage.StorageAccountDraft
+import com.microsoft.azure.toolkit.lib.storage.model.Kind
+import com.microsoft.azure.toolkit.lib.storage.model.Redundancy
+import org.apache.commons.lang3.StringUtils
+import java.util.concurrent.Callable
+
+class CreateOrUpdateDotNetFunctionAppTask(private val config: DotNetFunctionAppConfig) :
+ AzureTask>() {
+ companion object {
+ private const val FUNCTION_APP_NAME_PATTERN = "[^a-zA-Z0-9]"
+ }
+
+ private val functionAppRegex = Regex(FUNCTION_APP_NAME_PATTERN)
+
+ private val subTasks: MutableList> = mutableListOf()
+
+ private lateinit var appServicePlan: AppServicePlan
+ private lateinit var storageAccount: StorageAccount
+ private lateinit var functionApp: FunctionAppBase<*, *, *>
+
+ init {
+ initTasks()
+ }
+
+ private fun initTasks() {
+ val appDraft = Azure.az(AzureFunctions::class.java)
+ .functionApps(config.subscriptionId())
+ .updateOrCreate(config.appName(), config.resourceGroup())
+ .toDotNetFunctionAppDraft()
+
+ registerSubTask(getResourceGroupTask()) {}
+ registerSubTask(getServicePlanTask()) { appServicePlan = it }
+ if (appDraft.isDraftForCreating) {
+ registerSubTask(getStorageAccountTask()) { storageAccount = it }
+ }
+
+ if (config.deploymentSlotName().isNullOrEmpty()) {
+ val functionTask =
+ if (appDraft.exists()) getUpdateFunctionAppTask(appDraft)
+ else getCreateFunctionAppTask(appDraft)
+ registerSubTask(functionTask) { functionApp = it }
+ } else {
+ val slotDraft = getFunctionDeploymentSlot(appDraft)
+ val slotTask =
+ if (slotDraft.exists()) getUpdateFunctionSlotTask(slotDraft)
+ else getCreateFunctionSlotTask(slotDraft)
+ registerSubTask(slotTask) { functionApp = it }
+ }
+ }
+
+ private fun FunctionAppDraft.toDotNetFunctionAppDraft(): DotNetFunctionAppDraft {
+ val draftOrigin = origin
+ val draft =
+ if (draftOrigin != null) DotNetFunctionAppDraft(draftOrigin)
+ else DotNetFunctionAppDraft(name, resourceGroupName, module as FunctionAppModule)
+
+ return draft
+ }
+
+ private fun FunctionAppDeploymentSlotDraft.toDotNetFunctionAppDeploymentSlotDraft(): DotNetFunctionAppDeploymentSlotDraft {
+ val draftOrigin = origin
+ val draft =
+ if (draftOrigin != null) DotNetFunctionAppDeploymentSlotDraft(draftOrigin)
+ else DotNetFunctionAppDeploymentSlotDraft(name, module as FunctionAppDeploymentSlotModule)
+
+ return draft
+ }
+
+ private fun getResourceGroupTask(): AzureTask =
+ CreateResourceGroupTask(config.subscriptionId(), config.resourceGroup(), config.region())
+
+ private fun getServicePlanTask(): AzureTask? {
+ if (!config.deploymentSlotName().isNullOrEmpty()) {
+ AzureMessager.getMessager().info("Skip update app service plan for deployment slot")
+ return null
+ }
+
+ return AzureTask(Callable {
+ val planConfig = config.servicePlanConfig
+ val draft = Azure.az(AzureAppService::class.java)
+ .plans(planConfig.subscriptionId)
+ .updateOrCreate(planConfig.name, planConfig.resourceGroupName)
+ draft.operatingSystem = planConfig.os
+ draft.region = planConfig.region
+ draft.pricingTier = planConfig.pricingTier
+ return@Callable draft.commit()
+ })
+ }
+
+ private fun getStorageAccountTask(): AzureTask =
+ AzureTask(Callable {
+ val storageAccountName = config.storageAccountName() ?: getDefaultStorageAccountName(config.appName())
+ val storageResourceGroup = config.storageAccountResourceGroup() ?: config.resourceGroup()
+ val accounts = Azure.az(AzureStorageAccount::class.java).accounts(config.subscriptionId())
+ val existingAccount = accounts.get(storageAccountName, storageResourceGroup)
+ if (existingAccount != null && existingAccount.exists()) {
+ return@Callable existingAccount
+ }
+
+ val draft = accounts.create(storageAccountName, storageResourceGroup)
+ draft.setRegion(getNonStageRegion(config.region()))
+ draft.setKind(Kind.STORAGE_V2)
+ draft.setRedundancy(Redundancy.STANDARD_LRS)
+ return@Callable draft.commit()
+ })
+
+ private fun getDefaultStorageAccountName(functionAppName: String): String {
+ val context = ResourceManagerUtils.InternalRuntimeContext()
+ return context.randomResourceName(functionAppName.replace(functionAppRegex, ""), 20)
+ }
+
+ private fun getNonStageRegion(region: Region): Region {
+ val regionName = region.name
+ if (!regionName.contains("stage", true)) {
+ return region
+ }
+
+ return regionName.let {
+ var name = StringUtils.removeIgnoreCase(it, "(stage)")
+ name = StringUtils.removeIgnoreCase(name, "stage")
+ name = name.trim()
+ return@let Region.fromName(name)
+ }
+ }
+
+ private fun getCreateFunctionAppTask(draft: DotNetFunctionAppDraft): AzureTask {
+ val title = "Create new app(${config.appName()}) on subscription(${config.subscriptionId()})"
+ return AzureTask(title, Callable {
+ draft.appServicePlan = appServicePlan
+ draft.dotNetRuntime = getRuntime(config.dotnetRuntime)
+ draft.dockerConfiguration = getDockerConfiguration(config.dotnetRuntime)
+ draft.appSettings = config.appSettings()
+ draft.diagnosticConfig = config.diagnosticConfig()
+ draft.flexConsumptionConfiguration = config.flexConsumptionConfiguration()
+ draft.storageAccount = storageAccount
+
+ val result = draft.createIfNotExist()
+ Thread.sleep((10 * 1000).toLong())
+ result
+ })
+ }
+
+ private fun getUpdateFunctionAppTask(draft: DotNetFunctionAppDraft): AzureTask {
+ val title = "Update function app(${config.appName()})"
+ return AzureTask(title, Callable {
+ draft.appServicePlan = appServicePlan
+ draft.dotNetRuntime = getRuntime(config.dotnetRuntime)
+ draft.dockerConfiguration = getDockerConfiguration(config.dotnetRuntime)
+ val appSettingsToRemove = getAppSettingsToRemove(draft.appSettings ?: emptyMap(), config.appSettings())
+ draft.appSettings = config.appSettings()
+ draft.appSettingsToRemove = appSettingsToRemove
+ draft.diagnosticConfig = config.diagnosticConfig()
+ draft.flexConsumptionConfiguration = config.flexConsumptionConfiguration()
+ draft.storageAccount = storageAccount
+
+ draft.updateIfExist()
+ })
+ }
+
+ private fun getFunctionDeploymentSlot(functionApp: FunctionApp): DotNetFunctionAppDeploymentSlotDraft {
+ if (!functionApp.exists()) {
+ throw AzureToolkitRuntimeException("The Function App does not exist. Please make sure the Function App name is correct")
+ }
+ if (requireNotNull(functionApp.appServicePlan).pricingTier.isFlexConsumption) {
+ throw AzureToolkitRuntimeException("Deployment slot is not supported for function app with consumption plan")
+ }
+
+ return functionApp
+ .slots()
+ .updateOrCreate(config.deploymentSlotName(), config.resourceGroup())
+ .toDotNetFunctionAppDeploymentSlotDraft()
+ }
+
+ private fun getCreateFunctionSlotTask(draft: DotNetFunctionAppDeploymentSlotDraft): AzureTask {
+ val title = "Create new slot(${config.deploymentSlotName()}) on function app (${config.appName()})"
+ return AzureTask(title, Callable {
+ draft.dotNetRuntime = getRuntime(config.dotnetRuntime)
+ draft.dockerConfiguration = getDockerConfiguration(config.dotnetRuntime)
+ draft.diagnosticConfig = config.diagnosticConfig()
+ draft.configurationSource = config.deploymentSlotConfigurationSource()
+ draft.appSettings = config.appSettings()
+
+ draft.commit()
+ })
+ }
+
+ private fun getUpdateFunctionSlotTask(draft: DotNetFunctionAppDeploymentSlotDraft): AzureTask {
+ val title = "Update function deployment slot(${config.deploymentSlotName()})"
+ return AzureTask(title, Callable {
+ draft.dotNetRuntime = getRuntime(config.dotnetRuntime)
+ draft.dockerConfiguration = getDockerConfiguration(config.dotnetRuntime)
+ draft.diagnosticConfig = config.diagnosticConfig()
+ val appSettingsToRemove = getAppSettingsToRemove(draft.appSettings ?: emptyMap(), config.appSettings())
+ draft.appSettings = config.appSettings()
+ draft.appSettingsToRemove = appSettingsToRemove
+
+ draft.commit()
+ })
+ }
+
+ private fun getRuntime(runtimeConfig: DotNetRuntimeConfig?): DotNetRuntime? {
+ if (runtimeConfig == null) return null
+ if (runtimeConfig.isDocker) return null
+
+ return DotNetRuntime(
+ runtimeConfig.os(),
+ runtimeConfig.stack,
+ runtimeConfig.frameworkVersion,
+ runtimeConfig.functionStack,
+ false
+ )
+ }
+
+ private fun getDockerConfiguration(runtimeConfig: DotNetRuntimeConfig?): DockerConfiguration? {
+ if (runtimeConfig == null || !runtimeConfig.isDocker) return null
+
+ return DockerConfiguration.builder()
+ .userName(runtimeConfig.username())
+ .password(runtimeConfig.password())
+ .registryUrl(runtimeConfig.registryUrl())
+ .image(runtimeConfig.image())
+ .startUpCommand(runtimeConfig.startUpCommand())
+ .build()
+ }
+
+ private fun getAppSettingsToRemove(targetSettings: Map, newSettings: Map) =
+ targetSettings.keys.filter { !newSettings.containsKey(it) }.toSet()
+
+ private fun registerSubTask(task: AzureTask?, consumer: (result: T) -> Unit) {
+ if (task != null) {
+ subTasks.add(AzureTask(Callable {
+ val result = task.body.call()
+ consumer(result)
+ return@Callable result
+ }))
+ }
+ }
+
+ override fun doExecute(): FunctionAppBase<*, *, *> {
+ for (task in subTasks) {
+ task.body.call()
+ }
+
+ return functionApp
+ }
+}
\ No newline at end of file
diff --git a/PluginsAndFeatures/azure-toolkit-for-rider/azure-intellij-plugin-appservice-dotnet/src/main/kotlin/com/microsoft/azure/toolkit/intellij/appservice/functionapp/DotNetFunctionAppConfig.kt b/PluginsAndFeatures/azure-toolkit-for-rider/azure-intellij-plugin-appservice-dotnet/src/main/kotlin/com/microsoft/azure/toolkit/intellij/appservice/functionapp/DotNetFunctionAppConfig.kt
new file mode 100644
index 0000000000..78da84f214
--- /dev/null
+++ b/PluginsAndFeatures/azure-toolkit-for-rider/azure-intellij-plugin-appservice-dotnet/src/main/kotlin/com/microsoft/azure/toolkit/intellij/appservice/functionapp/DotNetFunctionAppConfig.kt
@@ -0,0 +1,12 @@
+/*
+ * Copyright 2018-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the MIT license.
+ */
+
+package com.microsoft.azure.toolkit.intellij.appservice.functionapp
+
+import com.microsoft.azure.toolkit.intellij.appservice.DotNetRuntimeConfig
+import com.microsoft.azure.toolkit.lib.appservice.config.FunctionAppConfig
+
+class DotNetFunctionAppConfig : FunctionAppConfig() {
+ var dotnetRuntime: DotNetRuntimeConfig? = null
+}
\ No newline at end of file
diff --git a/PluginsAndFeatures/azure-toolkit-for-rider/azure-intellij-plugin-appservice-dotnet/src/main/kotlin/com/microsoft/azure/toolkit/intellij/appservice/functionapp/DotNetFunctionAppDeploymentSlotDraft.kt b/PluginsAndFeatures/azure-toolkit-for-rider/azure-intellij-plugin-appservice-dotnet/src/main/kotlin/com/microsoft/azure/toolkit/intellij/appservice/functionapp/DotNetFunctionAppDeploymentSlotDraft.kt
new file mode 100644
index 0000000000..51626321e8
--- /dev/null
+++ b/PluginsAndFeatures/azure-toolkit-for-rider/azure-intellij-plugin-appservice-dotnet/src/main/kotlin/com/microsoft/azure/toolkit/intellij/appservice/functionapp/DotNetFunctionAppDeploymentSlotDraft.kt
@@ -0,0 +1,299 @@
+/*
+ * Copyright 2018-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the MIT license.
+ */
+
+package com.microsoft.azure.toolkit.intellij.appservice.functionapp
+
+import com.azure.core.management.exception.ManagementException
+import com.azure.core.util.Context
+import com.azure.resourcemanager.appservice.fluent.models.SitePatchResourceInner
+import com.azure.resourcemanager.appservice.models.DeploymentSlotBase
+import com.azure.resourcemanager.appservice.models.FunctionApp
+import com.azure.resourcemanager.appservice.models.FunctionDeploymentSlot
+import com.azure.resourcemanager.appservice.models.WebAppBase
+import com.microsoft.azure.toolkit.intellij.appservice.DotNetRuntime
+import com.microsoft.azure.toolkit.intellij.appservice.getDotNetRuntime
+import com.microsoft.azure.toolkit.lib.appservice.function.FunctionAppDeploymentSlot
+import com.microsoft.azure.toolkit.lib.appservice.function.FunctionAppDeploymentSlotModule
+import com.microsoft.azure.toolkit.lib.appservice.model.DiagnosticConfig
+import com.microsoft.azure.toolkit.lib.appservice.model.DockerConfiguration
+import com.microsoft.azure.toolkit.lib.appservice.model.FlexConsumptionConfiguration
+import com.microsoft.azure.toolkit.lib.appservice.model.OperatingSystem
+import com.microsoft.azure.toolkit.lib.appservice.utils.AppServiceUtils
+import com.microsoft.azure.toolkit.lib.appservice.utils.Utils
+import com.microsoft.azure.toolkit.lib.common.exception.AzureToolkitRuntimeException
+import com.microsoft.azure.toolkit.lib.common.messager.AzureMessager
+import com.microsoft.azure.toolkit.lib.common.model.AzResource
+
+class DotNetFunctionAppDeploymentSlotDraft : FunctionAppDeploymentSlot,
+ AzResource.Draft {
+ companion object {
+ const val CONFIGURATION_SOURCE_PARENT = "parent"
+ const val CONFIGURATION_SOURCE_NEW = "new"
+ }
+
+ constructor(name: String, module: FunctionAppDeploymentSlotModule) :
+ super(name, module) {
+ origin = null
+ }
+
+ constructor(origin: FunctionAppDeploymentSlot) : super(origin) {
+ this.origin = origin
+ }
+
+ private val origin: FunctionAppDeploymentSlot?
+
+ private var config: Config? = null
+
+ private val lock = Any()
+
+ override fun getOrigin() = origin
+
+ override fun reset() {
+ config = null
+ }
+
+ private fun ensureConfig(): Config {
+ synchronized(lock) {
+ val localConfig = config ?: Config()
+ config = localConfig
+ return localConfig
+ }
+ }
+
+ override fun isModified(): Boolean {
+ val localConfig = config
+ val notModified = localConfig == null ||
+ ((localConfig.runtime == null || localConfig.runtime == remote?.getDotNetRuntime()) &&
+ localConfig.dockerConfiguration == null &&
+ (localConfig.diagnosticConfig == null || localConfig.diagnosticConfig == super.getDiagnosticConfig()) &&
+ localConfig.configurationSource.isNullOrEmpty() &&
+ (localConfig.appSettings == null || localConfig.appSettings == super.getAppSettings()) &&
+ localConfig.appSettingsToRemove.isNullOrEmpty())
+
+ return !notModified
+ }
+
+ override fun createResourceInAzure(): FunctionDeploymentSlot {
+ val functionApp = requireNotNull(parent.remote)
+
+ val newAppSettings = appSettings
+ val newDiagnosticConfig = diagnosticConfig
+ val newConfigurationSource = configurationSource
+ val newFlexConsumptionConfiguration = flexConsumptionConfiguration
+ val source =
+ if (newConfigurationSource.isNullOrEmpty()) CONFIGURATION_SOURCE_PARENT else newConfigurationSource.lowercase()
+
+ val blank = functionApp.deploymentSlots().define(name)
+ val withCreate =
+ when (source) {
+ CONFIGURATION_SOURCE_NEW -> blank.withBrandNewConfiguration()
+ CONFIGURATION_SOURCE_PARENT -> blank.withConfigurationFromParent()
+ else -> {
+ try {
+ val sourceSlot = functionApp.deploymentSlots().getByName(newConfigurationSource)
+ requireNotNull(sourceSlot) { "Target slot configuration source does not exists in current app" }
+ blank.withConfigurationFromDeploymentSlot(sourceSlot)
+ } catch (e: ManagementException) {
+ throw AzureToolkitRuntimeException("Failed to get configuration source slot", e)
+ }
+ }
+ }
+
+ if (!newAppSettings.isNullOrEmpty())
+ withCreate.withAppSettings(newAppSettings)
+ if (newDiagnosticConfig != null)
+ AppServiceUtils.defineDiagnosticConfigurationForWebAppBase(withCreate, newDiagnosticConfig)
+ val updateFlexConsumptionConfiguration =
+ newFlexConsumptionConfiguration != null &&
+ parent.appServicePlan?.pricingTier?.isFlexConsumption == true
+ if (updateFlexConsumptionConfiguration) {
+ (withCreate as? FunctionApp)?.innerModel()
+ ?.withContainerSize(requireNotNull(newFlexConsumptionConfiguration).instanceSize)
+ }
+
+ val messager = AzureMessager.getMessager()
+ messager.info("Start creating Function App deployment slot ($name)...")
+
+ var slot = withCreate.create()
+ if (updateFlexConsumptionConfiguration) {
+ updateFlexConsumptionConfiguration(slot, requireNotNull(newFlexConsumptionConfiguration))
+ }
+ ensureConfig().appSettings = null
+ ensureConfig().diagnosticConfig = null
+ slot = updateRuntime(slot)
+
+ messager.success("Function App deployment slot ({0}) is successfully created")
+
+ return slot
+ }
+
+ private fun updateRuntime(slot: FunctionDeploymentSlot): FunctionDeploymentSlot {
+ val dotnetRuntime = dotNetRuntime
+ val isRuntimeModified =
+ (dotnetRuntime != null && dotnetRuntime != parent.getDotNetRuntime()) || dockerConfiguration != null
+ return if (isRuntimeModified)
+ updateResourceInAzure(slot)
+ else
+ slot
+ }
+
+ override fun updateResourceInAzure(remote: FunctionDeploymentSlot): FunctionDeploymentSlot {
+ val newRuntime = ensureConfig().runtime
+ val newDockerConfig = ensureConfig().dockerConfiguration
+ val newDiagnosticConfig = ensureConfig().diagnosticConfig
+ val newFlexConsumptionConfiguration = ensureConfig().flexConsumptionConfiguration
+ val settingsToAdd = ensureConfig().appSettings?.toMutableMap()
+
+ val oldRuntime = remote.getDotNetRuntime()
+ val oldDiagnosticConfig = super.getDiagnosticConfig()
+ val oldFlexConsumptionConfiguration = super.getFlexConsumptionConfiguration()
+ val oldAppSettings = Utils.normalizeAppSettings(remote.appSettings)
+
+ if (oldAppSettings != null && settingsToAdd != null) {
+ settingsToAdd.entries.removeAll(oldAppSettings.entries)
+ }
+ val settingsToRemove = ensureConfig().appSettingsToRemove
+ ?.filter { oldAppSettings.containsKey(it) }
+ ?.toSet()
+ ?: emptySet()
+
+ val runtimeModified = !oldRuntime.isDocker && newRuntime != null && newRuntime != oldRuntime
+ val dockerModified = oldRuntime.isDocker && newDockerConfig != null
+ val diagnosticModified = newDiagnosticConfig != null && newDiagnosticConfig != oldDiagnosticConfig
+ val flexConsumptionModified = parent.appServicePlan?.pricingTier?.isFlexConsumption == true &&
+ newFlexConsumptionConfiguration != null &&
+ newFlexConsumptionConfiguration != oldFlexConsumptionConfiguration
+ val appSettingsModified = !settingsToAdd.isNullOrEmpty() || settingsToRemove.isNotEmpty()
+ val isModified =
+ runtimeModified || dockerModified || diagnosticModified || flexConsumptionModified || appSettingsModified
+
+ var result = remote
+ if (isModified) {
+ val update = remote.update()
+
+ if (runtimeModified) newRuntime?.let { updateRuntime(update, it) }
+ if (dockerModified) newDockerConfig?.let { updateDockerConfiguration(update, it) }
+ if (diagnosticModified) newDiagnosticConfig?.let {
+ AppServiceUtils.updateDiagnosticConfigurationForWebAppBase(update, it)
+ }
+ settingsToAdd?.let { update.withAppSettings(it) }
+ settingsToRemove.let { if (settingsToRemove.isNotEmpty()) it.forEach { key -> update.withoutAppSetting(key) } }
+
+ val messager = AzureMessager.getMessager()
+ messager.info("Start updating Function App deployment slot (${remote.name()})...")
+
+ result = update.apply()
+
+ messager.success("Function app deployment slot (${remote.name()}) is successfully updated")
+ }
+
+ return result
+ }
+
+ private fun updateRuntime(update: DeploymentSlotBase.Update<*>, newRuntime: DotNetRuntime) {
+ val oldRuntime = (update as WebAppBase).getDotNetRuntime()
+ if (newRuntime.operatingSystem != oldRuntime.operatingSystem) {
+ throw AzureToolkitRuntimeException("Can not update the operation system for existing app service")
+ }
+
+ when (oldRuntime.operatingSystem) {
+ OperatingSystem.LINUX -> {
+ AzureMessager.getMessager().warning("Update runtime is not supported for Linux app service")
+ }
+
+ OperatingSystem.WINDOWS -> {
+ val functionStack = requireNotNull(newRuntime.functionStack) { "Unable to configure function runtime" }
+ update.withRuntime(functionStack.runtime())
+ .withRuntimeVersion(functionStack.version())
+ }
+
+ OperatingSystem.DOCKER -> return
+ }
+ }
+
+ private fun updateDockerConfiguration(update: DeploymentSlotBase.Update<*>, newConfig: DockerConfiguration) {
+ val draft =
+ if (newConfig.userName.isNullOrEmpty() && newConfig.password.isNullOrEmpty()) {
+ update.withPublicDockerHubImage(newConfig.image)
+ } else if (newConfig.registryUrl.isNullOrEmpty()) {
+ update.withPrivateDockerHubImage(newConfig.image)
+ .withCredentials(newConfig.userName, newConfig.password)
+ } else {
+ update.withPrivateRegistryImage(newConfig.image, newConfig.registryUrl)
+ .withCredentials(newConfig.userName, newConfig.password)
+ }
+ draft.withStartUpCommand(newConfig.startUpCommand)
+ }
+
+ private fun updateFlexConsumptionConfiguration(
+ slot: FunctionDeploymentSlot,
+ flexConfiguration: FlexConsumptionConfiguration
+ ) {
+ val name = "${slot.parent().name()}/slots/${slot.name()}"
+ val webApps = slot.manager().serviceClient().webApps
+ if (flexConfiguration.maximumInstances != null || flexConfiguration.alwaysReadyInstances != null) {
+ val configuration = webApps.getConfiguration(slot.resourceGroupName(), name)
+ if (flexConfiguration.maximumInstances != configuration.functionAppScaleLimit() ||
+ flexConfiguration.alwaysReadyInstances != configuration.minimumElasticInstanceCount()
+ ) {
+ configuration
+ .withFunctionAppScaleLimit(flexConfiguration.maximumInstances)
+ .withMinimumElasticInstanceCount(flexConfiguration.alwaysReadyInstances)
+ webApps.updateConfiguration(slot.resourceGroupName(), name, configuration)
+ }
+ }
+ if (slot.innerModel().containerSize() != flexConfiguration.instanceSize) {
+ val patch = SitePatchResourceInner()
+ .withContainerSize(flexConfiguration.instanceSize)
+ webApps
+ .updateWithResponse(slot.resourceGroupName(), name, patch, Context.NONE)
+ }
+ }
+
+ var dotNetRuntime: DotNetRuntime?
+ get() = config?.runtime ?: remote?.getDotNetRuntime()
+ set(value) {
+ ensureConfig().runtime = value
+ }
+ var dockerConfiguration: DockerConfiguration?
+ get() = config?.dockerConfiguration
+ set(value) {
+ ensureConfig().dockerConfiguration = value
+ }
+ var configurationSource: String?
+ get() = config?.configurationSource
+ set(value) {
+ ensureConfig().configurationSource = value
+ }
+ var appSettingsToRemove: Set?
+ get() = config?.appSettingsToRemove
+ set(value) {
+ ensureConfig().appSettingsToRemove = value
+ }
+
+ override fun getAppSettings() = config?.appSettings ?: super.getAppSettings()
+ fun setAppSettings(value: Map?) {
+ ensureConfig().appSettings = value
+ }
+
+ override fun getDiagnosticConfig() = config?.diagnosticConfig ?: super.getDiagnosticConfig()
+ fun setDiagnosticConfig(value: DiagnosticConfig?) {
+ ensureConfig().diagnosticConfig = value
+ }
+
+ override fun getFlexConsumptionConfiguration() = config?.flexConsumptionConfiguration ?: super.getFlexConsumptionConfiguration()
+ fun setFlexConsumptionConfiguration(value: FlexConsumptionConfiguration?) {
+ ensureConfig().flexConsumptionConfiguration = value
+ }
+
+ data class Config(
+ var runtime: DotNetRuntime? = null,
+ var dockerConfiguration: DockerConfiguration? = null,
+ var diagnosticConfig: DiagnosticConfig? = null,
+ var configurationSource: String? = null,
+ var appSettings: Map? = null,
+ var appSettingsToRemove: Set? = null,
+ var flexConsumptionConfiguration: FlexConsumptionConfiguration? = null
+ )
+}
\ No newline at end of file
diff --git a/PluginsAndFeatures/azure-toolkit-for-rider/azure-intellij-plugin-appservice-dotnet/src/main/kotlin/com/microsoft/azure/toolkit/intellij/appservice/functionapp/DotNetFunctionAppDraft.kt b/PluginsAndFeatures/azure-toolkit-for-rider/azure-intellij-plugin-appservice-dotnet/src/main/kotlin/com/microsoft/azure/toolkit/intellij/appservice/functionapp/DotNetFunctionAppDraft.kt
new file mode 100644
index 0000000000..7aa44e69d1
--- /dev/null
+++ b/PluginsAndFeatures/azure-toolkit-for-rider/azure-intellij-plugin-appservice-dotnet/src/main/kotlin/com/microsoft/azure/toolkit/intellij/appservice/functionapp/DotNetFunctionAppDraft.kt
@@ -0,0 +1,327 @@
+/*
+ * Copyright 2018-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the MIT license.
+ */
+
+package com.microsoft.azure.toolkit.intellij.appservice.functionapp
+
+import com.azure.resourcemanager.appservice.models.WebAppRuntimeStack
+import com.microsoft.azure.toolkit.intellij.appservice.DotNetRuntime
+import com.microsoft.azure.toolkit.intellij.appservice.getDotNetRuntime
+import com.microsoft.azure.toolkit.lib.appservice.function.FunctionApp
+import com.microsoft.azure.toolkit.lib.appservice.function.FunctionAppModule
+import com.microsoft.azure.toolkit.lib.appservice.model.DiagnosticConfig
+import com.microsoft.azure.toolkit.lib.appservice.model.DockerConfiguration
+import com.microsoft.azure.toolkit.lib.appservice.model.FlexConsumptionConfiguration
+import com.microsoft.azure.toolkit.lib.appservice.model.OperatingSystem
+import com.microsoft.azure.toolkit.lib.appservice.plan.AppServicePlan
+import com.microsoft.azure.toolkit.lib.appservice.utils.AppServiceUtils
+import com.microsoft.azure.toolkit.lib.common.bundle.AzureString
+import com.microsoft.azure.toolkit.lib.common.exception.AzureToolkitRuntimeException
+import com.microsoft.azure.toolkit.lib.common.messager.AzureMessager
+import com.microsoft.azure.toolkit.lib.common.model.AzResource
+import com.microsoft.azure.toolkit.lib.storage.StorageAccount
+
+class DotNetFunctionAppDraft : FunctionApp,
+ AzResource.Draft {
+ constructor(name: String, resourceGroupName: String, module: FunctionAppModule) :
+ super(name, resourceGroupName, module) {
+ origin = null
+ }
+
+ constructor(origin: FunctionApp) : super(origin) {
+ this.origin = origin
+ }
+
+ private val origin: FunctionApp?
+
+ private var config: Config? = null
+
+ private val lock = Any()
+
+ override fun getOrigin() = origin
+
+ override fun reset() {
+ config = null
+ }
+
+ private fun ensureConfig(): Config {
+ synchronized(lock) {
+ val localConfig = config ?: Config()
+ config = localConfig
+ return localConfig
+ }
+ }
+
+ override fun isModified(): Boolean {
+ val localConfig = config
+ val notModified = localConfig == null ||
+ ((localConfig.runtime == null || localConfig.runtime == remote?.getDotNetRuntime()) &&
+ (localConfig.plan == null || localConfig.plan == super.getAppServicePlan()) &&
+ localConfig.dockerConfiguration == null &&
+ localConfig.diagnosticConfig == null &&
+ (localConfig.appSettings == null || localConfig.appSettings == super.getAppSettings()) &&
+ localConfig.appSettingsToRemove.isNullOrEmpty())
+
+ return !notModified
+ }
+
+ override fun createResourceInAzure(): com.azure.resourcemanager.appservice.models.FunctionApp {
+ val newRuntime = requireNotNull(dotNetRuntime) { "'runtime' is required to create a Function App" }
+ val newPlan = requireNotNull(appServicePlan) { "'service plan' is required to create a Function App" }
+ val os = newRuntime.operatingSystem
+ if (os != newPlan.operatingSystem) {
+ throw AzureToolkitRuntimeException("Could not create $os app service in ${newPlan.operatingSystem} service plan")
+ }
+ val newAppSettings = appSettings
+ val newDiagnosticConfig = diagnosticConfig
+ val newFlexConsumptionConfiguration = flexConsumptionConfiguration
+ val newStorageAccount = storageAccount
+
+ val manager = requireNotNull(parent.remote)
+ val blank = manager.functionApps().define(name)
+ val withCreate = createFunctionApp(blank, os, newPlan, newRuntime)
+
+ if (!newAppSettings.isNullOrEmpty())
+ withCreate.withAppSettings(newAppSettings)
+ if (newStorageAccount != null)
+ withCreate.withExistingStorageAccount(newStorageAccount.remote)
+ if (newDiagnosticConfig != null)
+ AppServiceUtils.defineDiagnosticConfigurationForWebAppBase(withCreate, newDiagnosticConfig)
+
+ val updateFlexConsumptionConfiguration =
+ newFlexConsumptionConfiguration != null && newPlan.pricingTier.isFlexConsumption
+ if (updateFlexConsumptionConfiguration) {
+ withCreate.withContainerSize(newFlexConsumptionConfiguration!!.instanceSize)
+ withCreate.withWebAppAlwaysOn(false)
+ }
+
+ val messager = AzureMessager.getMessager()
+ messager.info(AzureString.format("Start creating Function App ({0})...", name))
+
+ val functionApp = withCreate.create()
+ if (updateFlexConsumptionConfiguration) {
+ updateFlexConsumptionConfiguration(functionApp, newFlexConsumptionConfiguration!!)
+ }
+
+ messager.success(AzureString.format("Function App ({0}) is successfully created", name))
+
+ return functionApp
+ }
+
+ private fun createFunctionApp(
+ blank: com.azure.resourcemanager.appservice.models.FunctionApp.DefinitionStages.Blank,
+ os: OperatingSystem,
+ plan: AppServicePlan,
+ runtime: DotNetRuntime
+ ) = when (os) {
+ OperatingSystem.LINUX -> {
+ val functionStack = requireNotNull(runtime.functionStack) { "Unable to configure function runtime" }
+ blank
+ .withExistingLinuxAppServicePlan(plan.remote)
+ .withExistingResourceGroup(resourceGroupName)
+ .withBuiltInImage(functionStack)
+ }
+
+ OperatingSystem.WINDOWS -> {
+ val functionStack = requireNotNull(runtime.functionStack) { "Unable to configure function runtime" }
+ blank
+ .withExistingAppServicePlan(plan.remote)
+ .withExistingResourceGroup(resourceGroupName)
+ .withRuntime(functionStack.runtime())
+ .withRuntimeVersion(functionStack.version())
+ }
+
+ OperatingSystem.DOCKER -> throw AzureToolkitRuntimeException("Unsupported operating system $os")
+ }
+
+ override fun updateResourceInAzure(remote: com.azure.resourcemanager.appservice.models.FunctionApp): com.azure.resourcemanager.appservice.models.FunctionApp {
+ if (origin == null)
+ throw AzureToolkitRuntimeException("Updating target is not specified")
+
+ val newPlan = ensureConfig().plan
+ val newRuntime = ensureConfig().runtime
+ val newDockerConfig = ensureConfig().dockerConfiguration
+ val newDiagnosticConfig = ensureConfig().diagnosticConfig
+ val newFlexConsumptionConfiguration = ensureConfig().flexConsumptionConfiguration
+ val storageAccount = storageAccount
+ val settingsToAdd = ensureConfig().appSettings?.toMutableMap()
+
+ val oldPlan = origin.appServicePlan
+ val oldRuntime = requireNotNull(origin.getDotNetRuntime())
+ val oldDiagnosticConfig = super.getDiagnosticConfig()
+ val oldFlexConsumptionConfiguration = origin.flexConsumptionConfiguration
+ val oldAppSettings = requireNotNull(origin.appSettings)
+
+ settingsToAdd?.entries?.removeAll(oldAppSettings.entries)
+ val settingsToRemove = ensureConfig().appSettingsToRemove
+ ?.filter { oldAppSettings.containsKey(it) }
+ ?.toSet()
+ ?: emptySet()
+
+ val planModified = newPlan != null && newPlan != oldPlan
+ val runtimeModified = !oldRuntime.isDocker && newRuntime != null && newRuntime != oldRuntime
+ val dockerModified = oldRuntime.isDocker && newDockerConfig != null
+ val diagnosticModified = newDiagnosticConfig != null && newDiagnosticConfig != oldDiagnosticConfig
+ val flexConsumptionModified = appServicePlan?.pricingTier?.isFlexConsumption == true &&
+ newFlexConsumptionConfiguration != null &&
+ !newFlexConsumptionConfiguration.isEmpty &&
+ newFlexConsumptionConfiguration != oldFlexConsumptionConfiguration
+ val isAppSettingsModified = !settingsToAdd.isNullOrEmpty() || settingsToRemove.isNotEmpty()
+ val isModified =
+ planModified || runtimeModified || dockerModified || diagnosticModified || flexConsumptionModified || isAppSettingsModified
+
+ var result = remote
+ if (isModified) {
+ val update = remote.update()
+
+ if (planModified) newPlan?.let { updateAppServicePlan(update, it) }
+ if (runtimeModified) newRuntime?.let { updateRuntime(update, it) }
+ if (dockerModified) newDockerConfig?.let { updateDockerConfiguration(update, it) }
+ if (diagnosticModified) newDiagnosticConfig?.let {
+ AppServiceUtils.updateDiagnosticConfigurationForWebAppBase(
+ update,
+ it
+ )
+ }
+ if (flexConsumptionModified) newFlexConsumptionConfiguration?.let { update.withContainerSize(it.instanceSize) }
+ storageAccount?.let { update.withExistingStorageAccount(it.remote) }
+ settingsToAdd?.let { update.withAppSettings(it) }
+ settingsToRemove.let { if (settingsToRemove.isNotEmpty()) it.forEach { key -> update.withoutAppSetting(key) } }
+
+ val messager = AzureMessager.getMessager()
+ messager.info("Start updating Function App (${remote.name()})")
+
+ result = update.apply()
+
+ if (flexConsumptionModified && newFlexConsumptionConfiguration != null) {
+ updateFlexConsumptionConfiguration(remote, newFlexConsumptionConfiguration)
+ }
+
+ messager.success("Function App (${remote.name()}) is successfully updated")
+ }
+
+ return result
+ }
+
+ private fun updateAppServicePlan(
+ update: com.azure.resourcemanager.appservice.models.FunctionApp.Update,
+ newPlan: AppServicePlan
+ ) {
+ val plan = requireNotNull(newPlan.remote) { "Target app service plan doesn't exist" }
+ val runtime = requireNotNull(dotNetRuntime) { "Unable to find function app runtime" }
+ if (runtime.operatingSystem != newPlan.operatingSystem) {
+ throw AzureToolkitRuntimeException("Could not migrate ${runtime.operatingSystem} app service to ${newPlan.operatingSystem} service plan")
+ }
+ update.withExistingAppServicePlan(plan)
+ }
+
+ private fun updateRuntime(
+ update: com.azure.resourcemanager.appservice.models.FunctionApp.Update,
+ newRuntime: DotNetRuntime
+ ) {
+ val oldRuntime = requireNotNull(origin?.getDotNetRuntime())
+ if (newRuntime.operatingSystem != oldRuntime.operatingSystem) {
+ throw AzureToolkitRuntimeException("Can not update the operation system for existing app service")
+ }
+
+ val functionStack = requireNotNull(newRuntime.functionStack) { "Unable to configure function runtime" }
+ when (oldRuntime.operatingSystem) {
+ OperatingSystem.LINUX -> {
+ update.withBuiltInImage(functionStack)
+ }
+
+ OperatingSystem.WINDOWS -> {
+ update.withRuntime(functionStack.runtime())
+ .withRuntimeVersion(functionStack.version())
+ }
+
+ OperatingSystem.DOCKER -> return
+ }
+ }
+
+ private fun updateDockerConfiguration(
+ update: com.azure.resourcemanager.appservice.models.FunctionApp.Update,
+ newConfig: DockerConfiguration
+ ) {
+ if (newConfig.userName.isNullOrEmpty() && newConfig.password.isNullOrEmpty()) {
+ update.withPublicDockerHubImage(newConfig.image)
+ } else if (newConfig.registryUrl.isNullOrEmpty()) {
+ update.withPrivateDockerHubImage(newConfig.image)
+ .withCredentials(newConfig.userName, newConfig.password)
+ } else {
+ update.withPrivateRegistryImage(newConfig.image, newConfig.registryUrl)
+ .withCredentials(newConfig.userName, newConfig.password)
+ }
+ }
+
+ private fun updateFlexConsumptionConfiguration(
+ app: com.azure.resourcemanager.appservice.models.FunctionApp,
+ flexConfiguration: FlexConsumptionConfiguration
+ ) {
+ val webApps = app.manager().serviceClient().webApps
+ if (flexConfiguration.maximumInstances != null || flexConfiguration.alwaysReadyInstances != null) {
+ val configuration = webApps.getConfiguration(app.resourceGroupName(), app.name())
+ if (flexConfiguration.maximumInstances != configuration.functionAppScaleLimit() ||
+ flexConfiguration.alwaysReadyInstances != configuration.minimumElasticInstanceCount()
+ ) {
+ configuration
+ .withFunctionAppScaleLimit(flexConfiguration.maximumInstances)
+ .withMinimumElasticInstanceCount(flexConfiguration.alwaysReadyInstances)
+ webApps.updateConfiguration(app.resourceGroupName(), app.name(), configuration)
+ }
+ }
+ }
+
+ var dotNetRuntime: DotNetRuntime?
+ get() = config?.runtime ?: remote?.getDotNetRuntime()
+ set(value) {
+ ensureConfig().runtime = value
+ }
+ var storageAccount: StorageAccount?
+ get() = config?.storageAccount
+ set(value) {
+ ensureConfig().storageAccount = value
+ }
+ var dockerConfiguration: DockerConfiguration?
+ get() = config?.dockerConfiguration
+ set(value) {
+ ensureConfig().dockerConfiguration = value
+ }
+ var appSettingsToRemove: Set?
+ get() = config?.appSettingsToRemove
+ set(value) {
+ ensureConfig().appSettingsToRemove = value
+ }
+
+ override fun getAppServicePlan() = config?.plan ?: super.getAppServicePlan()
+ fun setAppServicePlan(value: AppServicePlan?) {
+ ensureConfig().plan = value
+ }
+
+ override fun getAppSettings() = config?.appSettings ?: super.getAppSettings()
+ fun setAppSettings(value: Map?) {
+ ensureConfig().appSettings = value
+ }
+
+ override fun getDiagnosticConfig() = config?.diagnosticConfig ?: super.getDiagnosticConfig()
+ fun setDiagnosticConfig(value: DiagnosticConfig?) {
+ ensureConfig().diagnosticConfig = value
+ }
+
+ override fun getFlexConsumptionConfiguration() = config?.flexConsumptionConfiguration ?: super.getFlexConsumptionConfiguration()
+ fun setFlexConsumptionConfiguration(value: FlexConsumptionConfiguration?) {
+ ensureConfig().flexConsumptionConfiguration = value
+ }
+
+ data class Config(
+ var runtime: DotNetRuntime? = null,
+ var plan: AppServicePlan? = null,
+ var storageAccount: StorageAccount? = null,
+ var enableDistributedTracing: Boolean? = null,
+ var dockerConfiguration: DockerConfiguration? = null,
+ var diagnosticConfig: DiagnosticConfig? = null,
+ var appSettings: Map? = null,
+ var appSettingsToRemove: Set? = null,
+ var flexConsumptionConfiguration: FlexConsumptionConfiguration? = null
+ )
+}
\ No newline at end of file
diff --git a/PluginsAndFeatures/azure-toolkit-for-rider/azure-intellij-plugin-appservice-dotnet/src/main/kotlin/com/microsoft/azure/toolkit/intellij/appservice/webapp/CreateOrUpdateDotNetWebAppTask.kt b/PluginsAndFeatures/azure-toolkit-for-rider/azure-intellij-plugin-appservice-dotnet/src/main/kotlin/com/microsoft/azure/toolkit/intellij/appservice/webapp/CreateOrUpdateDotNetWebAppTask.kt
index d15a6182a4..8a6fcbdaec 100644
--- a/PluginsAndFeatures/azure-toolkit-for-rider/azure-intellij-plugin-appservice-dotnet/src/main/kotlin/com/microsoft/azure/toolkit/intellij/appservice/webapp/CreateOrUpdateDotNetWebAppTask.kt
+++ b/PluginsAndFeatures/azure-toolkit-for-rider/azure-intellij-plugin-appservice-dotnet/src/main/kotlin/com/microsoft/azure/toolkit/intellij/appservice/webapp/CreateOrUpdateDotNetWebAppTask.kt
@@ -4,6 +4,8 @@
package com.microsoft.azure.toolkit.intellij.appservice.webapp
+import com.microsoft.azure.toolkit.intellij.appservice.DotNetRuntime
+import com.microsoft.azure.toolkit.intellij.appservice.DotNetRuntimeConfig
import com.microsoft.azure.toolkit.lib.Azure
import com.microsoft.azure.toolkit.lib.appservice.AzureAppService
import com.microsoft.azure.toolkit.lib.appservice.model.DockerConfiguration
@@ -28,7 +30,7 @@ class CreateOrUpdateDotNetWebAppTask(private val config: DotNetAppServiceConfig)
private fun createOrUpdateResource(): WebAppBase<*, *, *> {
val az = Azure.az(AzureWebApp::class.java)
val target = az.webApps(config.subscriptionId()).getOrDraft(config.appName(), config.resourceGroup())
- if (!isDeployToDeploymentSlot()) {
+ if (config.deploymentSlotName().isNullOrEmpty()) {
if (!target.exists()) {
val availability = az.get(config.subscriptionId(), null)?.checkNameAvailability(config.appName())
if (availability?.isAvailable != true) {
@@ -52,9 +54,8 @@ class CreateOrUpdateDotNetWebAppTask(private val config: DotNetAppServiceConfig)
val slotDraft = target.slots()
.updateOrCreate(config.deploymentSlotName(), config.resourceGroup())
.toDotNetWebAppDeploymentSlotDraft()
- val slotExists = slotDraft.exists()
- return if (slotExists) updateDeploymentSlot(slotDraft)
+ return if (slotDraft.exists()) updateDeploymentSlot(slotDraft)
else createDeploymentSlot(slotDraft)
}
}
@@ -77,8 +78,8 @@ class CreateOrUpdateDotNetWebAppTask(private val config: DotNetAppServiceConfig)
appDraft.dotNetRuntime = getRuntime(config.dotnetRuntime)
appDraft.dockerConfiguration = getDockerConfiguration(config.dotnetRuntime)
appDraft.diagnosticConfig = config.diagnosticConfig()
+ appDraft.appSettingsToRemove = emptySet()
appDraft.appSettings = config.appSettings()
- appDraft.appSettingsToRemove = config.appSettingsToRemove()
return appDraft.createIfNotExist()
}
@@ -96,8 +97,8 @@ class CreateOrUpdateDotNetWebAppTask(private val config: DotNetAppServiceConfig)
appDraft.dotNetRuntime = getRuntime(config.dotnetRuntime)
appDraft.dockerConfiguration = getDockerConfiguration(config.dotnetRuntime)
appDraft.diagnosticConfig = config.diagnosticConfig()
+ appDraft.appSettingsToRemove = getAppSettingsToRemove(webApp.appSettings ?: emptyMap(), config.appSettings())
appDraft.appSettings = config.appSettings()
- appDraft.appSettingsToRemove = config.appSettingsToRemove()
val result = appDraft.updateIfExist()
?: throw AzureToolkitRuntimeException("Unable to update Web App")
@@ -114,7 +115,7 @@ class CreateOrUpdateDotNetWebAppTask(private val config: DotNetAppServiceConfig)
return draft
}
- private fun WebAppDeploymentSlotDraft.toDotNetWebAppDeploymentSlotDraft(): DotNetWebAppDeploymentSlotDraft{
+ private fun WebAppDeploymentSlotDraft.toDotNetWebAppDeploymentSlotDraft(): DotNetWebAppDeploymentSlotDraft {
val draftOrigin = origin
val draft =
if (draftOrigin != null) DotNetWebAppDeploymentSlotDraft(draftOrigin)
@@ -128,8 +129,8 @@ class CreateOrUpdateDotNetWebAppTask(private val config: DotNetAppServiceConfig)
draft.dockerConfiguration = getDockerConfiguration(config.dotnetRuntime)
draft.diagnosticConfig = config.diagnosticConfig()
draft.configurationSource = config.deploymentSlotConfigurationSource()
+ draft.appSettingsToRemove = emptySet()
draft.appSettings = config.appSettings()
- draft.appSettingsToRemove = config.appSettingsToRemove()
return draft.commit()
}
@@ -138,8 +139,8 @@ class CreateOrUpdateDotNetWebAppTask(private val config: DotNetAppServiceConfig)
draft.dotNetRuntime = getRuntime(config.dotnetRuntime)
draft.dockerConfiguration = getDockerConfiguration(config.dotnetRuntime)
draft.diagnosticConfig = config.diagnosticConfig()
+ draft.appSettingsToRemove = getAppSettingsToRemove(draft.appSettings ?: emptyMap(), config.appSettings())
draft.appSettings = config.appSettings()
- draft.appSettingsToRemove = config.appSettingsToRemove()
return draft.commit()
}
@@ -152,6 +153,7 @@ class CreateOrUpdateDotNetWebAppTask(private val config: DotNetAppServiceConfig)
runtimeConfig.os(),
runtimeConfig.stack,
runtimeConfig.frameworkVersion,
+ null,
false
)
} else {
@@ -159,6 +161,7 @@ class CreateOrUpdateDotNetWebAppTask(private val config: DotNetAppServiceConfig)
runtimeConfig.os(),
null,
null,
+ null,
true
)
}
@@ -176,7 +179,8 @@ class CreateOrUpdateDotNetWebAppTask(private val config: DotNetAppServiceConfig)
.build()
}
- private fun isDeployToDeploymentSlot() = !config.deploymentSlotName().isNullOrEmpty()
+ private fun getAppSettingsToRemove(targetSettings: Map, newSettings: Map) =
+ targetSettings.keys.filter { !newSettings.containsKey(it) }.toSet()
override fun doExecute(): WebAppBase<*, *, *> {
var result: Any? = null
diff --git a/PluginsAndFeatures/azure-toolkit-for-rider/azure-intellij-plugin-appservice-dotnet/src/main/kotlin/com/microsoft/azure/toolkit/intellij/appservice/webapp/DotNetAppServiceConfig.kt b/PluginsAndFeatures/azure-toolkit-for-rider/azure-intellij-plugin-appservice-dotnet/src/main/kotlin/com/microsoft/azure/toolkit/intellij/appservice/webapp/DotNetAppServiceConfig.kt
index c874f181a1..41ec727a17 100644
--- a/PluginsAndFeatures/azure-toolkit-for-rider/azure-intellij-plugin-appservice-dotnet/src/main/kotlin/com/microsoft/azure/toolkit/intellij/appservice/webapp/DotNetAppServiceConfig.kt
+++ b/PluginsAndFeatures/azure-toolkit-for-rider/azure-intellij-plugin-appservice-dotnet/src/main/kotlin/com/microsoft/azure/toolkit/intellij/appservice/webapp/DotNetAppServiceConfig.kt
@@ -4,6 +4,7 @@
package com.microsoft.azure.toolkit.intellij.appservice.webapp
+import com.microsoft.azure.toolkit.intellij.appservice.DotNetRuntimeConfig
import com.microsoft.azure.toolkit.lib.appservice.config.AppServiceConfig
class DotNetAppServiceConfig : AppServiceConfig() {
diff --git a/PluginsAndFeatures/azure-toolkit-for-rider/azure-intellij-plugin-appservice-dotnet/src/main/kotlin/com/microsoft/azure/toolkit/intellij/appservice/webapp/DotNetWebAppDeploymentSlotDraft.kt b/PluginsAndFeatures/azure-toolkit-for-rider/azure-intellij-plugin-appservice-dotnet/src/main/kotlin/com/microsoft/azure/toolkit/intellij/appservice/webapp/DotNetWebAppDeploymentSlotDraft.kt
index 07d5b6566d..5e614ef2a4 100644
--- a/PluginsAndFeatures/azure-toolkit-for-rider/azure-intellij-plugin-appservice-dotnet/src/main/kotlin/com/microsoft/azure/toolkit/intellij/appservice/webapp/DotNetWebAppDeploymentSlotDraft.kt
+++ b/PluginsAndFeatures/azure-toolkit-for-rider/azure-intellij-plugin-appservice-dotnet/src/main/kotlin/com/microsoft/azure/toolkit/intellij/appservice/webapp/DotNetWebAppDeploymentSlotDraft.kt
@@ -8,11 +8,12 @@ import com.azure.core.management.exception.ManagementException
import com.azure.resourcemanager.appservice.models.DeploymentSlot
import com.azure.resourcemanager.appservice.models.DeploymentSlotBase
import com.azure.resourcemanager.appservice.models.WebAppBase
+import com.microsoft.azure.toolkit.intellij.appservice.DotNetRuntime
+import com.microsoft.azure.toolkit.intellij.appservice.getDotNetRuntime
import com.microsoft.azure.toolkit.lib.appservice.model.DiagnosticConfig
import com.microsoft.azure.toolkit.lib.appservice.model.DockerConfiguration
import com.microsoft.azure.toolkit.lib.appservice.model.OperatingSystem
import com.microsoft.azure.toolkit.lib.appservice.utils.AppServiceUtils
-import com.microsoft.azure.toolkit.lib.appservice.utils.AppServiceUtils.fromWebAppDiagnosticLogs
import com.microsoft.azure.toolkit.lib.appservice.utils.Utils
import com.microsoft.azure.toolkit.lib.appservice.webapp.WebAppDeploymentSlot
import com.microsoft.azure.toolkit.lib.appservice.webapp.WebAppDeploymentSlotModule
@@ -60,8 +61,7 @@ class DotNetWebAppDeploymentSlotDraft : WebAppDeploymentSlot, AzResource.Draft blank.withBrandNewConfiguration()
@@ -100,13 +99,14 @@ class DotNetWebAppDeploymentSlotDraft : WebAppDeploymentSlot, AzResource.Draft update.withoutAppSetting(key) } }
@@ -171,6 +173,7 @@ class DotNetWebAppDeploymentSlotDraft : WebAppDeploymentSlot, AzResource.Draft {
AzureMessager.getMessager().warning("Update runtime is not supported for Linux app service")
@@ -236,6 +239,6 @@ class DotNetWebAppDeploymentSlotDraft : WebAppDeploymentSlot, AzResource.Draft? = null,
- var appSettingsToRemove: Set? = null,
+ var appSettingsToRemove: Set? = null
)
}
\ No newline at end of file
diff --git a/PluginsAndFeatures/azure-toolkit-for-rider/azure-intellij-plugin-appservice-dotnet/src/main/kotlin/com/microsoft/azure/toolkit/intellij/appservice/webapp/DotNetWebAppDraft.kt b/PluginsAndFeatures/azure-toolkit-for-rider/azure-intellij-plugin-appservice-dotnet/src/main/kotlin/com/microsoft/azure/toolkit/intellij/appservice/webapp/DotNetWebAppDraft.kt
index 1da6928329..3e54a2dc7b 100644
--- a/PluginsAndFeatures/azure-toolkit-for-rider/azure-intellij-plugin-appservice-dotnet/src/main/kotlin/com/microsoft/azure/toolkit/intellij/appservice/webapp/DotNetWebAppDraft.kt
+++ b/PluginsAndFeatures/azure-toolkit-for-rider/azure-intellij-plugin-appservice-dotnet/src/main/kotlin/com/microsoft/azure/toolkit/intellij/appservice/webapp/DotNetWebAppDraft.kt
@@ -6,6 +6,8 @@ package com.microsoft.azure.toolkit.intellij.appservice.webapp
import com.azure.resourcemanager.appservice.models.WebApp.DefinitionStages
import com.azure.resourcemanager.appservice.models.WebAppRuntimeStack
+import com.microsoft.azure.toolkit.intellij.appservice.DotNetRuntime
+import com.microsoft.azure.toolkit.intellij.appservice.getDotNetRuntime
import com.microsoft.azure.toolkit.lib.appservice.AppServiceAppBase
import com.microsoft.azure.toolkit.lib.appservice.model.DiagnosticConfig
import com.microsoft.azure.toolkit.lib.appservice.model.DockerConfiguration
@@ -90,7 +92,7 @@ class DotNetWebAppDraft : WebApp, AzResource.Draft update.withoutAppSetting(key) } }
@@ -230,12 +238,14 @@ class DotNetWebAppDraft : WebApp, AzResource.Draft {
- update.withBuiltInImage(newRuntime.stack)
+ val stack = requireNotNull(newRuntime.stack) { "Unable to configure web app runtime" }
+ update.withBuiltInImage(stack)
}
OperatingSystem.WINDOWS -> {
+ val frameworkVersion = requireNotNull(newRuntime.frameworkVersion) { "Unable to configure web app runtime" }
update.withRuntimeStack(WebAppRuntimeStack.NET)
- .withNetFrameworkVersion(newRuntime.frameworkVersion)
+ .withNetFrameworkVersion(frameworkVersion)
}
OperatingSystem.DOCKER -> return
diff --git a/PluginsAndFeatures/azure-toolkit-for-rider/azure-intellij-plugin-appservice-dotnet/src/main/kotlin/com/microsoft/azure/toolkit/intellij/legacy/webapp/runner/WebAppArtifactService.kt b/PluginsAndFeatures/azure-toolkit-for-rider/azure-intellij-plugin-appservice-dotnet/src/main/kotlin/com/microsoft/azure/toolkit/intellij/legacy/ArtifactService.kt
similarity index 70%
rename from PluginsAndFeatures/azure-toolkit-for-rider/azure-intellij-plugin-appservice-dotnet/src/main/kotlin/com/microsoft/azure/toolkit/intellij/legacy/webapp/runner/WebAppArtifactService.kt
rename to PluginsAndFeatures/azure-toolkit-for-rider/azure-intellij-plugin-appservice-dotnet/src/main/kotlin/com/microsoft/azure/toolkit/intellij/legacy/ArtifactService.kt
index c03c30a57f..0e2bc6bdd6 100644
--- a/PluginsAndFeatures/azure-toolkit-for-rider/azure-intellij-plugin-appservice-dotnet/src/main/kotlin/com/microsoft/azure/toolkit/intellij/legacy/webapp/runner/WebAppArtifactService.kt
+++ b/PluginsAndFeatures/azure-toolkit-for-rider/azure-intellij-plugin-appservice-dotnet/src/main/kotlin/com/microsoft/azure/toolkit/intellij/legacy/ArtifactService.kt
@@ -1,8 +1,8 @@
/*
- * Copyright 2018-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the MIT license.
+ * Copyright 2018-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the MIT license.
*/
-package com.microsoft.azure.toolkit.intellij.legacy.webapp.runner
+package com.microsoft.azure.toolkit.intellij.legacy
import com.intellij.openapi.components.Service
import com.intellij.openapi.components.service
@@ -29,23 +29,25 @@ import java.nio.file.Path
import java.util.zip.ZipOutputStream
@Service(Service.Level.PROJECT)
-class WebAppArtifactService(private val project: Project) {
+class ArtifactService(private val project: Project) {
companion object {
- fun getInstance(project: Project): WebAppArtifactService = project.service()
- private val LOG = logger()
+ fun getInstance(project: Project): ArtifactService = project.service()
+ private val LOG = logger()
}
fun prepareArtifact(
- publishableProject: PublishableProjectModel,
- configuration: String,
- platform: String,
- processHandler: RunProcessHandler
+ publishableProject: PublishableProjectModel,
+ configuration: String,
+ platform: String,
+ processHandler: RunProcessHandler,
+ zipArtifact: Boolean
): File {
processHandler.setText("Collecting ${publishableProject.projectName} project artifacts...")
if (configuration.isNotEmpty() && platform.isNotEmpty()) {
processHandler.setText("Using configuration: $configuration and platform: $platform")
}
val outDir = collectProjectArtifacts(publishableProject, configuration, platform)
+ if (!zipArtifact) return outDir
processHandler.setText("Creating ${publishableProject.projectName} project ZIP...")
return zipProjectArtifacts(outDir, processHandler)
@@ -63,23 +65,28 @@ class WebAppArtifactService(private val project: Project) {
* @return [File] to project content to be published
*/
private fun collectProjectArtifacts(
- publishableProject: PublishableProjectModel,
- configuration: String?,
- platform: String?
+ publishableProject: PublishableProjectModel,
+ configuration: String?,
+ platform: String?
): File {
val publishService = MsBuildPublishingService.getInstance(project)
val (tempDirMsBuildProperty, outPath) = publishService.getPublishToTempDirParameterAndPath()
val extraProperties = mutableListOf()
- if (!configuration.isNullOrEmpty()) extraProperties.add(CustomTargetExtraProperty("Configuration", configuration))
+ if (!configuration.isNullOrEmpty()) extraProperties.add(
+ CustomTargetExtraProperty(
+ "Configuration",
+ configuration
+ )
+ )
if (!platform.isNullOrEmpty()) extraProperties.add(CustomTargetExtraProperty("Platform", platform))
val buildStatus =
- if (publishableProject.isDotNetCore) {
- invokeMsBuild(publishableProject, listOf(tempDirMsBuildProperty) + extraProperties, false, true, true)
- } else {
- webPublishToFileSystem(publishableProject.projectFilePath, outPath, extraProperties, false, true)
- }
+ if (publishableProject.isDotNetCore) {
+ invokeMsBuild(publishableProject, listOf(tempDirMsBuildProperty) + extraProperties, false, true, true)
+ } else {
+ webPublishToFileSystem(publishableProject.projectFilePath, outPath, extraProperties, false, true)
+ }
val buildResult = buildStatus.buildResultKind
if (buildResult != BuildResultKind.Successful && buildResult != BuildResultKind.HasWarnings) {
@@ -94,36 +101,37 @@ class WebAppArtifactService(private val project: Project) {
}
private fun invokeMsBuild(
- projectModel: PublishableProjectModel,
- extraProperties: List,
- diagnosticsMode: Boolean,
- silentMode: Boolean = false,
- noRestore: Boolean = false
+ projectModel: PublishableProjectModel,
+ extraProperties: List,
+ diagnosticsMode: Boolean,
+ silentMode: Boolean = false,
+ noRestore: Boolean = false
): BuildStatus {
val buildParameters = BuildParameters(
- CustomTargetWithExtraProperties(
- "Publish",
- extraProperties
- ), listOf(projectModel.projectFilePath), diagnosticsMode, silentMode, noRestore = noRestore
+ CustomTargetWithExtraProperties(
+ "Publish",
+ extraProperties
+ ), listOf(projectModel.projectFilePath), diagnosticsMode, silentMode, noRestore = noRestore
)
return BuildTaskThrottler.getInstance(project).buildSequentiallySync(buildParameters)
}
private fun webPublishToFileSystem(
- pathToProject: String,
- outPath: Path,
- extraProperties: List,
- diagnosticsMode: Boolean = false,
- silentMode: Boolean = false
+ pathToProject: String,
+ outPath: Path,
+ extraProperties: List,
+ diagnosticsMode: Boolean = false,
+ silentMode: Boolean = false
): BuildStatus {
val buildParameters = BuildParameters(
- CustomTargetWithExtraProperties(
- "WebPublish",
- extraProperties + listOf(
- CustomTargetExtraProperty("WebPublishMethod", "FileSystem"),
- CustomTargetExtraProperty("PublishUrl", outPath.toString()))
- ), listOf(pathToProject), diagnosticsMode, silentMode
+ CustomTargetWithExtraProperties(
+ "WebPublish",
+ extraProperties + listOf(
+ CustomTargetExtraProperty("WebPublishMethod", "FileSystem"),
+ CustomTargetExtraProperty("PublishUrl", outPath.toString())
+ )
+ ), listOf(pathToProject), diagnosticsMode, silentMode
)
return BuildTaskThrottler.getInstance(project).buildSequentiallySync(buildParameters)
@@ -145,9 +153,9 @@ class WebAppArtifactService(private val project: Project) {
}
private fun zipProjectArtifacts(
- fromFile: File,
- processHandler: RunProcessHandler,
- deleteOriginal: Boolean = true
+ fromFile: File,
+ processHandler: RunProcessHandler,
+ deleteOriginal: Boolean = true
): File {
if (!fromFile.exists())
throw FileNotFoundException("Original file '${fromFile.path}' not found")
@@ -170,9 +178,9 @@ class WebAppArtifactService(private val project: Project) {
}
private fun packToZip(
- fileToZip: File,
- zipFileToCreate: File,
- filter: FileFilter? = null
+ fileToZip: File,
+ zipFileToCreate: File,
+ filter: FileFilter? = null
) {
if (!fileToZip.exists()) {
val message = "Source file or directory '${fileToZip.path}' does not exist"
diff --git a/PluginsAndFeatures/azure-toolkit-for-rider/azure-intellij-plugin-appservice-dotnet/src/main/kotlin/com/microsoft/azure/toolkit/intellij/legacy/webapp/runner/webappconfig/PublishableProjectModelExtensions.kt b/PluginsAndFeatures/azure-toolkit-for-rider/azure-intellij-plugin-appservice-dotnet/src/main/kotlin/com/microsoft/azure/toolkit/intellij/legacy/PublishableProjectModelExtensions.kt
similarity index 67%
rename from PluginsAndFeatures/azure-toolkit-for-rider/azure-intellij-plugin-appservice-dotnet/src/main/kotlin/com/microsoft/azure/toolkit/intellij/legacy/webapp/runner/webappconfig/PublishableProjectModelExtensions.kt
rename to PluginsAndFeatures/azure-toolkit-for-rider/azure-intellij-plugin-appservice-dotnet/src/main/kotlin/com/microsoft/azure/toolkit/intellij/legacy/PublishableProjectModelExtensions.kt
index 74dd5ecd21..d3a21caa1a 100644
--- a/PluginsAndFeatures/azure-toolkit-for-rider/azure-intellij-plugin-appservice-dotnet/src/main/kotlin/com/microsoft/azure/toolkit/intellij/legacy/webapp/runner/webappconfig/PublishableProjectModelExtensions.kt
+++ b/PluginsAndFeatures/azure-toolkit-for-rider/azure-intellij-plugin-appservice-dotnet/src/main/kotlin/com/microsoft/azure/toolkit/intellij/legacy/PublishableProjectModelExtensions.kt
@@ -1,16 +1,22 @@
/*
- * Copyright 2018-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the MIT license.
+ * Copyright 2018-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the MIT license.
*/
-package com.microsoft.azure.toolkit.intellij.legacy.webapp.runner.webappconfig
+package com.microsoft.azure.toolkit.intellij.legacy
+import com.azure.resourcemanager.appservice.models.FunctionRuntimeStack
import com.azure.resourcemanager.appservice.models.NetFrameworkVersion
import com.azure.resourcemanager.appservice.models.RuntimeStack
+import com.intellij.openapi.application.readAction
import com.intellij.openapi.project.Project
+import com.intellij.openapi.rd.util.withUiContext
import com.intellij.openapi.util.SystemInfo
import com.jetbrains.rider.model.PublishableProjectModel
import com.jetbrains.rider.model.projectModelTasks
import com.jetbrains.rider.projectView.solution
+import com.microsoft.azure.toolkit.intellij.legacy.function.coreTools.FunctionCoreToolsMsBuildService
+import com.microsoft.azure.toolkit.intellij.legacy.function.runner.localRun.localsettings.FunctionLocalSettingsUtil
+import com.microsoft.azure.toolkit.intellij.legacy.function.runner.localRun.localsettings.FunctionWorkerRuntime
import com.microsoft.azure.toolkit.lib.appservice.model.OperatingSystem
fun PublishableProjectModel.canBePublishedToAzure() = isWeb && (isDotNetCore || SystemInfo.isWindows)
@@ -36,7 +42,7 @@ fun PublishableProjectModel.getStackAndVersion(
} else {
val version =
if (dotnetVersion != null) NetFrameworkVersion.fromString("v$dotnetVersion")
- else NetFrameworkVersion.fromString("v8.0")
+ else NetFrameworkVersion.fromString("v8.0")
return null to version
}
@@ -54,6 +60,28 @@ fun PublishableProjectModel.getStackAndVersion(
}
}
+suspend fun PublishableProjectModel.getFunctionStack(
+ project: Project
+): FunctionRuntimeStack {
+ val functionLocalSettings = readAction {
+ FunctionLocalSettingsUtil.readFunctionLocalSettings(project, this)
+ }
+ val workerRuntime = functionLocalSettings?.values?.workerRuntime ?: FunctionWorkerRuntime.DotNetIsolated
+ val coreToolsVersion = withUiContext {
+ FunctionCoreToolsMsBuildService
+ .getInstance()
+ .requestAzureFunctionsVersion(project, this@getFunctionStack.projectFilePath)
+ ?.trimStart('v', 'V')
+ ?: "4"
+ }
+ val dotnetVersion = getProjectDotNetVersion(project, this)
+ return FunctionRuntimeStack(
+ workerRuntime.value,
+ "~$coreToolsVersion",
+ "${workerRuntime.value}|$dotnetVersion"
+ )
+}
+
private fun getProjectDotNetVersion(project: Project, publishableProject: PublishableProjectModel): String? {
val currentFramework = getCurrentFrameworkId(project, publishableProject) ?: return null
return netAppVersionRegex.find(currentFramework)?.groups?.get(1)?.value
diff --git a/PluginsAndFeatures/azure-toolkit-for-rider/azure-intellij-plugin-appservice-dotnet/src/main/kotlin/com/microsoft/azure/toolkit/intellij/legacy/appservice/AppServiceInfoAdvancedPanel.kt b/PluginsAndFeatures/azure-toolkit-for-rider/azure-intellij-plugin-appservice-dotnet/src/main/kotlin/com/microsoft/azure/toolkit/intellij/legacy/appservice/AppServiceInfoAdvancedPanel.kt
index 77f95d53b8..f595082535 100644
--- a/PluginsAndFeatures/azure-toolkit-for-rider/azure-intellij-plugin-appservice-dotnet/src/main/kotlin/com/microsoft/azure/toolkit/intellij/legacy/appservice/AppServiceInfoAdvancedPanel.kt
+++ b/PluginsAndFeatures/azure-toolkit-for-rider/azure-intellij-plugin-appservice-dotnet/src/main/kotlin/com/microsoft/azure/toolkit/intellij/legacy/appservice/AppServiceInfoAdvancedPanel.kt
@@ -22,7 +22,7 @@ import com.microsoft.azure.toolkit.intellij.common.dotnetProjectComboBox
import com.microsoft.azure.toolkit.intellij.legacy.appservice.serviceplan.ServicePlanComboBox
import com.microsoft.azure.toolkit.intellij.legacy.webapp.WebAppCreationDialog.Companion.RIDER_PROJECT_CONFIGURATION
import com.microsoft.azure.toolkit.intellij.legacy.webapp.WebAppCreationDialog.Companion.RIDER_PROJECT_PLATFORM
-import com.microsoft.azure.toolkit.intellij.legacy.webapp.runner.webappconfig.canBePublishedToAzure
+import com.microsoft.azure.toolkit.intellij.legacy.canBePublishedToAzure
import com.microsoft.azure.toolkit.lib.appservice.config.AppServicePlanConfig
import com.microsoft.azure.toolkit.lib.appservice.model.*
import com.microsoft.azure.toolkit.lib.appservice.plan.AppServicePlan
@@ -85,7 +85,7 @@ class AppServiceInfoAdvancedPanel(
private lateinit var configurationAndPlatformComboBox: Cell>>
init {
- operatingSystem = OperatingSystem.WINDOWS
+ operatingSystem = OperatingSystem.LINUX
panel = panel {
group("Project Details") {
diff --git a/PluginsAndFeatures/azure-toolkit-for-rider/azure-intellij-plugin-appservice-dotnet/src/main/kotlin/com/microsoft/azure/toolkit/intellij/legacy/appservice/AppServiceInfoBasicPanel.kt b/PluginsAndFeatures/azure-toolkit-for-rider/azure-intellij-plugin-appservice-dotnet/src/main/kotlin/com/microsoft/azure/toolkit/intellij/legacy/appservice/AppServiceInfoBasicPanel.kt
index a78fdd91f7..e19198e806 100644
--- a/PluginsAndFeatures/azure-toolkit-for-rider/azure-intellij-plugin-appservice-dotnet/src/main/kotlin/com/microsoft/azure/toolkit/intellij/legacy/appservice/AppServiceInfoBasicPanel.kt
+++ b/PluginsAndFeatures/azure-toolkit-for-rider/azure-intellij-plugin-appservice-dotnet/src/main/kotlin/com/microsoft/azure/toolkit/intellij/legacy/appservice/AppServiceInfoBasicPanel.kt
@@ -17,7 +17,7 @@ import com.microsoft.azure.toolkit.intellij.common.configurationAndPlatformCombo
import com.microsoft.azure.toolkit.intellij.common.dotnetProjectComboBox
import com.microsoft.azure.toolkit.intellij.legacy.webapp.WebAppCreationDialog.Companion.RIDER_PROJECT_CONFIGURATION
import com.microsoft.azure.toolkit.intellij.legacy.webapp.WebAppCreationDialog.Companion.RIDER_PROJECT_PLATFORM
-import com.microsoft.azure.toolkit.intellij.legacy.webapp.runner.webappconfig.canBePublishedToAzure
+import com.microsoft.azure.toolkit.intellij.legacy.canBePublishedToAzure
import com.microsoft.azure.toolkit.lib.appservice.model.JavaVersion
import com.microsoft.azure.toolkit.lib.appservice.model.OperatingSystem
import com.microsoft.azure.toolkit.lib.appservice.model.Runtime
@@ -51,7 +51,7 @@ class AppServiceInfoBasicPanel(
private lateinit var configurationAndPlatformComboBox: Cell>>
init {
- operatingSystem = OperatingSystem.WINDOWS
+ operatingSystem = OperatingSystem.LINUX
panel = panel {
group("Instance Details") {
diff --git a/PluginsAndFeatures/azure-toolkit-for-rider/azure-intellij-plugin-appservice-dotnet/src/main/kotlin/com/microsoft/azure/toolkit/intellij/legacy/function/coreTools/FunctionCoreToolsMsBuildService.kt b/PluginsAndFeatures/azure-toolkit-for-rider/azure-intellij-plugin-appservice-dotnet/src/main/kotlin/com/microsoft/azure/toolkit/intellij/legacy/function/coreTools/FunctionCoreToolsMsBuildService.kt
index 56e69caf49..0a434c8784 100644
--- a/PluginsAndFeatures/azure-toolkit-for-rider/azure-intellij-plugin-appservice-dotnet/src/main/kotlin/com/microsoft/azure/toolkit/intellij/legacy/function/coreTools/FunctionCoreToolsMsBuildService.kt
+++ b/PluginsAndFeatures/azure-toolkit-for-rider/azure-intellij-plugin-appservice-dotnet/src/main/kotlin/com/microsoft/azure/toolkit/intellij/legacy/function/coreTools/FunctionCoreToolsMsBuildService.kt
@@ -14,7 +14,7 @@ import com.jetbrains.rider.projectView.solution
@Service
class FunctionCoreToolsMsBuildService {
companion object {
- fun getInstance(): FunctionCoreToolsMsBuildService = service()
+ fun getInstance() = service()
const val PROPERTY_AZURE_FUNCTIONS_VERSION = "AzureFunctionsVersion"
}
diff --git a/PluginsAndFeatures/azure-toolkit-for-rider/azure-intellij-plugin-appservice-dotnet/src/main/kotlin/com/microsoft/azure/toolkit/intellij/legacy/function/runner/deploy/FunctionDeploymentConfiguration.kt b/PluginsAndFeatures/azure-toolkit-for-rider/azure-intellij-plugin-appservice-dotnet/src/main/kotlin/com/microsoft/azure/toolkit/intellij/legacy/function/runner/deploy/FunctionDeploymentConfiguration.kt
index 2ffc4a0dda..ae3c6138da 100644
--- a/PluginsAndFeatures/azure-toolkit-for-rider/azure-intellij-plugin-appservice-dotnet/src/main/kotlin/com/microsoft/azure/toolkit/intellij/legacy/function/runner/deploy/FunctionDeploymentConfiguration.kt
+++ b/PluginsAndFeatures/azure-toolkit-for-rider/azure-intellij-plugin-appservice-dotnet/src/main/kotlin/com/microsoft/azure/toolkit/intellij/legacy/function/runner/deploy/FunctionDeploymentConfiguration.kt
@@ -9,68 +9,92 @@ import com.intellij.execution.configurations.ConfigurationFactory
import com.intellij.execution.runners.ExecutionEnvironment
import com.intellij.openapi.options.ConfigurationException
import com.intellij.openapi.project.Project
-import com.jetbrains.rider.model.PublishableProjectModel
+import com.intellij.util.xmlb.XmlSerializer
import com.microsoft.azure.toolkit.ide.appservice.function.FunctionAppConfig
import com.microsoft.azure.toolkit.intellij.legacy.common.RiderAzureRunConfigurationBase
-import com.microsoft.azure.toolkit.intellij.legacy.function.saveAppSettingsToSecurityStorage
import com.microsoft.azure.toolkit.lib.appservice.model.OperatingSystem
-import com.microsoft.azure.toolkit.lib.common.utils.JsonUtils
-import org.apache.commons.codec.digest.DigestUtils
+import com.microsoft.azure.toolkit.lib.appservice.model.PricingTier
+import com.microsoft.azure.toolkit.lib.common.model.Region
+import org.jdom.Element
class FunctionDeploymentConfiguration(private val project: Project, factory: ConfigurationFactory, name: String?) :
RiderAzureRunConfigurationBase(project, factory, name) {
- private val functionDeploymentModel = DotNetFunctionDeployModel()
+ private val functionPublishModel = FunctionPublishModel()
+ var functionAppConfig: FunctionAppConfig
+ get() = functionPublishModel.functionAppConfig
+ set(value) {
+ functionPublishModel.functionAppConfig = value
+ }
+ val resourceId: String?
+ get() = functionPublishModel.functionAppConfig.resourceId
+ val functionAppName: String?
+ get() = functionPublishModel.functionAppConfig.name
+ val subscriptionId: String
+ get() = functionPublishModel.functionAppConfig.subscriptionId
+ val resourceGroup: String
+ get() = functionPublishModel.functionAppConfig.resourceGroup.name
+ val region: Region
+ get() = functionPublishModel.functionAppConfig.region
+ val appServicePlanName: String?
+ get() = functionPublishModel.functionAppConfig.servicePlan.name
+ val appServicePlanResourceGroupName: String?
+ get() = functionPublishModel.functionAppConfig.servicePlan.resourceGroupName
+ val pricingTier: PricingTier
+ get() = functionPublishModel.functionAppConfig.servicePlan.pricingTier
+ val operatingSystem: OperatingSystem
+ get() = functionPublishModel.functionAppConfig.runtime.operatingSystem
+ var appSettings: MutableMap
+ get() = functionPublishModel.functionAppConfig.appSettings
+ set(value) {
+ functionPublishModel.functionAppConfig.appSettings = value
+ }
var appSettingsKey: String?
- get() = functionDeploymentModel.appSettingsKey
+ get() = functionPublishModel.appSettingsKey
set(value) {
- functionDeploymentModel.appSettingsKey = value
+ functionPublishModel.appSettingsKey = value
}
var projectConfiguration: String
- get() = functionDeploymentModel.projectConfiguration
+ get() = functionPublishModel.projectConfiguration
set(value) {
- functionDeploymentModel.projectConfiguration = value
+ functionPublishModel.projectConfiguration = value
}
var projectPlatform: String
- get() = functionDeploymentModel.projectPlatform
+ get() = functionPublishModel.projectPlatform
set(value) {
- functionDeploymentModel.projectPlatform = value
+ functionPublishModel.projectPlatform = value
+ }
+ var publishableProjectPath: String?
+ get() = functionPublishModel.publishableProjectPath
+ set(value) {
+ functionPublishModel.publishableProjectPath = value
}
- fun setAppSettings(appSettings: Map) {
- functionDeploymentModel.functionAppConfig.appSettings = appSettings
- functionDeploymentModel.appSettingsHash = DigestUtils.md5Hex(JsonUtils.toJson(appSettings).uppercase())
- saveAppSettingsToSecurityStorage(appSettingsKey, appSettings)
- }
-
- fun getAppSettings() = functionDeploymentModel.functionAppConfig?.appSettings ?: emptyMap()
-
- fun getPublishableProject() = functionDeploymentModel.publishableProject
-
- fun saveProject(projectModel: PublishableProjectModel) {
- functionDeploymentModel.publishableProject = projectModel
- }
-
- fun getConfig(): FunctionAppConfig? = functionDeploymentModel.functionAppConfig
+ override fun getState(executor: Executor, environment: ExecutionEnvironment) =
+ FunctionDeploymentState(project, this)
- fun saveConfig(config: FunctionAppConfig) {
- functionDeploymentModel.functionAppConfig = config
- saveAppSettingsToSecurityStorage(functionDeploymentModel.appSettingsKey, config.appSettings)
- }
+ override fun getConfigurationEditor() = FunctionDeploymentSettingsEditor(project, this)
- override fun getModel() = functionDeploymentModel
+ override fun getModel() = functionPublishModel
override fun checkConfiguration() {
checkAzurePreconditions()
- val functionAppConfig = functionDeploymentModel.functionAppConfig
- if (functionAppConfig.resourceId.isNullOrEmpty() && functionAppConfig.name.isNullOrEmpty()) throw ConfigurationException("Please specify target function")
- if (functionAppConfig.runtime.operatingSystem == OperatingSystem.DOCKER) throw ConfigurationException("Invalid target, docker function is currently not supported")
- if (functionAppConfig.servicePlan == null) throw ConfigurationException("Meta-data of target function app is still loading...")
+ val functionAppConfig = functionPublishModel.functionAppConfig
+ if (functionAppConfig.resourceId.isNullOrEmpty() && functionAppConfig.name.isNullOrEmpty()) throw ConfigurationException(
+ "Please specify target function"
+ )
+ if (functionAppConfig.runtime?.operatingSystem == OperatingSystem.DOCKER) throw ConfigurationException("Invalid target, docker function is currently not supported")
+ if (functionAppConfig.servicePlan == null) throw ConfigurationException("Meta-data of target function app is still loading...")
}
- override fun getState(executor: Executor, environment: ExecutionEnvironment) =
- FunctionDeploymentState(project, this)
+ override fun readExternal(element: Element) {
+ XmlSerializer.deserializeInto(getModel(), element)
+ }
- override fun getConfigurationEditor() = FunctionDeploymentSettingsEditor(project, this)
+ override fun writeExternal(element: Element) {
+ XmlSerializer.serializeInto(getModel(), element) { accessor, _ ->
+ !accessor.name.equals("application", true)
+ }
+ }
}
\ No newline at end of file
diff --git a/PluginsAndFeatures/azure-toolkit-for-rider/azure-intellij-plugin-appservice-dotnet/src/main/kotlin/com/microsoft/azure/toolkit/intellij/legacy/function/runner/deploy/FunctionDeploymentConfigurationFactory.kt b/PluginsAndFeatures/azure-toolkit-for-rider/azure-intellij-plugin-appservice-dotnet/src/main/kotlin/com/microsoft/azure/toolkit/intellij/legacy/function/runner/deploy/FunctionDeploymentConfigurationFactory.kt
deleted file mode 100644
index 417860c345..0000000000
--- a/PluginsAndFeatures/azure-toolkit-for-rider/azure-intellij-plugin-appservice-dotnet/src/main/kotlin/com/microsoft/azure/toolkit/intellij/legacy/function/runner/deploy/FunctionDeploymentConfigurationFactory.kt
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright 2018-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the MIT license.
- */
-
-package com.microsoft.azure.toolkit.intellij.legacy.function.runner.deploy
-
-import com.intellij.execution.configurations.ConfigurationFactory
-import com.intellij.execution.configurations.ConfigurationType
-import com.intellij.execution.configurations.RunConfiguration
-import com.intellij.openapi.project.Project
-import com.microsoft.azure.toolkit.ide.common.icon.AzureIcons
-import com.microsoft.azure.toolkit.intellij.common.IntelliJAzureIcons
-import javax.swing.Icon
-
-class FunctionDeploymentConfigurationFactory(type: ConfigurationType) : ConfigurationFactory(type) {
- companion object {
- private const val FACTORY_ID = "Azure - Deploy Function"
- private const val FACTORY_NAME = "Deploy Function"
- }
-
- override fun getId() = FACTORY_ID
-
- override fun getIcon(): Icon = IntelliJAzureIcons.getIcon(AzureIcons.FunctionApp.DEPLOY)
-
- override fun getName() = FACTORY_NAME
-
- override fun createTemplateConfiguration(project: Project) =
- FunctionDeploymentConfiguration(project, this, project.name)
-
- override fun createConfiguration(name: String?, template: RunConfiguration) =
- FunctionDeploymentConfiguration(template.project, this, name)
-}
\ No newline at end of file
diff --git a/PluginsAndFeatures/azure-toolkit-for-rider/azure-intellij-plugin-appservice-dotnet/src/main/kotlin/com/microsoft/azure/toolkit/intellij/legacy/function/runner/deploy/FunctionDeploymentConfigurationType.kt b/PluginsAndFeatures/azure-toolkit-for-rider/azure-intellij-plugin-appservice-dotnet/src/main/kotlin/com/microsoft/azure/toolkit/intellij/legacy/function/runner/deploy/FunctionDeploymentConfigurationType.kt
index 46353c5b3b..fcb57e0800 100644
--- a/PluginsAndFeatures/azure-toolkit-for-rider/azure-intellij-plugin-appservice-dotnet/src/main/kotlin/com/microsoft/azure/toolkit/intellij/legacy/function/runner/deploy/FunctionDeploymentConfigurationType.kt
+++ b/PluginsAndFeatures/azure-toolkit-for-rider/azure-intellij-plugin-appservice-dotnet/src/main/kotlin/com/microsoft/azure/toolkit/intellij/legacy/function/runner/deploy/FunctionDeploymentConfigurationType.kt
@@ -4,17 +4,27 @@
package com.microsoft.azure.toolkit.intellij.legacy.function.runner.deploy
-import com.intellij.execution.configurations.ConfigurationTypeBase
+import com.intellij.execution.configurations.ConfigurationTypeUtil
+import com.intellij.execution.configurations.RunConfiguration
+import com.intellij.execution.configurations.SimpleConfigurationType
+import com.intellij.openapi.project.Project
+import com.intellij.openapi.util.NotNullLazyValue
import com.microsoft.azure.toolkit.ide.common.icon.AzureIcons
import com.microsoft.azure.toolkit.intellij.common.IntelliJAzureIcons
-class FunctionDeploymentConfigurationType : ConfigurationTypeBase(
+class FunctionDeploymentConfigurationType : SimpleConfigurationType(
"AzureFunctionAppPublish",
"Azure - Function App",
"Azure Publish Function App configuration",
- IntelliJAzureIcons.getIcon(AzureIcons.FunctionApp.DEPLOY)
+ NotNullLazyValue.createValue { IntelliJAzureIcons.getIcon(AzureIcons.FunctionApp.MODULE) }
) {
init {
- addFactory(FunctionDeploymentConfigurationFactory(this))
+ fun getInstance() = ConfigurationTypeUtil.findConfigurationType(FunctionDeploymentConfigurationType::class.java)
}
+
+ override fun createTemplateConfiguration(project: Project) =
+ FunctionDeploymentConfiguration(project, this, project.name)
+
+ override fun createConfiguration(name: String?, template: RunConfiguration) =
+ FunctionDeploymentConfiguration(template.project, this, name)
}
\ No newline at end of file
diff --git a/PluginsAndFeatures/azure-toolkit-for-rider/azure-intellij-plugin-appservice-dotnet/src/main/kotlin/com/microsoft/azure/toolkit/intellij/legacy/function/runner/deploy/FunctionDeploymentSettingsPanel.kt b/PluginsAndFeatures/azure-toolkit-for-rider/azure-intellij-plugin-appservice-dotnet/src/main/kotlin/com/microsoft/azure/toolkit/intellij/legacy/function/runner/deploy/FunctionDeploymentSettingsPanel.kt
index cfb53acb61..1531a562ff 100644
--- a/PluginsAndFeatures/azure-toolkit-for-rider/azure-intellij-plugin-appservice-dotnet/src/main/kotlin/com/microsoft/azure/toolkit/intellij/legacy/function/runner/deploy/FunctionDeploymentSettingsPanel.kt
+++ b/PluginsAndFeatures/azure-toolkit-for-rider/azure-intellij-plugin-appservice-dotnet/src/main/kotlin/com/microsoft/azure/toolkit/intellij/legacy/function/runner/deploy/FunctionDeploymentSettingsPanel.kt
@@ -16,17 +16,14 @@ import com.jetbrains.rider.projectView.solution
import com.jetbrains.rider.run.configurations.publishing.PublishRuntimeSettingsCoreHelper
import com.microsoft.azure.toolkit.ide.appservice.function.FunctionAppConfig
import com.microsoft.azure.toolkit.ide.appservice.model.DeploymentSlotConfig
-import com.microsoft.azure.toolkit.intellij.common.AzureDotnetProjectComboBox
-import com.microsoft.azure.toolkit.intellij.common.AzureFormPanel
-import com.microsoft.azure.toolkit.intellij.common.configurationAndPlatformComboBox
-import com.microsoft.azure.toolkit.intellij.common.dotnetProjectComboBox
+import com.microsoft.azure.toolkit.intellij.common.*
import com.microsoft.azure.toolkit.intellij.legacy.appservice.table.AppSettingsTable
import com.microsoft.azure.toolkit.intellij.legacy.appservice.table.AppSettingsTableUtils
import com.microsoft.azure.toolkit.intellij.legacy.common.RiderAzureSettingPanel
import com.microsoft.azure.toolkit.intellij.legacy.function.FunctionAppComboBox
import com.microsoft.azure.toolkit.intellij.legacy.function.functionAppComboBox
import com.microsoft.azure.toolkit.intellij.legacy.function.runner.deploy.ui.components.DeploymentSlotComboBox
-import com.microsoft.azure.toolkit.intellij.legacy.webapp.runner.webappconfig.canBePublishedToAzure
+import com.microsoft.azure.toolkit.intellij.legacy.canBePublishedToAzure
import com.microsoft.azure.toolkit.lib.Azure
import com.microsoft.azure.toolkit.lib.appservice.AppServiceAppBase
import com.microsoft.azure.toolkit.lib.appservice.function.AzureFunctions
@@ -34,12 +31,11 @@ import java.util.*
import javax.swing.JPanel
class FunctionDeploymentSettingsPanel(private val project: Project, configuration: FunctionDeploymentConfiguration) :
- RiderAzureSettingPanel(), AzureFormPanel {
+ RiderAzureSettingPanel() {
+
private val panel: JPanel
private var appSettingsKey: String = configuration.appSettingsKey ?: UUID.randomUUID().toString()
-
private var appSettingsResourceId: String? = null
-
private lateinit var functionAppComboBox: Cell
private lateinit var deployToSlotCheckBox: Cell
private lateinit var deploymentSlotComboBox: Cell
@@ -160,72 +156,61 @@ class FunctionDeploymentSettingsPanel(private val project: Project, configuratio
override fun apply(configuration: FunctionDeploymentConfiguration) {
configuration.appSettingsKey = appSettingsKey
- configuration.setAppSettings(appSettingsTable.appSettings)
- dotnetProjectComboBox.component.value?.let { configuration.saveProject(it) }
- configuration.projectConfiguration = getSelectedConfiguration()
- configuration.projectPlatform = getSelectedPlatform()
+
val functionConfig = functionAppComboBox.component.value
- val isDeploymentSlotSelected = deployToSlotCheckBox.component.isSelected
- val deploymentSlotConfig = deploymentSlotComboBox.component.value
- functionConfig
- ?.toBuilder()
- ?.deploymentSlot(if (isDeploymentSlotSelected) deploymentSlotConfig else null)
- ?.appSettings(appSettingsTable.appSettings)
- ?.build()
- ?.let { configuration.saveConfig(it) }
+ functionConfig?.let {
+ val builder = it.toBuilder()
+
+ if (deployToSlotCheckBox.component.isSelected) builder.deploymentSlot(deploymentSlotComboBox.component.value)
+ else builder.deploymentSlot(null)
+
+ builder.appSettings(appSettingsTable.appSettings)
+
+ configuration.functionAppConfig = it
+ }
+
+ val publishableProject = dotnetProjectComboBox.component.value
+ configuration.publishableProjectPath = publishableProject?.projectFilePath
+ val (projectConfiguration, projectPlatform) = configurationAndPlatformComboBox.component.component.getPublishConfiguration()
+ configuration.projectConfiguration = projectConfiguration
+ configuration.projectPlatform = projectPlatform
}
override fun reset(configuration: FunctionDeploymentConfiguration) {
- val appSettings = configuration.getAppSettings()
- if (appSettings.isNotEmpty()) appSettingsTable.setAppSettings(appSettings)
+ if (configuration.resourceId.isNullOrEmpty() || configuration.functionAppName.isNullOrEmpty()) return
val settingsKey = configuration.appSettingsKey
if (!settingsKey.isNullOrEmpty()) appSettingsKey = settingsKey
- val config = configuration.getConfig()
- if (config != null && (!config.resourceId.isNullOrEmpty() || !config.name.isNullOrEmpty())) {
- functionAppComboBox.component.value = config
- functionAppComboBox.component.setConfigModel(config)
- deployToSlotCheckBox.component.isSelected = config.deploymentSlot != null
- toggleDeploymentSlot(config.deploymentSlot != null)
+ val functionConfig = configuration.functionAppConfig
+ functionConfig.let { functionApp ->
+ functionAppComboBox.component.value = functionApp
+ functionAppComboBox.component.setConfigModel(functionApp)
+
+ deployToSlotCheckBox.component.isSelected = functionApp.deploymentSlot != null
+ toggleDeploymentSlot(functionApp.deploymentSlot != null)
+ functionApp.deploymentSlot?.let { deploymentSlotComboBox.component.value = it }
+
appSettingsResourceId =
- if (config.resourceId.isNullOrEmpty() && config.name.isNullOrEmpty()) null
- else getResourceId(config, config.deploymentSlot)
- config.deploymentSlot?.let { deploymentSlotComboBox.component.value = it }
- config.appSettings?.let { appSettingsTable.setAppSettings(it) }
+ if (functionApp.resourceId.isNullOrEmpty() && functionApp.name.isNullOrEmpty()) null
+ else getResourceId(functionApp, functionApp.deploymentSlot)
+
+ functionApp.appSettings?.let { appSettingsTable.setAppSettings(it) }
}
- val projectId = configuration.getPublishableProject()?.projectModelId
- if (projectId != null) {
- project.solution.publishableProjectsModel.publishableProjects.values
- .firstOrNull { p -> p.projectModelId == projectId }
- ?.let { p -> dotnetProjectComboBox.component.setProject(p) }
+ val publishableProject = project.solution.publishableProjectsModel.publishableProjects.values
+ .firstOrNull { p -> p.projectFilePath == configuration.publishableProjectPath }
+ if (publishableProject != null) {
+ dotnetProjectComboBox.component.setProject(publishableProject)
}
- setConfigurationAndPlatform(configuration.projectConfiguration, configuration.projectPlatform)
+ configurationAndPlatformComboBox.component.component.setPublishConfiguration(
+ configuration.projectConfiguration,
+ configuration.projectPlatform
+ )
}
override fun getMainPanel() = panel
override fun disposeEditor() {
}
-
- override fun setValue(data: FunctionDeploymentConfiguration) = reset(data)
-
- override fun getInputs() =
- listOf(functionAppComboBox.component, deploymentSlotComboBox.component, dotnetProjectComboBox.component)
-
- private fun getSelectedConfiguration() = getSelectedConfigurationAndPlatform()?.configuration ?: ""
- private fun getSelectedPlatform() = getSelectedConfigurationAndPlatform()?.platform ?: ""
- private fun getSelectedConfigurationAndPlatform(): PublishRuntimeSettingsCoreHelper.ConfigurationAndPlatform? =
- configurationAndPlatformComboBox.component.component.selectedItem as? PublishRuntimeSettingsCoreHelper.ConfigurationAndPlatform
-
- fun setConfigurationAndPlatform(configuration: String, platform: String) {
- for (i in 0 until configurationAndPlatformComboBox.component.component.model.size) {
- val item = configurationAndPlatformComboBox.component.component.model.getElementAt(i)
- if (item?.configuration == configuration && item.platform == platform) {
- configurationAndPlatformComboBox.component.component.selectedItem = item
- break
- }
- }
- }
}
\ No newline at end of file
diff --git a/PluginsAndFeatures/azure-toolkit-for-rider/azure-intellij-plugin-appservice-dotnet/src/main/kotlin/com/microsoft/azure/toolkit/intellij/legacy/function/runner/deploy/FunctionDeploymentState.kt b/PluginsAndFeatures/azure-toolkit-for-rider/azure-intellij-plugin-appservice-dotnet/src/main/kotlin/com/microsoft/azure/toolkit/intellij/legacy/function/runner/deploy/FunctionDeploymentState.kt
index c3bc9c3a37..485c4ffa2d 100644
--- a/PluginsAndFeatures/azure-toolkit-for-rider/azure-intellij-plugin-appservice-dotnet/src/main/kotlin/com/microsoft/azure/toolkit/intellij/legacy/function/runner/deploy/FunctionDeploymentState.kt
+++ b/PluginsAndFeatures/azure-toolkit-for-rider/azure-intellij-plugin-appservice-dotnet/src/main/kotlin/com/microsoft/azure/toolkit/intellij/legacy/function/runner/deploy/FunctionDeploymentState.kt
@@ -2,25 +2,98 @@
* Copyright 2018-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the MIT license.
*/
+@file:Suppress("UnstableApiUsage")
+
package com.microsoft.azure.toolkit.intellij.legacy.function.runner.deploy
+import com.intellij.openapi.progress.runBlockingCancellable
import com.intellij.openapi.project.Project
+import com.jetbrains.rider.model.PublishableProjectModel
+import com.jetbrains.rider.model.publishableProjectsModel
+import com.jetbrains.rider.projectView.solution
+import com.microsoft.azure.toolkit.intellij.appservice.DotNetRuntimeConfig
+import com.microsoft.azure.toolkit.intellij.appservice.functionapp.CreateOrUpdateDotNetFunctionAppTask
+import com.microsoft.azure.toolkit.intellij.appservice.functionapp.DotNetFunctionAppConfig
import com.microsoft.azure.toolkit.intellij.common.RunProcessHandler
+import com.microsoft.azure.toolkit.intellij.legacy.ArtifactService
import com.microsoft.azure.toolkit.intellij.legacy.common.RiderAzureRunProfileState
+import com.microsoft.azure.toolkit.intellij.legacy.getFunctionStack
+import com.microsoft.azure.toolkit.lib.appservice.config.RuntimeConfig
import com.microsoft.azure.toolkit.lib.appservice.function.FunctionAppBase
+import com.microsoft.azure.toolkit.lib.appservice.model.FunctionDeployType
+import com.microsoft.azure.toolkit.lib.appservice.model.JavaVersion
+import com.microsoft.azure.toolkit.lib.appservice.model.WebContainer
+import com.microsoft.azure.toolkit.lib.appservice.task.DeployFunctionAppTask
+import com.microsoft.azure.toolkit.lib.common.operation.OperationContext
class FunctionDeploymentState(
project: Project,
private val functionDeploymentConfiguration: FunctionDeploymentConfiguration
) : RiderAzureRunProfileState>(project) {
- private val deployModel = functionDeploymentConfiguration.getModel()
-
override fun executeSteps(processHandler: RunProcessHandler): FunctionAppBase<*, *, *> {
- throw NotImplementedError()
+ OperationContext.current().setMessager(processHandlerMessenger)
+
+ processHandler.setText("Start Function App deployment")
+
+ val publishableProjectPath = functionDeploymentConfiguration.publishableProjectPath
+ ?: throw RuntimeException("Project is not defined")
+ val publishableProject = project.solution.publishableProjectsModel.publishableProjects.values
+ .firstOrNull { it.projectFilePath == publishableProjectPath }
+ ?: throw RuntimeException("Project is not defined")
+
+ val config = creatDotNetFunctionAppConfig(publishableProject)
+ val createTask = CreateOrUpdateDotNetFunctionAppTask(config)
+ val deployTarget = createTask.execute()
+
+ val artifactDirectory = ArtifactService.getInstance(project)
+ .prepareArtifact(
+ publishableProject,
+ functionDeploymentConfiguration.projectConfiguration,
+ functionDeploymentConfiguration.projectPlatform,
+ processHandler,
+ false
+ )
+
+ val deployTask = DeployFunctionAppTask(deployTarget, artifactDirectory, FunctionDeployType.ZIP)
+ deployTask.execute()
+
+ return deployTarget
+ }
+
+ private fun creatDotNetFunctionAppConfig(publishableProject: PublishableProjectModel) =
+ DotNetFunctionAppConfig().apply {
+ subscriptionId(functionDeploymentConfiguration.subscriptionId)
+ resourceGroup(functionDeploymentConfiguration.resourceGroup)
+ region(functionDeploymentConfiguration.region)
+ servicePlanName(functionDeploymentConfiguration.appServicePlanName)
+ servicePlanResourceGroup(functionDeploymentConfiguration.appServicePlanResourceGroupName)
+ pricingTier(functionDeploymentConfiguration.pricingTier)
+ appName(functionDeploymentConfiguration.functionAppName)
+ runtime(createRuntimeConfig())
+ dotnetRuntime = createDotNetRuntimeConfig(publishableProject)
+ appSettings(functionDeploymentConfiguration.appSettings)
+ }
+
+ private fun createRuntimeConfig() = RuntimeConfig().apply {
+ os(functionDeploymentConfiguration.operatingSystem)
+ javaVersion(JavaVersion.OFF)
+ webContainer(WebContainer.JAVA_OFF)
+ }
+
+ private fun createDotNetRuntimeConfig(publishableProject: PublishableProjectModel) = DotNetRuntimeConfig().apply {
+ val operatingSystem = functionDeploymentConfiguration.operatingSystem
+ os(operatingSystem)
+ javaVersion(JavaVersion.OFF)
+ webContainer(WebContainer.JAVA_OFF)
+ isDocker = false
+ functionStack = runBlockingCancellable {
+ publishableProject.getFunctionStack(project)
+ }
}
override fun onSuccess(result: FunctionAppBase<*, *, *>, processHandler: RunProcessHandler) {
+ result.appSettings?.let { functionDeploymentConfiguration.appSettings = it }
processHandler.notifyComplete()
}
}
\ No newline at end of file
diff --git a/PluginsAndFeatures/azure-toolkit-for-rider/azure-intellij-plugin-appservice-dotnet/src/main/kotlin/com/microsoft/azure/toolkit/intellij/legacy/function/runner/deploy/DotNetFunctionDeployModel.kt b/PluginsAndFeatures/azure-toolkit-for-rider/azure-intellij-plugin-appservice-dotnet/src/main/kotlin/com/microsoft/azure/toolkit/intellij/legacy/function/runner/deploy/FunctionPublishModel.kt
similarity index 61%
rename from PluginsAndFeatures/azure-toolkit-for-rider/azure-intellij-plugin-appservice-dotnet/src/main/kotlin/com/microsoft/azure/toolkit/intellij/legacy/function/runner/deploy/DotNetFunctionDeployModel.kt
rename to PluginsAndFeatures/azure-toolkit-for-rider/azure-intellij-plugin-appservice-dotnet/src/main/kotlin/com/microsoft/azure/toolkit/intellij/legacy/function/runner/deploy/FunctionPublishModel.kt
index 25c35d2188..2b8f396f30 100644
--- a/PluginsAndFeatures/azure-toolkit-for-rider/azure-intellij-plugin-appservice-dotnet/src/main/kotlin/com/microsoft/azure/toolkit/intellij/legacy/function/runner/deploy/DotNetFunctionDeployModel.kt
+++ b/PluginsAndFeatures/azure-toolkit-for-rider/azure-intellij-plugin-appservice-dotnet/src/main/kotlin/com/microsoft/azure/toolkit/intellij/legacy/function/runner/deploy/FunctionPublishModel.kt
@@ -4,10 +4,9 @@
package com.microsoft.azure.toolkit.intellij.legacy.function.runner.deploy
-import com.jetbrains.rider.model.PublishableProjectModel
-class DotNetFunctionDeployModel: FunctionDeployModel() {
- var publishableProject: PublishableProjectModel? = null
+class FunctionPublishModel : FunctionDeployModel() {
+ var publishableProjectPath: String? = null
var projectConfiguration: String = ""
var projectPlatform: String = ""
}
\ No newline at end of file
diff --git a/PluginsAndFeatures/azure-toolkit-for-rider/azure-intellij-plugin-appservice-dotnet/src/main/kotlin/com/microsoft/azure/toolkit/intellij/legacy/function/runner/localRun/localsettings/FunctionLocalSettings.kt b/PluginsAndFeatures/azure-toolkit-for-rider/azure-intellij-plugin-appservice-dotnet/src/main/kotlin/com/microsoft/azure/toolkit/intellij/legacy/function/runner/localRun/localsettings/FunctionLocalSettings.kt
index 8cbe806b16..445c64c86f 100644
--- a/PluginsAndFeatures/azure-toolkit-for-rider/azure-intellij-plugin-appservice-dotnet/src/main/kotlin/com/microsoft/azure/toolkit/intellij/legacy/function/runner/localRun/localsettings/FunctionLocalSettings.kt
+++ b/PluginsAndFeatures/azure-toolkit-for-rider/azure-intellij-plugin-appservice-dotnet/src/main/kotlin/com/microsoft/azure/toolkit/intellij/legacy/function/runner/localRun/localsettings/FunctionLocalSettings.kt
@@ -17,9 +17,13 @@ data class FunctionValuesModel(
val webJobsHttpExampleDisabled: Boolean?,
val bindingConnection: String?)
-data class FunctionHostModel(val localHttpPort: Int?, val cors: String?, val corsCredentials: Boolean?)
+data class FunctionHostModel(
+ val localHttpPort: Int?,
+ val cors: String?,
+ val corsCredentials: Boolean?
+)
enum class FunctionWorkerRuntime(val value: String) {
- DotNetDefault("dotnet"),
- DotNetIsolated("dotnet-isolated")
+ DotNetDefault("DOTNET"),
+ DotNetIsolated("DOTNET-ISOLATED")
}
\ No newline at end of file
diff --git a/PluginsAndFeatures/azure-toolkit-for-rider/azure-intellij-plugin-appservice-dotnet/src/main/kotlin/com/microsoft/azure/toolkit/intellij/legacy/function/runner/localRun/localsettings/FunctionLocalSettingsUtil.kt b/PluginsAndFeatures/azure-toolkit-for-rider/azure-intellij-plugin-appservice-dotnet/src/main/kotlin/com/microsoft/azure/toolkit/intellij/legacy/function/runner/localRun/localsettings/FunctionLocalSettingsUtil.kt
index a2bac83b4b..fce35917fe 100644
--- a/PluginsAndFeatures/azure-toolkit-for-rider/azure-intellij-plugin-appservice-dotnet/src/main/kotlin/com/microsoft/azure/toolkit/intellij/legacy/function/runner/localRun/localsettings/FunctionLocalSettingsUtil.kt
+++ b/PluginsAndFeatures/azure-toolkit-for-rider/azure-intellij-plugin-appservice-dotnet/src/main/kotlin/com/microsoft/azure/toolkit/intellij/legacy/function/runner/localRun/localsettings/FunctionLocalSettingsUtil.kt
@@ -7,24 +7,31 @@ package com.microsoft.azure.toolkit.intellij.legacy.function.runner.localRun.loc
import com.intellij.openapi.project.Project
import com.intellij.openapi.vfs.VfsUtil
import com.intellij.openapi.vfs.VirtualFile
+import com.jetbrains.rider.model.PublishableProjectModel
import com.jetbrains.rider.model.RunnableProject
-import java.io.File
+import java.nio.file.Path
+import kotlin.io.path.Path
+import kotlin.io.path.absolutePathString
+import kotlin.io.path.exists
object FunctionLocalSettingsUtil {
+ fun readFunctionLocalSettings(project: Project, publishableProject: PublishableProjectModel): FunctionLocalSettings? =
+ readFunctionLocalSettings(project, Path(publishableProject.projectFilePath).parent.absolutePathString())
+
fun readFunctionLocalSettings(project: Project, runnableProject: RunnableProject): FunctionLocalSettings? =
- readFunctionLocalSettings(project, File(runnableProject.projectFilePath).parent)
+ readFunctionLocalSettings(project, Path(runnableProject.projectFilePath).parent.absolutePathString())
fun readFunctionLocalSettings(project: Project, basePath: String): FunctionLocalSettings? {
val localSettingsFile = getLocalSettingsVirtualFile(basePath) ?: return null
return FunctionLocalSettingsParser.getInstance().readLocalSettingsJsonFrom(localSettingsFile, project)
}
- fun getLocalSettingsVirtualFile(basePath: String): VirtualFile? {
+ private fun getLocalSettingsVirtualFile(basePath: String): VirtualFile? {
val localSettingsFile = getLocalSettingFile(basePath)
if (!localSettingsFile.exists()) return null
- return VfsUtil.findFileByIoFile(localSettingsFile, true)
+ return VfsUtil.findFile(localSettingsFile, true)
}
- fun getLocalSettingFile(basePath: String): File = File(basePath).resolve("local.settings.json")
+ private fun getLocalSettingFile(basePath: String): Path = Path(basePath).resolve("local.settings.json")
}
\ No newline at end of file
diff --git a/PluginsAndFeatures/azure-toolkit-for-rider/azure-intellij-plugin-appservice-dotnet/src/main/kotlin/com/microsoft/azure/toolkit/intellij/legacy/webapp/WebAppCreationDialog.kt b/PluginsAndFeatures/azure-toolkit-for-rider/azure-intellij-plugin-appservice-dotnet/src/main/kotlin/com/microsoft/azure/toolkit/intellij/legacy/webapp/WebAppCreationDialog.kt
index f4d4943288..e899fc37fe 100644
--- a/PluginsAndFeatures/azure-toolkit-for-rider/azure-intellij-plugin-appservice-dotnet/src/main/kotlin/com/microsoft/azure/toolkit/intellij/legacy/webapp/WebAppCreationDialog.kt
+++ b/PluginsAndFeatures/azure-toolkit-for-rider/azure-intellij-plugin-appservice-dotnet/src/main/kotlin/com/microsoft/azure/toolkit/intellij/legacy/webapp/WebAppCreationDialog.kt
@@ -31,10 +31,16 @@ open class WebAppCreationDialog(project: Project) : ConfigDialog(p
val selectedSubscriptions = Azure.az(AzureAccount::class.java).account().selectedSubscriptions
if (selectedSubscriptions.isEmpty()) {
this.close()
- throw AzureToolkitRuntimeException("There are no subscriptions selected in your account.", IAccountActions.SELECT_SUBS)
+ throw AzureToolkitRuntimeException(
+ "There are no subscriptions selected in your account.",
+ IAccountActions.SELECT_SUBS
+ )
}
- basicPanel = AppServiceInfoBasicPanel(project, selectedSubscriptions[0]) { WebAppConfig.getWebAppDefaultConfig(project.name) }
+ basicPanel = AppServiceInfoBasicPanel(
+ project,
+ selectedSubscriptions[0]
+ ) { WebAppConfig.getWebAppDefaultConfig(project.name) }
advancedPanel = AppServiceInfoAdvancedPanel(project) { WebAppConfig.getWebAppDefaultConfig(project.name) }
panel = panel {
diff --git a/PluginsAndFeatures/azure-toolkit-for-rider/azure-intellij-plugin-appservice-dotnet/src/main/kotlin/com/microsoft/azure/toolkit/intellij/legacy/webapp/action/CreateWebAppAction.kt b/PluginsAndFeatures/azure-toolkit-for-rider/azure-intellij-plugin-appservice-dotnet/src/main/kotlin/com/microsoft/azure/toolkit/intellij/legacy/webapp/action/CreateWebAppAction.kt
index c75ce9cdb9..668806c7b5 100644
--- a/PluginsAndFeatures/azure-toolkit-for-rider/azure-intellij-plugin-appservice-dotnet/src/main/kotlin/com/microsoft/azure/toolkit/intellij/legacy/webapp/action/CreateWebAppAction.kt
+++ b/PluginsAndFeatures/azure-toolkit-for-rider/azure-intellij-plugin-appservice-dotnet/src/main/kotlin/com/microsoft/azure/toolkit/intellij/legacy/webapp/action/CreateWebAppAction.kt
@@ -14,14 +14,14 @@ import com.jetbrains.rider.projectView.solution
import com.microsoft.azure.toolkit.ide.appservice.webapp.model.WebAppConfig
import com.microsoft.azure.toolkit.intellij.appservice.webapp.CreateOrUpdateDotNetWebAppTask
import com.microsoft.azure.toolkit.intellij.appservice.webapp.DotNetAppServiceConfig
-import com.microsoft.azure.toolkit.intellij.appservice.webapp.DotNetRuntimeConfig
+import com.microsoft.azure.toolkit.intellij.appservice.DotNetRuntimeConfig
import com.microsoft.azure.toolkit.intellij.common.RunProcessHandler
import com.microsoft.azure.toolkit.intellij.common.RunProcessHandlerMessenger
import com.microsoft.azure.toolkit.intellij.legacy.webapp.WebAppCreationDialog
import com.microsoft.azure.toolkit.intellij.legacy.webapp.WebAppCreationDialog.Companion.RIDER_PROJECT_CONFIGURATION
import com.microsoft.azure.toolkit.intellij.legacy.webapp.WebAppCreationDialog.Companion.RIDER_PROJECT_PLATFORM
-import com.microsoft.azure.toolkit.intellij.legacy.webapp.runner.WebAppArtifactService
-import com.microsoft.azure.toolkit.intellij.legacy.webapp.runner.webappconfig.getStackAndVersion
+import com.microsoft.azure.toolkit.intellij.legacy.ArtifactService
+import com.microsoft.azure.toolkit.intellij.legacy.getStackAndVersion
import com.microsoft.azure.toolkit.lib.appservice.config.RuntimeConfig
import com.microsoft.azure.toolkit.lib.appservice.model.DeployType
import com.microsoft.azure.toolkit.lib.appservice.model.JavaVersion
@@ -150,8 +150,8 @@ class CreateWebAppAction {
val messenger = RunProcessHandlerMessenger(processHandler)
OperationContext.current().messager = messenger
- val zipFile = WebAppArtifactService.getInstance(project)
- .prepareArtifact(projectModel, projectConfiguration, projectPlatform, processHandler)
+ val zipFile = ArtifactService.getInstance(project)
+ .prepareArtifact(projectModel, projectConfiguration, projectPlatform, processHandler, true)
val artifact = WebAppArtifact.builder()
.file(zipFile)
.deployType(DeployType.ZIP)
diff --git a/PluginsAndFeatures/azure-toolkit-for-rider/azure-intellij-plugin-appservice-dotnet/src/main/kotlin/com/microsoft/azure/toolkit/intellij/legacy/webapp/runner/webappconfig/WebAppConfiguration.kt b/PluginsAndFeatures/azure-toolkit-for-rider/azure-intellij-plugin-appservice-dotnet/src/main/kotlin/com/microsoft/azure/toolkit/intellij/legacy/webapp/runner/webappconfig/WebAppConfiguration.kt
index 26e081539d..f14a3327a9 100644
--- a/PluginsAndFeatures/azure-toolkit-for-rider/azure-intellij-plugin-appservice-dotnet/src/main/kotlin/com/microsoft/azure/toolkit/intellij/legacy/webapp/runner/webappconfig/WebAppConfiguration.kt
+++ b/PluginsAndFeatures/azure-toolkit-for-rider/azure-intellij-plugin-appservice-dotnet/src/main/kotlin/com/microsoft/azure/toolkit/intellij/legacy/webapp/runner/webappconfig/WebAppConfiguration.kt
@@ -111,17 +111,12 @@ class WebAppConfiguration(private val project: Project, factory: ConfigurationFa
set(value) {
webAppPublishModel.appSettingsKey = value
}
- var appSettingsToRemove: Set
- get() = webAppPublishModel.appSettingsToRemove
- set(value) {
- webAppPublishModel.appSettingsToRemove = value
- }
var runtime: Runtime?
get() = webAppPublishModel.runtime
set(value) {
webAppPublishModel.saveRuntime(value)
}
- var operatingSystem : OperatingSystem
+ var operatingSystem: OperatingSystem
get() = OperatingSystem.fromString(webAppPublishModel.operatingSystem)
set(value) {
webAppPublishModel.operatingSystem = value.toString()
diff --git a/PluginsAndFeatures/azure-toolkit-for-rider/azure-intellij-plugin-appservice-dotnet/src/main/kotlin/com/microsoft/azure/toolkit/intellij/legacy/webapp/runner/webappconfig/WebAppDeployConfigurationPanel.kt b/PluginsAndFeatures/azure-toolkit-for-rider/azure-intellij-plugin-appservice-dotnet/src/main/kotlin/com/microsoft/azure/toolkit/intellij/legacy/webapp/runner/webappconfig/WebAppDeployConfigurationPanel.kt
index 0c198b7dca..47639472e1 100644
--- a/PluginsAndFeatures/azure-toolkit-for-rider/azure-intellij-plugin-appservice-dotnet/src/main/kotlin/com/microsoft/azure/toolkit/intellij/legacy/webapp/runner/webappconfig/WebAppDeployConfigurationPanel.kt
+++ b/PluginsAndFeatures/azure-toolkit-for-rider/azure-intellij-plugin-appservice-dotnet/src/main/kotlin/com/microsoft/azure/toolkit/intellij/legacy/webapp/runner/webappconfig/WebAppDeployConfigurationPanel.kt
@@ -21,13 +21,11 @@ import com.microsoft.azure.toolkit.ide.appservice.model.AzureArtifactConfig
import com.microsoft.azure.toolkit.ide.appservice.model.DeploymentSlotConfig
import com.microsoft.azure.toolkit.ide.appservice.webapp.model.WebAppConfig
import com.microsoft.azure.toolkit.ide.appservice.webapp.model.WebAppDeployRunConfigurationModel
-import com.microsoft.azure.toolkit.intellij.common.AzureDotnetProjectComboBox
-import com.microsoft.azure.toolkit.intellij.common.AzureFormPanel
+import com.microsoft.azure.toolkit.intellij.common.*
import com.microsoft.azure.toolkit.intellij.common.component.UIUtils
-import com.microsoft.azure.toolkit.intellij.common.configurationAndPlatformComboBox
-import com.microsoft.azure.toolkit.intellij.common.dotnetProjectComboBox
import com.microsoft.azure.toolkit.intellij.legacy.appservice.table.AppSettingsTable
import com.microsoft.azure.toolkit.intellij.legacy.appservice.table.AppSettingsTableUtils
+import com.microsoft.azure.toolkit.intellij.legacy.canBePublishedToAzure
import com.microsoft.azure.toolkit.intellij.legacy.webapp.WebAppCreationDialog.Companion.RIDER_PROJECT_CONFIGURATION
import com.microsoft.azure.toolkit.intellij.legacy.webapp.WebAppCreationDialog.Companion.RIDER_PROJECT_PLATFORM
import com.microsoft.azure.toolkit.lib.Azure
@@ -51,8 +49,6 @@ class WebAppDeployConfigurationPanel(private val project: Project) : AzureFormPa
private val formatter = DateTimeFormatter.ofPattern("yyMMddHHmmss")
- private val currentAppSettingKeys = mutableListOf()
-
val panel: JPanel
private lateinit var webAppComboBox: Cell
@@ -197,16 +193,10 @@ class WebAppDeployConfigurationPanel(private val project: Project) : AzureFormPa
}
} else if (selectedWebApp != before) {
appSettingsTable.loadAppSettings {
- currentAppSettingKeys.clear()
if (selectedWebApp.resourceId.isNullOrEmpty()) {
selectedWebApp.appSettings
- }
- else {
- val currentSettings = Azure.az(AzureWebApp::class.java).webApp(selectedWebApp.resourceId)?.appSettings
- if (currentSettings != null) {
- currentAppSettingKeys.addAll(currentSettings.keys)
- }
- currentSettings
+ } else {
+ Azure.az(AzureWebApp::class.java).webApp(selectedWebApp.resourceId)?.appSettings
}
}
}
@@ -255,13 +245,7 @@ class WebAppDeployConfigurationPanel(private val project: Project) : AzureFormPa
}
fun setConfigurationAndPlatform(configuration: String, platform: String) {
- for (i in 0 until configurationAndPlatformComboBox.component.component.model.size) {
- val item = configurationAndPlatformComboBox.component.component.model.getElementAt(i)
- if (item?.configuration == configuration && item.platform == platform) {
- configurationAndPlatformComboBox.component.component.selectedItem = item
- break
- }
- }
+ configurationAndPlatformComboBox.component.component.setPublishConfiguration(configuration, platform)
}
override fun getValue(): WebAppDeployRunConfigurationModel {
@@ -293,15 +277,9 @@ class WebAppDeployConfigurationPanel(private val project: Project) : AzureFormPa
if (webAppComboBox.component.value?.appSettings?.containsKey(RIDER_PROJECT_PLATFORM) == true)
webAppComboBox.component.value?.appSettings?.remove(RIDER_PROJECT_PLATFORM)
- val appSettings = appSettingsTable.appSettings
- val settingsToRemove = currentAppSettingKeys
- .filter { !appSettings.containsKey(it) }
- .toSet()
-
val webAppConfig = webAppComboBox.component.value
?.toBuilder()
?.appSettings(appSettingsTable.appSettings)
- ?.appSettingsToRemove(settingsToRemove)
?.deploymentSlot(slotConfig)
?.build()
@@ -314,10 +292,8 @@ class WebAppDeployConfigurationPanel(private val project: Project) : AzureFormPa
.build()
}
- fun getSelectedConfiguration() = getSelectedConfigurationAndPlatform()?.configuration ?: ""
- fun getSelectedPlatform() = getSelectedConfigurationAndPlatform()?.platform ?: ""
- private fun getSelectedConfigurationAndPlatform(): PublishRuntimeSettingsCoreHelper.ConfigurationAndPlatform? =
- configurationAndPlatformComboBox.component.component.selectedItem as? PublishRuntimeSettingsCoreHelper.ConfigurationAndPlatform
+ fun getConfigurationAndPlatform(): Pair =
+ configurationAndPlatformComboBox.component.component.getPublishConfiguration()
override fun getInputs() = listOf(webAppComboBox.component, dotnetProjectComboBox.component)
diff --git a/PluginsAndFeatures/azure-toolkit-for-rider/azure-intellij-plugin-appservice-dotnet/src/main/kotlin/com/microsoft/azure/toolkit/intellij/legacy/webapp/runner/webappconfig/WebAppPublishModel.kt b/PluginsAndFeatures/azure-toolkit-for-rider/azure-intellij-plugin-appservice-dotnet/src/main/kotlin/com/microsoft/azure/toolkit/intellij/legacy/webapp/runner/webappconfig/WebAppPublishModel.kt
index 22956e0f12..e7f4f7d582 100644
--- a/PluginsAndFeatures/azure-toolkit-for-rider/azure-intellij-plugin-appservice-dotnet/src/main/kotlin/com/microsoft/azure/toolkit/intellij/legacy/webapp/runner/webappconfig/WebAppPublishModel.kt
+++ b/PluginsAndFeatures/azure-toolkit-for-rider/azure-intellij-plugin-appservice-dotnet/src/main/kotlin/com/microsoft/azure/toolkit/intellij/legacy/webapp/runner/webappconfig/WebAppPublishModel.kt
@@ -10,7 +10,6 @@ import java.util.*
class WebAppPublishModel : WebAppSettingModel() {
var appSettingsKey: String = UUID.randomUUID().toString()
var appSettings: Map = mapOf()
- var appSettingsToRemove: Set = setOf()
var isOpenBrowserAfterDeployment: Boolean = true
var slotPanelVisible: Boolean = true
var publishableProjectPath: String? = null
diff --git a/PluginsAndFeatures/azure-toolkit-for-rider/azure-intellij-plugin-appservice-dotnet/src/main/kotlin/com/microsoft/azure/toolkit/intellij/legacy/webapp/runner/webappconfig/WebAppRunState.kt b/PluginsAndFeatures/azure-toolkit-for-rider/azure-intellij-plugin-appservice-dotnet/src/main/kotlin/com/microsoft/azure/toolkit/intellij/legacy/webapp/runner/webappconfig/WebAppRunState.kt
index c4b2a08632..cf1fd6821d 100644
--- a/PluginsAndFeatures/azure-toolkit-for-rider/azure-intellij-plugin-appservice-dotnet/src/main/kotlin/com/microsoft/azure/toolkit/intellij/legacy/webapp/runner/webappconfig/WebAppRunState.kt
+++ b/PluginsAndFeatures/azure-toolkit-for-rider/azure-intellij-plugin-appservice-dotnet/src/main/kotlin/com/microsoft/azure/toolkit/intellij/legacy/webapp/runner/webappconfig/WebAppRunState.kt
@@ -12,11 +12,12 @@ import com.jetbrains.rider.model.publishableProjectsModel
import com.jetbrains.rider.projectView.solution
import com.microsoft.azure.toolkit.intellij.appservice.webapp.CreateOrUpdateDotNetWebAppTask
import com.microsoft.azure.toolkit.intellij.appservice.webapp.DotNetAppServiceConfig
-import com.microsoft.azure.toolkit.intellij.appservice.webapp.DotNetRuntimeConfig
+import com.microsoft.azure.toolkit.intellij.appservice.DotNetRuntimeConfig
import com.microsoft.azure.toolkit.intellij.appservice.webapp.DotNetWebAppDeploymentSlotDraft
import com.microsoft.azure.toolkit.intellij.common.RunProcessHandler
import com.microsoft.azure.toolkit.intellij.legacy.common.RiderAzureRunProfileState
-import com.microsoft.azure.toolkit.intellij.legacy.webapp.runner.WebAppArtifactService
+import com.microsoft.azure.toolkit.intellij.legacy.getStackAndVersion
+import com.microsoft.azure.toolkit.intellij.legacy.ArtifactService
import com.microsoft.azure.toolkit.lib.appservice.config.RuntimeConfig
import com.microsoft.azure.toolkit.lib.appservice.model.*
import com.microsoft.azure.toolkit.lib.appservice.task.DeployWebAppTask
@@ -35,6 +36,8 @@ class WebAppRunState(project: Project, private val webAppConfiguration: WebAppCo
override fun executeSteps(processHandler: RunProcessHandler): WebAppBase<*, *, *> {
OperationContext.current().setMessager(processHandlerMessenger)
+ processHandler.setText("Start Web App deployment")
+
val publishableProjectPath = webAppConfiguration.publishableProjectPath
?: throw RuntimeException("Project is not defined")
val publishableProject = project.solution.publishableProjectsModel.publishableProjects.values
@@ -45,12 +48,13 @@ class WebAppRunState(project: Project, private val webAppConfiguration: WebAppCo
val createTask = CreateOrUpdateDotNetWebAppTask(config)
val deployTarget = createTask.execute()
- val zipFile = WebAppArtifactService.getInstance(project)
+ val zipFile = ArtifactService.getInstance(project)
.prepareArtifact(
publishableProject,
webAppConfiguration.projectConfiguration,
webAppConfiguration.projectPlatform,
- processHandler
+ processHandler,
+ true
)
val artifact = WebAppArtifact.builder()
.file(zipFile)
@@ -77,7 +81,6 @@ class WebAppRunState(project: Project, private val webAppConfiguration: WebAppCo
runtime(createRuntimeConfig())
dotnetRuntime = createDotNetRuntimeConfig(publishableProject)
appSettings(webAppConfiguration.applicationSettings)
- appSettingsToRemove(webAppConfiguration.appSettingsToRemove)
val slotName =
if (webAppConfiguration.isDeployToSlot) webAppConfiguration.newSlotName ?: webAppConfiguration.slotName
else null
@@ -130,11 +133,10 @@ class WebAppRunState(project: Project, private val webAppConfiguration: WebAppCo
webAppId = app.id
}
applicationSettings = app.appSettings ?: emptyMap()
- appSettingsToRemove = emptySet()
webAppName = app.name
resourceGroup = app.resourceGroupName
- appServicePlanName = app.getAppServicePlan()?.name
- appServicePlanResourceGroupName = app.getAppServicePlan()?.resourceGroupName
+ appServicePlanName = app.appServicePlan?.name
+ appServicePlanResourceGroupName = app.appServicePlan?.resourceGroupName
}
}
@@ -145,7 +147,6 @@ class WebAppRunState(project: Project, private val webAppConfiguration: WebAppCo
when (ex) {
is IOException,
is URISyntaxException -> processHandler.println(ex.message, ProcessOutputTypes.STDERR)
-
else -> throw ex
}
}
diff --git a/PluginsAndFeatures/azure-toolkit-for-rider/azure-intellij-plugin-appservice-dotnet/src/main/kotlin/com/microsoft/azure/toolkit/intellij/legacy/webapp/runner/webappconfig/WebAppSettingEditor.kt b/PluginsAndFeatures/azure-toolkit-for-rider/azure-intellij-plugin-appservice-dotnet/src/main/kotlin/com/microsoft/azure/toolkit/intellij/legacy/webapp/runner/webappconfig/WebAppSettingEditor.kt
index c0fd016745..2750115015 100644
--- a/PluginsAndFeatures/azure-toolkit-for-rider/azure-intellij-plugin-appservice-dotnet/src/main/kotlin/com/microsoft/azure/toolkit/intellij/legacy/webapp/runner/webappconfig/WebAppSettingEditor.kt
+++ b/PluginsAndFeatures/azure-toolkit-for-rider/azure-intellij-plugin-appservice-dotnet/src/main/kotlin/com/microsoft/azure/toolkit/intellij/legacy/webapp/runner/webappconfig/WebAppSettingEditor.kt
@@ -8,7 +8,8 @@ import com.intellij.openapi.project.Project
import com.microsoft.azure.toolkit.intellij.legacy.common.RiderAzureSettingsEditor
class WebAppSettingEditor(project: Project, configuration: WebAppConfiguration) :
- RiderAzureSettingsEditor() {
+ RiderAzureSettingsEditor() {
+
private val panel = WebAppSettingPanel(project, configuration)
override fun getPanel() = panel
}
\ No newline at end of file
diff --git a/PluginsAndFeatures/azure-toolkit-for-rider/azure-intellij-plugin-appservice-dotnet/src/main/kotlin/com/microsoft/azure/toolkit/intellij/legacy/webapp/runner/webappconfig/WebAppSettingPanel.kt b/PluginsAndFeatures/azure-toolkit-for-rider/azure-intellij-plugin-appservice-dotnet/src/main/kotlin/com/microsoft/azure/toolkit/intellij/legacy/webapp/runner/webappconfig/WebAppSettingPanel.kt
index 47aae8d031..3cc2ede2e7 100644
--- a/PluginsAndFeatures/azure-toolkit-for-rider/azure-intellij-plugin-appservice-dotnet/src/main/kotlin/com/microsoft/azure/toolkit/intellij/legacy/webapp/runner/webappconfig/WebAppSettingPanel.kt
+++ b/PluginsAndFeatures/azure-toolkit-for-rider/azure-intellij-plugin-appservice-dotnet/src/main/kotlin/com/microsoft/azure/toolkit/intellij/legacy/webapp/runner/webappconfig/WebAppSettingPanel.kt
@@ -40,8 +40,7 @@ class WebAppSettingPanel(private val project: Project, configuration: WebAppConf
override fun apply(configuration: WebAppConfiguration) {
val runConfigurationModel = webAppPanel.value
- val projectConfiguration = webAppPanel.getSelectedConfiguration()
- val projectPlatform = webAppPanel.getSelectedPlatform()
+ val (projectConfiguration, projectPlatform) = webAppPanel.getConfigurationAndPlatform()
val publishableProject = runConfigurationModel.artifactConfig?.let {
val artifactId = it.artifactIdentifier.toIntOrNull() ?: return@let null
project.solution.publishableProjectsModel.publishableProjects.values
@@ -56,7 +55,6 @@ class WebAppSettingPanel(private val project: Project, configuration: WebAppConf
configuration.webAppName = it.name
configuration.runtime = it.runtime
configuration.applicationSettings = it.appSettings
- configuration.appSettingsToRemove = it.appSettingsToRemove
configuration.isCreatingNew = it.resourceId.isNullOrEmpty()
if (configuration.isCreatingNew) {
@@ -142,7 +140,6 @@ class WebAppSettingPanel(private val project: Project, configuration: WebAppConf
.servicePlan(plan)
.deploymentSlot(slotConfig)
.appSettings(configuration.applicationSettings)
- .appSettingsToRemove(configuration.appSettingsToRemove)
val webAppConfig =
if (configuration.isCreatingNew) configBuilder.region(region).pricingTier(pricingTier).build()
else configBuilder.build()
diff --git a/PluginsAndFeatures/azure-toolkit-for-rider/azure-intellij-plugin-appservice-dotnet/src/main/kotlin/com/microsoft/azure/toolkit/intellij/legacy/webapp/runner/webappcontainers/DockerPushConfiguration.kt b/PluginsAndFeatures/azure-toolkit-for-rider/azure-intellij-plugin-appservice-dotnet/src/main/kotlin/com/microsoft/azure/toolkit/intellij/legacy/webapp/runner/webappcontainers/DockerPushConfiguration.kt
deleted file mode 100644
index d83c05a449..0000000000
--- a/PluginsAndFeatures/azure-toolkit-for-rider/azure-intellij-plugin-appservice-dotnet/src/main/kotlin/com/microsoft/azure/toolkit/intellij/legacy/webapp/runner/webappcontainers/DockerPushConfiguration.kt
+++ /dev/null
@@ -1,15 +0,0 @@
-/*
- * Copyright 2018-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the MIT license.
- */
-
-package com.microsoft.azure.toolkit.intellij.legacy.webapp.runner.webappcontainers
-
-import com.microsoft.azure.toolkit.intellij.common.DockerImageModel
-
-data class DockerPushConfiguration(
- val registryAddress: String?,
- val repositoryName: String?,
- val tagName: String?,
- val dockerImage: DockerImageModel?,
- val dockerServer: String?
-)
\ No newline at end of file
diff --git a/PluginsAndFeatures/azure-toolkit-for-rider/azure-intellij-plugin-appservice-dotnet/src/main/kotlin/com/microsoft/azure/toolkit/intellij/legacy/webapp/runner/webappcontainers/WebAppContainersConfigurationType.kt b/PluginsAndFeatures/azure-toolkit-for-rider/azure-intellij-plugin-appservice-dotnet/src/main/kotlin/com/microsoft/azure/toolkit/intellij/legacy/webapp/runner/webappcontainers/WebAppContainersConfigurationType.kt
index 81e82f4233..79f6c02422 100644
--- a/PluginsAndFeatures/azure-toolkit-for-rider/azure-intellij-plugin-appservice-dotnet/src/main/kotlin/com/microsoft/azure/toolkit/intellij/legacy/webapp/runner/webappcontainers/WebAppContainersConfigurationType.kt
+++ b/PluginsAndFeatures/azure-toolkit-for-rider/azure-intellij-plugin-appservice-dotnet/src/main/kotlin/com/microsoft/azure/toolkit/intellij/legacy/webapp/runner/webappcontainers/WebAppContainersConfigurationType.kt
@@ -18,7 +18,7 @@ class WebAppContainersConfigurationType : SimpleConfigurationType(
"AzureWebAppContainersPublish",
"Azure - Web App for Containers",
"Azure Publish Web App for Containers configuration",
- NotNullLazyValue.createValue {IntelliJAzureIcons.getIcon(AzureIcons.WebApp.MODULE) }
+ NotNullLazyValue.createValue { IntelliJAzureIcons.getIcon(AzureIcons.WebApp.MODULE) }
) {
companion object {
fun getInstance() = ConfigurationTypeUtil.findConfigurationType(WebAppContainersConfigurationType::class.java)
diff --git a/PluginsAndFeatures/azure-toolkit-for-rider/azure-intellij-plugin-appservice-dotnet/src/main/kotlin/com/microsoft/azure/toolkit/intellij/legacy/webapp/runner/webappcontainers/WebAppContainersRunState.kt b/PluginsAndFeatures/azure-toolkit-for-rider/azure-intellij-plugin-appservice-dotnet/src/main/kotlin/com/microsoft/azure/toolkit/intellij/legacy/webapp/runner/webappcontainers/WebAppContainersRunState.kt
index cda8ccd572..aeea185889 100644
--- a/PluginsAndFeatures/azure-toolkit-for-rider/azure-intellij-plugin-appservice-dotnet/src/main/kotlin/com/microsoft/azure/toolkit/intellij/legacy/webapp/runner/webappcontainers/WebAppContainersRunState.kt
+++ b/PluginsAndFeatures/azure-toolkit-for-rider/azure-intellij-plugin-appservice-dotnet/src/main/kotlin/com/microsoft/azure/toolkit/intellij/legacy/webapp/runner/webappcontainers/WebAppContainersRunState.kt
@@ -7,7 +7,7 @@ package com.microsoft.azure.toolkit.intellij.legacy.webapp.runner.webappcontaine
import com.intellij.openapi.project.Project
import com.microsoft.azure.toolkit.intellij.appservice.webapp.CreateOrUpdateDotNetWebAppTask
import com.microsoft.azure.toolkit.intellij.appservice.webapp.DotNetAppServiceConfig
-import com.microsoft.azure.toolkit.intellij.appservice.webapp.DotNetRuntimeConfig
+import com.microsoft.azure.toolkit.intellij.appservice.DotNetRuntimeConfig
import com.microsoft.azure.toolkit.intellij.common.RunProcessHandler
import com.microsoft.azure.toolkit.intellij.legacy.common.RiderAzureRunProfileState
import com.microsoft.azure.toolkit.lib.appservice.AppServiceAppBase
diff --git a/PluginsAndFeatures/azure-toolkit-for-rider/azure-intellij-plugin-lib-dotnet/src/main/kotlin/com/microsoft/azure/toolkit/intellij/common/PublishConfigurationComboBoxExtensions.kt b/PluginsAndFeatures/azure-toolkit-for-rider/azure-intellij-plugin-lib-dotnet/src/main/kotlin/com/microsoft/azure/toolkit/intellij/common/PublishConfigurationComboBoxExtensions.kt
new file mode 100644
index 0000000000..d616086a72
--- /dev/null
+++ b/PluginsAndFeatures/azure-toolkit-for-rider/azure-intellij-plugin-lib-dotnet/src/main/kotlin/com/microsoft/azure/toolkit/intellij/common/PublishConfigurationComboBoxExtensions.kt
@@ -0,0 +1,22 @@
+package com.microsoft.azure.toolkit.intellij.common
+
+import com.intellij.openapi.ui.ComboBox
+import com.jetbrains.rider.run.configurations.publishing.PublishRuntimeSettingsCoreHelper
+
+fun ComboBox.setPublishConfiguration(
+ configuration: String,
+ platform: String
+) {
+ for (i in 0 until model.size) {
+ val item = model.getElementAt(i)
+ if (item?.configuration == configuration && item.platform == platform) {
+ selectedItem = item
+ break
+ }
+ }
+}
+
+fun ComboBox.getPublishConfiguration(): Pair {
+ val item = selectedItem as? PublishRuntimeSettingsCoreHelper.ConfigurationAndPlatform
+ return (item?.configuration ?: "") to (item?.platform ?: "")
+}
\ No newline at end of file