From fc6e95e04f24ebbf0d4d3ff466d6fe295ccfb276 Mon Sep 17 00:00:00 2001 From: Hanxiao Liu Date: Tue, 17 Aug 2021 16:35:39 +0800 Subject: [PATCH 001/126] Extract schema for shared azure properties --- azure-maven-plugin-lib/pom.xml | 9 + .../maven/AzureAppServiceMavenPlugin.json | 78 +++++ .../azure-toolkit-common-lib/pom.xml | 9 + .../schema/appservice/AppServiceName.json | 9 + .../schema/appservice/AppServicePlanName.json | 9 + .../schema/appservice/DeploymentSlotName.json | 9 + .../resources/schema/appservice/Runtime.json | 77 +++++ .../schema/common/AuthConfiguration.json | 83 ++++++ .../schema/common/AzureEnvironment.json | 8 + .../schema/common/NonEmptyString.json | 7 + .../schema/common/ResourceGroupName.json | 9 + .../resources/schema/WebAppConfiguration.json | 269 ++---------------- 12 files changed, 327 insertions(+), 249 deletions(-) create mode 100644 azure-maven-plugin-lib/src/main/resources/schema/maven/AzureAppServiceMavenPlugin.json create mode 100644 azure-toolkit-libs/azure-toolkit-common-lib/src/main/resources/schema/appservice/AppServiceName.json create mode 100644 azure-toolkit-libs/azure-toolkit-common-lib/src/main/resources/schema/appservice/AppServicePlanName.json create mode 100644 azure-toolkit-libs/azure-toolkit-common-lib/src/main/resources/schema/appservice/DeploymentSlotName.json create mode 100644 azure-toolkit-libs/azure-toolkit-common-lib/src/main/resources/schema/appservice/Runtime.json create mode 100644 azure-toolkit-libs/azure-toolkit-common-lib/src/main/resources/schema/common/AuthConfiguration.json create mode 100644 azure-toolkit-libs/azure-toolkit-common-lib/src/main/resources/schema/common/AzureEnvironment.json create mode 100644 azure-toolkit-libs/azure-toolkit-common-lib/src/main/resources/schema/common/NonEmptyString.json create mode 100644 azure-toolkit-libs/azure-toolkit-common-lib/src/main/resources/schema/common/ResourceGroupName.json diff --git a/azure-maven-plugin-lib/pom.xml b/azure-maven-plugin-lib/pom.xml index e3f98bb180..4f5962d50a 100644 --- a/azure-maven-plugin-lib/pom.xml +++ b/azure-maven-plugin-lib/pom.xml @@ -177,6 +177,15 @@ + + + src/main/resources + true + + schema/**/*.json + + + org.apache.maven.plugins diff --git a/azure-maven-plugin-lib/src/main/resources/schema/maven/AzureAppServiceMavenPlugin.json b/azure-maven-plugin-lib/src/main/resources/schema/maven/AzureAppServiceMavenPlugin.json new file mode 100644 index 0000000000..9be88e1eaa --- /dev/null +++ b/azure-maven-plugin-lib/src/main/resources/schema/maven/AzureAppServiceMavenPlugin.json @@ -0,0 +1,78 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "Configuration", + "description": "Configuration for Maven plugin for Azure Web App", + "properties": { + "subscriptionId": { + "$ref": "classpath:///schema/common/NonEmptyString.json" + }, + "resourceGroup": { + "$ref": "classpath:///schema/common/ResourceGroup.json" + }, + "appName": { + "$ref": "classpath:///schema/appservice/AppServiceName.json" + }, + "appServicePlanName": { + "$ref": "classpath:///schema/appservice/AppServicePlanName.json" + }, + "appServicePlanResourceGroup": { + "$ref": "classpath:///schema/common/ResourceGroup.json" + }, + "auth": { + "$ref": "#/definitions/auth" + }, + "deploymentSlot": { + "$ref": "#/definitions/deployment-slot" + }, + "appSettings": { + "type": "object" + }, + "allowTelemetry": { + "type": "boolean", + "default": true + }, + "failsOnError": { + "type": "boolean", + "default": true + }, + "authType": { + "$ref": "classpath:///schema/common/AuthConfiguration.json#/definitions/auth-type", + "deprecationMessage": "Please set auth related properties like type in " + } + }, + "required": [ + "appName", + "resourceGroup" + ], + "definitions": { + "deployment-slot": { + "title": "DeploymentSlotConfiguration", + "description": "Deployment slot configuration for Maven plugin for Azure Web App", + "type": "object", + "properties": { + "name": { + "$ref": "classpath:///schema/appservice/DeploymentSlotName.json" + }, + "configurationSource": { + "$ref": "classpath:///schema/common/NonEmptyString.json" + } + }, + "required": [ + "name" + ] + }, + "auth": { + "title": "AuthConfiguration", + "description": "The auth config for accessing azure resources for maven", + "type": "object", + "properties": { + "serverId": { + "$ref": "classpath:///schema/common/NonEmptyString.json" + } + }, + "allOf": [ + {"$ref": "classpath:///schema/common/AuthConfiguration.json"} + ] + } + } +} diff --git a/azure-toolkit-libs/azure-toolkit-common-lib/pom.xml b/azure-toolkit-libs/azure-toolkit-common-lib/pom.xml index 8d99f15bfb..4b22791174 100644 --- a/azure-toolkit-libs/azure-toolkit-common-lib/pom.xml +++ b/azure-toolkit-libs/azure-toolkit-common-lib/pom.xml @@ -120,6 +120,15 @@ + + + src/main/resources + true + + schema/**/*.json + + + diff --git a/azure-toolkit-libs/azure-toolkit-common-lib/src/main/resources/schema/appservice/AppServiceName.json b/azure-toolkit-libs/azure-toolkit-common-lib/src/main/resources/schema/appservice/AppServiceName.json new file mode 100644 index 0000000000..e0f9cd6f66 --- /dev/null +++ b/azure-toolkit-libs/azure-toolkit-common-lib/src/main/resources/schema/appservice/AppServiceName.json @@ -0,0 +1,9 @@ +{ + "title": "App Service Name", + "$schema": "http://json-schema.org/draft-07/schema#", + "description": "Name for Azure App Service", + "type": "string", + "pattern": "^[a-zA-Z0-9\\-]+$", + "minLength": 2, + "maxLength": 60 +} \ No newline at end of file diff --git a/azure-toolkit-libs/azure-toolkit-common-lib/src/main/resources/schema/appservice/AppServicePlanName.json b/azure-toolkit-libs/azure-toolkit-common-lib/src/main/resources/schema/appservice/AppServicePlanName.json new file mode 100644 index 0000000000..12b8085ee2 --- /dev/null +++ b/azure-toolkit-libs/azure-toolkit-common-lib/src/main/resources/schema/appservice/AppServicePlanName.json @@ -0,0 +1,9 @@ +{ + "title": "App Service Name", + "$schema": "http://json-schema.org/draft-07/schema#", + "description": "Name for Azure App Service", + "type": "string", + "pattern": "^[a-zA-Z0-9\\-]+$", + "minLength": 1, + "maxLength": 40 +} \ No newline at end of file diff --git a/azure-toolkit-libs/azure-toolkit-common-lib/src/main/resources/schema/appservice/DeploymentSlotName.json b/azure-toolkit-libs/azure-toolkit-common-lib/src/main/resources/schema/appservice/DeploymentSlotName.json new file mode 100644 index 0000000000..686718f982 --- /dev/null +++ b/azure-toolkit-libs/azure-toolkit-common-lib/src/main/resources/schema/appservice/DeploymentSlotName.json @@ -0,0 +1,9 @@ +{ + "title": "App Service Name", + "$schema": "http://json-schema.org/draft-07/schema#", + "description": "Name for Azure App Service", + "type": "string", + "pattern": "^[A-Za-z0-9-]+$", + "minLength": 1, + "maxLength": 60 +} \ No newline at end of file diff --git a/azure-toolkit-libs/azure-toolkit-common-lib/src/main/resources/schema/appservice/Runtime.json b/azure-toolkit-libs/azure-toolkit-common-lib/src/main/resources/schema/appservice/Runtime.json new file mode 100644 index 0000000000..245bb4b9d7 --- /dev/null +++ b/azure-toolkit-libs/azure-toolkit-common-lib/src/main/resources/schema/appservice/Runtime.json @@ -0,0 +1,77 @@ +{ + "title": "Runtime", + "$schema": "http://json-schema.org/draft-07/schema#", + "description": "Runtime configuration for Maven plugin for App Service", + "type": "object", + "properties": { + "os": { + "description": "The operating system for app service", + "type": "string", + "pattern": "(?i)^(windows|linux|docker)$" + }, + "webContainer": { + "$ref": "classpath:///schema/common/NonEmptyString.json" + }, + "javaVersion": { + "$ref": "classpath:///schema/common/NonEmptyString.json" + }, + "image": { + "$ref": "classpath:///schema/common/NonEmptyString.json" + }, + "serverId": { + "$ref": "classpath:///schema/common/NonEmptyString.json" + }, + "registryUrl": { + "type": "string", + "pattern": "^https.*" + } + }, + "dependencies": { + "serverId": [ + "image" + ], + "registryUrl": [ + "image" + ] + }, + "required": [ + "os" + ], + "allOf": [ + { + "if": { + "properties": { + "os": { + "pattern": "(?i)^(windows|linux)$" + } + }, + "required": [ + "os" + ] + }, + "then": { + "required": [ + "javaVersion", + "webContainer" + ] + } + }, + { + "if": { + "properties": { + "os": { + "pattern": "(?i)^(docker)$" + } + }, + "required": [ + "os" + ] + }, + "then": { + "required": [ + "image" + ] + } + } + ] +} diff --git a/azure-toolkit-libs/azure-toolkit-common-lib/src/main/resources/schema/common/AuthConfiguration.json b/azure-toolkit-libs/azure-toolkit-common-lib/src/main/resources/schema/common/AuthConfiguration.json new file mode 100644 index 0000000000..f5c31e1808 --- /dev/null +++ b/azure-toolkit-libs/azure-toolkit-common-lib/src/main/resources/schema/common/AuthConfiguration.json @@ -0,0 +1,83 @@ +{ + "title": "AuthConfiguration", + "$schema": "http://json-schema.org/draft-07/schema#", + "description": "The auth config for accessing azure resources", + "type": "object", + "properties": { + "type": { + "$ref": "#/definitions/auth-type" + }, + "client": { + "description": "Client ID", + "type": "string" + }, + "tenant": { + "description": "Tenant ID", + "type": "string" + }, + "key": { + "description": "Password", + "type": "string" + }, + "certificate": { + "description": "The absolute path of your certificate", + "type": "string" + }, + "certificatePassword": { + "description": "The password for your certificate, if there is any", + "type": "string" + }, + "environment": { + "$ref": "classpath:///schema/common/AzureEnvironment.json" + } + }, + "allOf": [ + { + "if": { + "properties": { + "type": { + "pattern": "(?i)^service_principal$" + } + }, + "required": [ + "type" + ] + }, + "then": { + "anyOf": [ + { + "required": [ + "client", + "tenant", + "key" + ] + }, + { + "required": [ + "client", + "tenant", + "certificate" + ] + } + ] + } + } + ], + "not": { + "required": [ + "key", + "certificate" + ] + }, + "dependencies": { + "certificatePassword": [ + "certificate" + ] + }, + "definitions": { + "auth-type": { + "type": "string", + "pattern": "(?i)^(auto|service_principal|managed_identity|azure_cli|vscode|intellij|azure_auth_maven_plugin|device_code|oauth2|visual_studio)$" + } + } +} diff --git a/azure-toolkit-libs/azure-toolkit-common-lib/src/main/resources/schema/common/AzureEnvironment.json b/azure-toolkit-libs/azure-toolkit-common-lib/src/main/resources/schema/common/AzureEnvironment.json new file mode 100644 index 0000000000..427d5e6ea3 --- /dev/null +++ b/azure-toolkit-libs/azure-toolkit-common-lib/src/main/resources/schema/common/AzureEnvironment.json @@ -0,0 +1,8 @@ +{ + "title": "Azure Environment", + "$schema": "http://json-schema.org/draft-07/schema#", + "description": "The Azure cloud environment", + "type": "string", + "default": "AZURE", + "pattern": "(?i)^(AZURE|AZURE_CHINA|AZURE_GERMANY|AZURE_US_GOVERNMENT)$" +} \ No newline at end of file diff --git a/azure-toolkit-libs/azure-toolkit-common-lib/src/main/resources/schema/common/NonEmptyString.json b/azure-toolkit-libs/azure-toolkit-common-lib/src/main/resources/schema/common/NonEmptyString.json new file mode 100644 index 0000000000..a1e59ceb75 --- /dev/null +++ b/azure-toolkit-libs/azure-toolkit-common-lib/src/main/resources/schema/common/NonEmptyString.json @@ -0,0 +1,7 @@ +{ + "title": "None Empty String", + "$schema": "http://json-schema.org/draft-07/schema#", + "description": "Schema for non-empty string", + "type": "string", + "minLength": 1 +} \ No newline at end of file diff --git a/azure-toolkit-libs/azure-toolkit-common-lib/src/main/resources/schema/common/ResourceGroupName.json b/azure-toolkit-libs/azure-toolkit-common-lib/src/main/resources/schema/common/ResourceGroupName.json new file mode 100644 index 0000000000..21dbc75d2d --- /dev/null +++ b/azure-toolkit-libs/azure-toolkit-common-lib/src/main/resources/schema/common/ResourceGroupName.json @@ -0,0 +1,9 @@ +{ + "title": "Azure Resource Group", + "$schema": "http://json-schema.org/draft-07/schema#", + "description": "The auth config for accessing azure resources", + "type": "string", + "pattern": "^[a-zA-Z0-9\\.\\_\\-\\(\\)]+$", + "minLength": 2, + "maxLength": 90 +} \ No newline at end of file diff --git a/azure-webapp-maven-plugin/src/main/resources/schema/WebAppConfiguration.json b/azure-webapp-maven-plugin/src/main/resources/schema/WebAppConfiguration.json index 9cd35a427f..d08b331353 100644 --- a/azure-webapp-maven-plugin/src/main/resources/schema/WebAppConfiguration.json +++ b/azure-webapp-maven-plugin/src/main/resources/schema/WebAppConfiguration.json @@ -3,55 +3,8 @@ "title": "Configuration", "description": "Configuration for Maven plugin for Azure Web App", "properties": { - "subscriptionId": { - "$ref": "#/definitions/non-empty-string" - }, - "resourceGroup": { - "$ref": "#/definitions/azure-resource-group" - }, - "appName": { - "type": "string", - "pattern": "^[a-zA-Z0-9\\-]+$", - "minLength": 2, - "maxLength": 60 - }, - "appServicePlanName": { - "type": "string", - "pattern": "^[a-zA-Z0-9\\-]+$", - "minLength": 1, - "maxLength": 40 - }, - "appServicePlanResourceGroup": { - "$ref": "#/definitions/azure-resource-group" - }, - "auth": { - "$ref": "#/definitions/auth" - }, - "region": { - "$ref": "#/definitions/non-empty-string" - }, "pricingTier": { - "$ref": "#/definitions/non-empty-string" - }, - "runtime": { - "$ref": "#/definitions/runtime" - }, - "deployment": { - "$ref": "#/definitions/deployment" - }, - "deploymentSlot": { - "$ref": "#/definitions/deployment-slot" - }, - "appSettings": { - "type": "object" - }, - "allowTelemetry": { - "type": "boolean", - "default": true - }, - "failsOnError": { - "type": "boolean", - "default": true + "$ref": "classpath:///schema/common/NonEmptyString.json" }, "stopAppDuringDeployment": { "type": "boolean", @@ -61,208 +14,26 @@ "type": "boolean", "default": false }, - "authType": { - "$ref": "#/definitions/auth-type", - "deprecationMessage": "Please set auth related properties like type in " - } - }, - "required": [ - "appName", - "resourceGroup" - ], - "definitions": { - "non-empty-string": { - "type": "string", - "minLength": 1 - }, - "auth-type": { - "type": "string", - "pattern": "(?i)^(auto|service_principal|managed_identity|azure_cli|vscode|intellij|azure_auth_maven_plugin|device_code|oauth2|visual_studio)$" + "region": { + "$ref": "classpath:///schema/common/NonEmptyString.json" }, - "azure-resource-group": { + "schemaVersion": { "type": "string", - "pattern": "^[a-zA-Z0-9._\\-()]+$", - "minLength": 1, - "maxLength": 90 - }, - "deployment-slot": { - "title": "DeploymentSlotConfiguration", - "description": "Deployment slot configuration for Maven plugin for Azure Web App", - "type": "object", - "properties": { - "name": { - "type": "string", - "pattern": "^[A-Za-z0-9-]+$", - "minLength": 1, - "maxLength": 60 - }, - "configurationSource": { - "$ref": "#/definitions/non-empty-string" - } - }, - "required": [ - "name" - ] + "deprecationMessage": " has been deprecated, only v2 schema is supported now" }, "runtime": { - "title": "Runtime", - "description": "Runtime configuration for Maven plugin for Azure Web App", - "type": "object", - "properties": { - "os": { - "description": "The operating system for app service", - "type": "string", - "pattern": "(?i)^(windows|linux|docker)$" - }, - "webContainer": { - "$ref": "#/definitions/non-empty-string" - }, - "javaVersion": { - "$ref": "#/definitions/non-empty-string" - }, - "image": { - "$ref": "#/definitions/non-empty-string" - }, - "serverId": { - "$ref": "#/definitions/non-empty-string" - }, - "registryUrl": { - "type": "string", - "pattern": "^https.*" - } - }, - "dependencies": { - "serverId": [ - "image" - ], - "registryUrl": [ - "image" - ] - }, - "required": [ - "os" - ], - "allOf": [ - { - "if": { - "properties": { - "os": { - "pattern": "(?i)^(windows|linux)$" - } - }, - "required": [ - "os" - ] - }, - "then": { - "required": [ - "javaVersion", - "webContainer" - ] - } - }, - { - "if": { - "properties": { - "os": { - "pattern": "(?i)^(docker)$" - } - }, - "required": [ - "os" - ] - }, - "then": { - "required": [ - "image" - ] - } - } - ] - }, - "auth": { - "title": "AuthConfiguration", - "description": "The auth config for accessing azure resources", - "type": "object", - "properties": { - "type": { - "$ref": "#/definitions/auth-type" - }, - "serverId": { - "description": "The server id defined in maven settings", - "type": "string" - }, - "client": { - "description": "Client ID", - "type": "string" - }, - "tenant": { - "description": "Tenant ID", - "type": "string" - }, - "key": { - "description": "Password", - "type": "string" - }, - "certificate": { - "description": "The absolute path of your certificate", - "type": "string" - }, - "certificatePassword": { - "description": "The password for your certificate, if there is any", - "type": "string" - }, - "environment": { - "description": "The Azure cloud environment", - "type": "string", - "default": "AZURE", - "pattern": "(?i)^(AZURE|AZURE_CHINA|AZURE_GERMANY|AZURE_US_GOVERNMENT)$" - } - }, - "allOf": [ - { - "if": { - "properties": { - "type": { - "pattern": "(?i)^service_principal$" - } - }, - "required": [ - "type" - ] - }, - "then": { - "anyOf": [ - { - "required": [ - "client", - "tenant", - "key" - ] - }, - { - "required": [ - "client", - "tenant", - "certificate" - ] - } - ] - } - } - ], - "not": { - "required": [ - "key", - "certificate" - ] - }, - "dependencies": { - "certificatePassword": [ - "certificate" - ] - } + "$ref": "classpath:///schema/appservice/Runtime.json" }, + "deployment": { + "$ref": "#/definitions/deployment" + } + }, + "allOf": [ + { + "$ref": "classpath:///schema/maven/AzureAppServiceMavenPlugin.json" + } + ], + "definitions": { "deployment-resource": { "type": "object", "title": "Deployment Resource", @@ -273,21 +44,21 @@ "pattern": "(?i)^(war|jar|ear|lib|script|static|startup|zip)$" }, "directory": { - "$ref": "#/definitions/non-empty-string" + "$ref": "classpath:///schema/common/NonEmptyString.json" }, "targetPath": { - "$ref": "#/definitions/non-empty-string" + "$ref": "classpath:///schema/common/NonEmptyString.json" }, "includes": { "type": "array", "items": { - "$ref": "#/definitions/non-empty-string" + "$ref": "classpath:///schema/common/NonEmptyString.json" } }, "excludes": { "type": "array", "items": { - "$ref": "#/definitions/non-empty-string" + "$ref": "classpath:///schema/common/NonEmptyString.json" } } } From 69d14e2a8f86bc2e9448d7b6dd9810f2e8a58918 Mon Sep 17 00:00:00 2001 From: Hanxiao Liu Date: Wed, 18 Aug 2021 13:45:55 +0800 Subject: [PATCH 002/126] Fix style and description typo for shared schema --- .../resources/schema/maven/AzureAppServiceMavenPlugin.json | 4 ++-- .../main/resources/schema/appservice/AppServiceName.json | 2 +- .../resources/schema/appservice/AppServicePlanName.json | 6 +++--- .../resources/schema/appservice/DeploymentSlotName.json | 6 +++--- .../src/main/resources/schema/common/AzureEnvironment.json | 2 +- .../src/main/resources/schema/common/NonEmptyString.json | 2 +- .../src/main/resources/schema/common/ResourceGroupName.json | 4 ++-- 7 files changed, 13 insertions(+), 13 deletions(-) diff --git a/azure-maven-plugin-lib/src/main/resources/schema/maven/AzureAppServiceMavenPlugin.json b/azure-maven-plugin-lib/src/main/resources/schema/maven/AzureAppServiceMavenPlugin.json index 9be88e1eaa..e6978475ee 100644 --- a/azure-maven-plugin-lib/src/main/resources/schema/maven/AzureAppServiceMavenPlugin.json +++ b/azure-maven-plugin-lib/src/main/resources/schema/maven/AzureAppServiceMavenPlugin.json @@ -7,7 +7,7 @@ "$ref": "classpath:///schema/common/NonEmptyString.json" }, "resourceGroup": { - "$ref": "classpath:///schema/common/ResourceGroup.json" + "$ref": "classpath:///schema/common/ResourceGroupName.json" }, "appName": { "$ref": "classpath:///schema/appservice/AppServiceName.json" @@ -16,7 +16,7 @@ "$ref": "classpath:///schema/appservice/AppServicePlanName.json" }, "appServicePlanResourceGroup": { - "$ref": "classpath:///schema/common/ResourceGroup.json" + "$ref": "classpath:///schema/common/ResourceGroupName.json" }, "auth": { "$ref": "#/definitions/auth" diff --git a/azure-toolkit-libs/azure-toolkit-common-lib/src/main/resources/schema/appservice/AppServiceName.json b/azure-toolkit-libs/azure-toolkit-common-lib/src/main/resources/schema/appservice/AppServiceName.json index e0f9cd6f66..5bc6a7c4fe 100644 --- a/azure-toolkit-libs/azure-toolkit-common-lib/src/main/resources/schema/appservice/AppServiceName.json +++ b/azure-toolkit-libs/azure-toolkit-common-lib/src/main/resources/schema/appservice/AppServiceName.json @@ -6,4 +6,4 @@ "pattern": "^[a-zA-Z0-9\\-]+$", "minLength": 2, "maxLength": 60 -} \ No newline at end of file +} diff --git a/azure-toolkit-libs/azure-toolkit-common-lib/src/main/resources/schema/appservice/AppServicePlanName.json b/azure-toolkit-libs/azure-toolkit-common-lib/src/main/resources/schema/appservice/AppServicePlanName.json index 12b8085ee2..954261e4bf 100644 --- a/azure-toolkit-libs/azure-toolkit-common-lib/src/main/resources/schema/appservice/AppServicePlanName.json +++ b/azure-toolkit-libs/azure-toolkit-common-lib/src/main/resources/schema/appservice/AppServicePlanName.json @@ -1,9 +1,9 @@ { - "title": "App Service Name", + "title": "App Service Plan Name", "$schema": "http://json-schema.org/draft-07/schema#", - "description": "Name for Azure App Service", + "description": "Name for Azure App Service Plan", "type": "string", "pattern": "^[a-zA-Z0-9\\-]+$", "minLength": 1, "maxLength": 40 -} \ No newline at end of file +} diff --git a/azure-toolkit-libs/azure-toolkit-common-lib/src/main/resources/schema/appservice/DeploymentSlotName.json b/azure-toolkit-libs/azure-toolkit-common-lib/src/main/resources/schema/appservice/DeploymentSlotName.json index 686718f982..4e1fdf3efd 100644 --- a/azure-toolkit-libs/azure-toolkit-common-lib/src/main/resources/schema/appservice/DeploymentSlotName.json +++ b/azure-toolkit-libs/azure-toolkit-common-lib/src/main/resources/schema/appservice/DeploymentSlotName.json @@ -1,9 +1,9 @@ { - "title": "App Service Name", + "title": "App Service Deployment Slot Name", "$schema": "http://json-schema.org/draft-07/schema#", - "description": "Name for Azure App Service", + "description": "Name for Azure App Service deployment slot", "type": "string", "pattern": "^[A-Za-z0-9-]+$", "minLength": 1, "maxLength": 60 -} \ No newline at end of file +} diff --git a/azure-toolkit-libs/azure-toolkit-common-lib/src/main/resources/schema/common/AzureEnvironment.json b/azure-toolkit-libs/azure-toolkit-common-lib/src/main/resources/schema/common/AzureEnvironment.json index 427d5e6ea3..cda609e0f4 100644 --- a/azure-toolkit-libs/azure-toolkit-common-lib/src/main/resources/schema/common/AzureEnvironment.json +++ b/azure-toolkit-libs/azure-toolkit-common-lib/src/main/resources/schema/common/AzureEnvironment.json @@ -5,4 +5,4 @@ "type": "string", "default": "AZURE", "pattern": "(?i)^(AZURE|AZURE_CHINA|AZURE_GERMANY|AZURE_US_GOVERNMENT)$" -} \ No newline at end of file +} diff --git a/azure-toolkit-libs/azure-toolkit-common-lib/src/main/resources/schema/common/NonEmptyString.json b/azure-toolkit-libs/azure-toolkit-common-lib/src/main/resources/schema/common/NonEmptyString.json index a1e59ceb75..29523c9705 100644 --- a/azure-toolkit-libs/azure-toolkit-common-lib/src/main/resources/schema/common/NonEmptyString.json +++ b/azure-toolkit-libs/azure-toolkit-common-lib/src/main/resources/schema/common/NonEmptyString.json @@ -4,4 +4,4 @@ "description": "Schema for non-empty string", "type": "string", "minLength": 1 -} \ No newline at end of file +} diff --git a/azure-toolkit-libs/azure-toolkit-common-lib/src/main/resources/schema/common/ResourceGroupName.json b/azure-toolkit-libs/azure-toolkit-common-lib/src/main/resources/schema/common/ResourceGroupName.json index 21dbc75d2d..7883f0a8bc 100644 --- a/azure-toolkit-libs/azure-toolkit-common-lib/src/main/resources/schema/common/ResourceGroupName.json +++ b/azure-toolkit-libs/azure-toolkit-common-lib/src/main/resources/schema/common/ResourceGroupName.json @@ -1,9 +1,9 @@ { "title": "Azure Resource Group", "$schema": "http://json-schema.org/draft-07/schema#", - "description": "The auth config for accessing azure resources", + "description": "Name for Azure Resource Group", "type": "string", "pattern": "^[a-zA-Z0-9\\.\\_\\-\\(\\)]+$", "minLength": 2, "maxLength": 90 -} \ No newline at end of file +} From a29e7b959b6b8983ad7558fd3736c944a710dcd9 Mon Sep 17 00:00:00 2001 From: Hanxiao Liu Date: Wed, 18 Aug 2021 13:51:15 +0800 Subject: [PATCH 003/126] Add common schema uuid and validate subsId/tenantId/clientId with uuid --- .../resources/schema/maven/AzureAppServiceMavenPlugin.json | 2 +- .../main/resources/schema/common/AuthConfiguration.json | 6 ++---- .../src/main/resources/schema/common/UUID.json | 7 +++++++ 3 files changed, 10 insertions(+), 5 deletions(-) create mode 100644 azure-toolkit-libs/azure-toolkit-common-lib/src/main/resources/schema/common/UUID.json diff --git a/azure-maven-plugin-lib/src/main/resources/schema/maven/AzureAppServiceMavenPlugin.json b/azure-maven-plugin-lib/src/main/resources/schema/maven/AzureAppServiceMavenPlugin.json index e6978475ee..ae0ed006d5 100644 --- a/azure-maven-plugin-lib/src/main/resources/schema/maven/AzureAppServiceMavenPlugin.json +++ b/azure-maven-plugin-lib/src/main/resources/schema/maven/AzureAppServiceMavenPlugin.json @@ -4,7 +4,7 @@ "description": "Configuration for Maven plugin for Azure Web App", "properties": { "subscriptionId": { - "$ref": "classpath:///schema/common/NonEmptyString.json" + "$ref": "classpath:///schema/common/UUID.json" }, "resourceGroup": { "$ref": "classpath:///schema/common/ResourceGroupName.json" diff --git a/azure-toolkit-libs/azure-toolkit-common-lib/src/main/resources/schema/common/AuthConfiguration.json b/azure-toolkit-libs/azure-toolkit-common-lib/src/main/resources/schema/common/AuthConfiguration.json index f5c31e1808..98c3218dd4 100644 --- a/azure-toolkit-libs/azure-toolkit-common-lib/src/main/resources/schema/common/AuthConfiguration.json +++ b/azure-toolkit-libs/azure-toolkit-common-lib/src/main/resources/schema/common/AuthConfiguration.json @@ -8,12 +8,10 @@ "$ref": "#/definitions/auth-type" }, "client": { - "description": "Client ID", - "type": "string" + "$ref": "classpath:///schema/common/UUID.json" }, "tenant": { - "description": "Tenant ID", - "type": "string" + "$ref": "classpath:///schema/common/UUID.json" }, "key": { "description": "Password", diff --git a/azure-toolkit-libs/azure-toolkit-common-lib/src/main/resources/schema/common/UUID.json b/azure-toolkit-libs/azure-toolkit-common-lib/src/main/resources/schema/common/UUID.json new file mode 100644 index 0000000000..5bd02ac18f --- /dev/null +++ b/azure-toolkit-libs/azure-toolkit-common-lib/src/main/resources/schema/common/UUID.json @@ -0,0 +1,7 @@ +{ + "title": "UUID", + "$schema": "http://json-schema.org/draft-07/schema#", + "description": "Universally Unique Identifier", + "type": "string", + "format": "uuid" +} From 854fafdada6527c8bdd21057ffa31dd01bf4d8f4 Mon Sep 17 00:00:00 2001 From: Hanxiao Liu Date: Tue, 17 Aug 2021 17:04:20 +0800 Subject: [PATCH 004/126] Fix validation issue for service principal authentication with severId --- .../maven/AzureAppServiceMavenPlugin.json | 78 ++++++++++++++++++- 1 file changed, 75 insertions(+), 3 deletions(-) diff --git a/azure-maven-plugin-lib/src/main/resources/schema/maven/AzureAppServiceMavenPlugin.json b/azure-maven-plugin-lib/src/main/resources/schema/maven/AzureAppServiceMavenPlugin.json index ae0ed006d5..fdda9c84fd 100644 --- a/azure-maven-plugin-lib/src/main/resources/schema/maven/AzureAppServiceMavenPlugin.json +++ b/azure-maven-plugin-lib/src/main/resources/schema/maven/AzureAppServiceMavenPlugin.json @@ -63,16 +63,88 @@ }, "auth": { "title": "AuthConfiguration", - "description": "The auth config for accessing azure resources for maven", + "$schema": "http://json-schema.org/draft-07/schema#", + "description": "The auth config for accessing azure resources", "type": "object", "properties": { + "type": { + "$ref": "classpath:///schema/common/AuthConfiguration.json#/definitions/auth-type" + }, + "client": { + "description": "Client ID", + "type": "string" + }, + "tenant": { + "description": "Tenant ID", + "type": "string" + }, "serverId": { "$ref": "classpath:///schema/common/NonEmptyString.json" + }, + "key": { + "description": "Password", + "type": "string" + }, + "certificate": { + "description": "The absolute path of your certificate", + "type": "string" + }, + "certificatePassword": { + "description": "The password for your certificate, if there is any", + "type": "string" + }, + "environment": { + "$ref": "classpath:///schema/common/AzureEnvironment.json" } }, "allOf": [ - {"$ref": "classpath:///schema/common/AuthConfiguration.json"} - ] + { + "if": { + "properties": { + "type": { + "pattern": "(?i)^service_principal$" + } + }, + "required": [ + "type" + ] + }, + "then": { + "anyOf": [ + { + "required": [ + "client", + "tenant", + "key" + ] + }, + { + "required": [ + "client", + "tenant", + "certificate" + ] + }, + { + "required": [ + "serverId" + ] + } + ] + } + } + ], + "not": { + "required": [ + "key", + "certificate" + ] + }, + "dependencies": { + "certificatePassword": [ + "certificate" + ] + } } } } From 813ea6e44301acdaf3675a9a9c1e860a0564d6e0 Mon Sep 17 00:00:00 2001 From: Hanxiao Liu Date: Wed, 18 Aug 2021 14:12:34 +0800 Subject: [PATCH 005/126] Migrate to use uuid for client/tenant id --- .../resources/schema/maven/AzureAppServiceMavenPlugin.json | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/azure-maven-plugin-lib/src/main/resources/schema/maven/AzureAppServiceMavenPlugin.json b/azure-maven-plugin-lib/src/main/resources/schema/maven/AzureAppServiceMavenPlugin.json index fdda9c84fd..e9040f0886 100644 --- a/azure-maven-plugin-lib/src/main/resources/schema/maven/AzureAppServiceMavenPlugin.json +++ b/azure-maven-plugin-lib/src/main/resources/schema/maven/AzureAppServiceMavenPlugin.json @@ -71,12 +71,10 @@ "$ref": "classpath:///schema/common/AuthConfiguration.json#/definitions/auth-type" }, "client": { - "description": "Client ID", - "type": "string" + "$ref": "classpath:///schema/common/UUID.json" }, "tenant": { - "description": "Tenant ID", - "type": "string" + "$ref": "classpath:///schema/common/UUID.json" }, "serverId": { "$ref": "classpath:///schema/common/NonEmptyString.json" From 3847b8132f9ba97e0335934465b4e35d0bd083a1 Mon Sep 17 00:00:00 2001 From: Hanxiao Liu Date: Wed, 18 Aug 2021 16:23:56 +0800 Subject: [PATCH 006/126] Add schema relative path to id and fix reflection issues when no schema founded --- .../lib/common/validator/SchemaValidator.java | 27 +++++++++++++++---- 1 file changed, 22 insertions(+), 5 deletions(-) diff --git a/azure-toolkit-libs/azure-toolkit-common-lib/src/main/java/com/microsoft/azure/toolkit/lib/common/validator/SchemaValidator.java b/azure-toolkit-libs/azure-toolkit-common-lib/src/main/java/com/microsoft/azure/toolkit/lib/common/validator/SchemaValidator.java index 84cbe00e89..f017ef5446 100644 --- a/azure-toolkit-libs/azure-toolkit-common-lib/src/main/java/com/microsoft/azure/toolkit/lib/common/validator/SchemaValidator.java +++ b/azure-toolkit-libs/azure-toolkit-common-lib/src/main/java/com/microsoft/azure/toolkit/lib/common/validator/SchemaValidator.java @@ -13,6 +13,7 @@ import com.networknt.schema.JsonSchema; import com.networknt.schema.JsonSchemaFactory; import com.networknt.schema.SpecVersion; +import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.io.FilenameUtils; import org.apache.commons.lang3.tuple.Pair; import org.reflections.Reflections; @@ -22,11 +23,13 @@ import javax.annotation.Nullable; import java.io.IOException; import java.io.InputStream; +import java.nio.file.Path; +import java.nio.file.Paths; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.Set; +import java.util.Optional; import java.util.regex.Pattern; import java.util.stream.Collectors; @@ -35,7 +38,7 @@ import static com.fasterxml.jackson.databind.MapperFeature.AUTO_DETECT_IS_GETTERS; public class SchemaValidator { - + private static final Path SCHEMA_ROOT = Paths.get("schema"); private final Map schemaMap = new HashMap<>(); private final JsonSchemaFactory factory = JsonSchemaFactory.getInstance(SpecVersion.VersionFlag.V7); private final ObjectMapper objectMapper = new ObjectMapper().setSerializationInclusion(JsonInclude.Include.NON_EMPTY) @@ -47,10 +50,13 @@ public class SchemaValidator { } private SchemaValidator() { - final Set resources = new Reflections("schema", new ResourcesScanner()).getResources(Pattern.compile(".*\\.json")); - resources.stream().map(resource -> Pair.of(resource, SchemaValidator.class.getResourceAsStream("/" + resource))) + Optional.of(new Reflections("schema/", new ResourcesScanner())) + .filter(reflections -> CollectionUtils.isNotEmpty(reflections.getStore().keySet())) + .map(reflections -> reflections.getResources(Pattern.compile(".*\\.json"))) + .orElse(Collections.emptySet()) + .stream().map(resource -> Pair.of(resource, SchemaValidator.class.getResourceAsStream("/" + resource))) .filter(pair -> pair.getValue() != null) - .forEach(pair -> registerSchema(FilenameUtils.getBaseName(pair.getKey()), pair.getValue())); + .forEach(pair -> registerSchema(getSchemaId(pair.getKey()), pair.getValue())); } public static SchemaValidator getInstance() { @@ -97,6 +103,17 @@ private List validate(@Nonnull final JsonSchema schema, @Nonn return schema.validate(value, value, pathPrefix).stream().map(ValidationMessage::fromRawMessage).collect(Collectors.toList()); } + private static final String getSchemaId(final String path) { + try { + final Path schemaPath = Paths.get(FilenameUtils.removeExtension(path)); + final Path relativePath = SCHEMA_ROOT.relativize(schemaPath); + return FilenameUtils.separatorsToUnix(relativePath.toString()); + } catch (IllegalArgumentException e) { + // fallback to schema path for path parse issue + return path; + } + } + private static class LazyHolder { static final SchemaValidator INSTANCE = new SchemaValidator(); } From 59b3204b94201b7daf9be1bdb9f142ae2f5ac912 Mon Sep 17 00:00:00 2001 From: Hanxiao Liu Date: Wed, 18 Aug 2021 16:37:23 +0800 Subject: [PATCH 007/126] Support validate and throw exception in SchemaValidator --- .../lib/common/validator/SchemaValidator.java | 26 ++++++++++++++----- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/azure-toolkit-libs/azure-toolkit-common-lib/src/main/java/com/microsoft/azure/toolkit/lib/common/validator/SchemaValidator.java b/azure-toolkit-libs/azure-toolkit-common-lib/src/main/java/com/microsoft/azure/toolkit/lib/common/validator/SchemaValidator.java index f017ef5446..70c7a9b6c2 100644 --- a/azure-toolkit-libs/azure-toolkit-common-lib/src/main/java/com/microsoft/azure/toolkit/lib/common/validator/SchemaValidator.java +++ b/azure-toolkit-libs/azure-toolkit-common-lib/src/main/java/com/microsoft/azure/toolkit/lib/common/validator/SchemaValidator.java @@ -9,12 +9,14 @@ import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; 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.networknt.schema.JsonSchema; import com.networknt.schema.JsonSchemaFactory; import com.networknt.schema.SpecVersion; import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.io.FilenameUtils; +import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.tuple.Pair; import org.reflections.Reflections; import org.reflections.scanners.ResourcesScanner; @@ -39,6 +41,8 @@ public class SchemaValidator { private static final Path SCHEMA_ROOT = Paths.get("schema"); + private static final String INVALID_PARAMETER_ERROR_MESSAGE = "Invalid parameters founded, please correct the value with messages below:"; + private final Map schemaMap = new HashMap<>(); private final JsonSchemaFactory factory = JsonSchemaFactory.getInstance(SpecVersion.VersionFlag.V7); private final ObjectMapper objectMapper = new ObjectMapper().setSerializationInclusion(JsonInclude.Include.NON_EMPTY) @@ -87,20 +91,28 @@ public List validate(@Nonnull final String schemaId, @Nonnull return validate(schemaId, objectMapper.convertValue(value, JsonNode.class), pathPrefix); } - public List validate(@Nonnull final String schemaId, @Nonnull final JsonNode value) { - return validate(schemaId, value, "$"); - } - public List validate(@Nonnull final String schemaId, @Nonnull final JsonNode value, @Nullable final String pathPrefix) { if (!schemaMap.containsKey(schemaId)) { AzureMessager.getMessager().warning(AzureString.format("Skip validation as schema %s was not registered", schemaId)); return Collections.emptyList(); } - return validate(schemaMap.get(schemaId), value, pathPrefix); + return schemaMap.get(schemaId).validate(value, value, pathPrefix).stream().map(ValidationMessage::fromRawMessage).collect(Collectors.toList()); } - private List validate(@Nonnull final JsonSchema schema, @Nonnull final JsonNode value, @Nullable final String pathPrefix) { - return schema.validate(value, value, pathPrefix).stream().map(ValidationMessage::fromRawMessage).collect(Collectors.toList()); + public void validateAndThrow(@Nonnull final String schemaId, @Nonnull final Object value) { + validateAndThrow(schemaId, value, "$"); + } + + public void validateAndThrow(@Nonnull final String schemaId, @Nonnull final Object value, @Nullable final String pathPrefix) { + validateAndThrow(schemaId, objectMapper.convertValue(value, JsonNode.class), pathPrefix); + } + + public void validateAndThrow(@Nonnull final String schemaId, @Nonnull final JsonNode value, @Nullable final String pathPrefix) { + final List result = validate(schemaId, value, pathPrefix); + if (CollectionUtils.isNotEmpty(result)) { + final String errorDetails = result.stream().map(message -> message.getMessage().toString()).collect(Collectors.joining(StringUtils.LF)); + throw new AzureToolkitRuntimeException(String.join(StringUtils.LF, INVALID_PARAMETER_ERROR_MESSAGE, errorDetails)); + } } private static final String getSchemaId(final String path) { From be8bbac663798a83b67875d02d629393ae26cc45 Mon Sep 17 00:00:00 2001 From: Hanxiao Liu Date: Wed, 18 Aug 2021 17:25:05 +0800 Subject: [PATCH 008/126] Add json schema for app service plan creation/update task --- .../schema/appservice/AppServicePlan.json | 33 +++++++++++++++++++ .../appservice/CreateAppServicePlan.json | 15 +++++++++ .../resources/schema/appservice/Runtime.json | 13 +++++--- 3 files changed, 57 insertions(+), 4 deletions(-) create mode 100644 azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/resources/schema/appservice/AppServicePlan.json create mode 100644 azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/resources/schema/appservice/CreateAppServicePlan.json diff --git a/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/resources/schema/appservice/AppServicePlan.json b/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/resources/schema/appservice/AppServicePlan.json new file mode 100644 index 0000000000..4120a435d2 --- /dev/null +++ b/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/resources/schema/appservice/AppServicePlan.json @@ -0,0 +1,33 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "App Service Plan - Update", + "description": "Schema for AppServicePlanConfig when update existing service plan", + "properties": { + "subscriptionId": { + "$ref": "classpath:///schema/common/UUID.json" + }, + "servicePlanResourceGroup": { + "$ref": "classpath:///schema/common/ResourceGroupName.json" + }, + "servicePlanName": { + "$ref": "classpath:///schema/appservice/AppServicePlanName.json" + }, + "region": { + "$ref": "classpath:///schema/common/NonEmptyString.json" + }, + "os": { + "$ref": "classpath:///schema/appservice/Runtime.json#/definitions/os" + }, + "region": { + "type": "object" + }, + "pricingTier": { + "type": "object" + } + }, + "required": [ + "subscriptionId", + "servicePlanName", + "servicePlanResourceGroup" + ] +} diff --git a/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/resources/schema/appservice/CreateAppServicePlan.json b/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/resources/schema/appservice/CreateAppServicePlan.json new file mode 100644 index 0000000000..43b98bf4ca --- /dev/null +++ b/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/resources/schema/appservice/CreateAppServicePlan.json @@ -0,0 +1,15 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "App Service Plan - Update", + "description": "Schema for AppServicePlanConfig when update existing service plan", + "allOf": [ + { + "$ref": "classpath:///schema/appservice/AppServicePlan.json" + } + ], + "required": [ + "os", + "region", + "pricingTier" + ] +} diff --git a/azure-toolkit-libs/azure-toolkit-common-lib/src/main/resources/schema/appservice/Runtime.json b/azure-toolkit-libs/azure-toolkit-common-lib/src/main/resources/schema/appservice/Runtime.json index 245bb4b9d7..d869b6ef55 100644 --- a/azure-toolkit-libs/azure-toolkit-common-lib/src/main/resources/schema/appservice/Runtime.json +++ b/azure-toolkit-libs/azure-toolkit-common-lib/src/main/resources/schema/appservice/Runtime.json @@ -5,9 +5,7 @@ "type": "object", "properties": { "os": { - "description": "The operating system for app service", - "type": "string", - "pattern": "(?i)^(windows|linux|docker)$" + "$ref": "#/definitions/os" }, "webContainer": { "$ref": "classpath:///schema/common/NonEmptyString.json" @@ -73,5 +71,12 @@ ] } } - ] + ], + "definitions": { + "os": { + "description": "The operating system for app service", + "type": "string", + "pattern": "(?i)^(windows|linux|docker)$" + } + } } From 642fc9e4e91a328101e5144085d859265555a319 Mon Sep 17 00:00:00 2001 From: Hanxiao Liu Date: Wed, 18 Aug 2021 17:26:05 +0800 Subject: [PATCH 009/126] Validate AppServicePlanConfig with SchemaValidator in CreateOrAppServicePlanTask --- .../appservice/config/AppServicePlanConfig.java | 2 ++ .../lib/appservice/model/OperatingSystem.java | 4 ++-- .../toolkit/lib/appservice/model/PricingTier.java | 2 ++ .../task/CreateOrUpdateAppServicePlanTask.java | 15 +++------------ .../azure/toolkit/lib/common/model/Region.java | 2 ++ .../lib/common/validator/SchemaValidator.java | 2 +- 6 files changed, 12 insertions(+), 15 deletions(-) diff --git a/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/config/AppServicePlanConfig.java b/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/config/AppServicePlanConfig.java index d3e46fb807..6e22a9c013 100644 --- a/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/config/AppServicePlanConfig.java +++ b/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/config/AppServicePlanConfig.java @@ -5,6 +5,7 @@ package com.microsoft.azure.toolkit.lib.appservice.config; +import com.fasterxml.jackson.annotation.JsonAutoDetect; import com.microsoft.azure.toolkit.lib.appservice.model.OperatingSystem; import com.microsoft.azure.toolkit.lib.appservice.model.PricingTier; import com.microsoft.azure.toolkit.lib.common.model.Region; @@ -15,6 +16,7 @@ @Getter @Setter @Accessors(fluent = true) +@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY) public class AppServicePlanConfig { private String subscriptionId; diff --git a/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/model/OperatingSystem.java b/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/model/OperatingSystem.java index c905e4a2d2..675b3bdcad 100644 --- a/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/model/OperatingSystem.java +++ b/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/model/OperatingSystem.java @@ -5,11 +5,10 @@ package com.microsoft.azure.toolkit.lib.appservice.model; +import com.fasterxml.jackson.annotation.JsonAutoDetect; import lombok.AllArgsConstructor; -import lombok.EqualsAndHashCode; import lombok.Getter; import lombok.NoArgsConstructor; -import lombok.Setter; import org.apache.commons.lang3.StringUtils; import java.util.Arrays; @@ -17,6 +16,7 @@ @Getter @NoArgsConstructor @AllArgsConstructor +@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY) public enum OperatingSystem { WINDOWS("windows"), LINUX("linux"), diff --git a/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/model/PricingTier.java b/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/model/PricingTier.java index 5fcff7c3f3..085ee2b10d 100644 --- a/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/model/PricingTier.java +++ b/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/model/PricingTier.java @@ -5,6 +5,7 @@ package com.microsoft.azure.toolkit.lib.appservice.model; +import com.fasterxml.jackson.annotation.JsonAutoDetect; import com.google.common.collect.Sets; import com.microsoft.azure.toolkit.lib.common.model.ExpandableParameter; import lombok.AllArgsConstructor; @@ -24,6 +25,7 @@ @Setter @NoArgsConstructor @AllArgsConstructor +@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY) public class PricingTier implements ExpandableParameter { public static final PricingTier BASIC_B1 = new PricingTier("Basic", "B1"); public static final PricingTier BASIC_B2 = new PricingTier("Basic", "B2"); diff --git a/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/task/CreateOrUpdateAppServicePlanTask.java b/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/task/CreateOrUpdateAppServicePlanTask.java index 86e90fd73f..ac2429cf7f 100644 --- a/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/task/CreateOrUpdateAppServicePlanTask.java +++ b/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/task/CreateOrUpdateAppServicePlanTask.java @@ -9,12 +9,12 @@ import com.microsoft.azure.toolkit.lib.appservice.AzureAppService; import com.microsoft.azure.toolkit.lib.appservice.config.AppServicePlanConfig; import com.microsoft.azure.toolkit.lib.appservice.service.IAppServicePlan; -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.operation.AzureOperation; import com.microsoft.azure.toolkit.lib.common.task.AzureTask; import com.microsoft.azure.toolkit.lib.common.telemetry.AzureTelemetry; +import com.microsoft.azure.toolkit.lib.common.validator.SchemaValidator; import lombok.AllArgsConstructor; import java.util.Objects; @@ -28,23 +28,14 @@ public class CreateOrUpdateAppServicePlanTask extends AzureTask @AzureOperation(name = "appservice|plan.create_update", params = {"this.config.servicePlanName()"}, type = AzureOperation.Type.SERVICE) public IAppServicePlan execute() { + SchemaValidator.getInstance().validateAndThrow("appservice/AppServicePlan", config); final AzureAppService az = Azure.az(AzureAppService.class).subscription(config.subscriptionId()); final IAppServicePlan appServicePlan = az.appServicePlan(config.servicePlanResourceGroup(), config.servicePlanName()); final String servicePlanName = config.servicePlanName(); if (!appServicePlan.exists()) { + SchemaValidator.getInstance().validateAndThrow("appservice/CreateAppServicePlan", config); AzureMessager.getMessager().info(String.format(CREATE_APP_SERVICE_PLAN, servicePlanName)); AzureTelemetry.getActionContext().setProperty(CREATE_NEW_APP_SERVICE_PLAN, String.valueOf(true)); - if (config.os() == null) { - throw new AzureToolkitRuntimeException("Missing required configuration for 'runtime.os'."); - } - - if (config.region() == null) { - throw new AzureToolkitRuntimeException("Missing required configuration for 'region'."); - } - - if (config.pricingTier() == null) { - throw new AzureToolkitRuntimeException("Missing required configuration for 'pricingTier'."); - } appServicePlan.create() .withName(servicePlanName) diff --git a/azure-toolkit-libs/azure-toolkit-common-lib/src/main/java/com/microsoft/azure/toolkit/lib/common/model/Region.java b/azure-toolkit-libs/azure-toolkit-common-lib/src/main/java/com/microsoft/azure/toolkit/lib/common/model/Region.java index e4480eb5cd..4f4d2e900c 100644 --- a/azure-toolkit-libs/azure-toolkit-common-lib/src/main/java/com/microsoft/azure/toolkit/lib/common/model/Region.java +++ b/azure-toolkit-libs/azure-toolkit-common-lib/src/main/java/com/microsoft/azure/toolkit/lib/common/model/Region.java @@ -4,6 +4,7 @@ */ package com.microsoft.azure.toolkit.lib.common.model; +import com.fasterxml.jackson.annotation.JsonAutoDetect; import com.google.common.collect.Sets; import lombok.AllArgsConstructor; import lombok.EqualsAndHashCode; @@ -21,6 +22,7 @@ @NoArgsConstructor @AllArgsConstructor @EqualsAndHashCode +@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY) public class Region implements ExpandableParameter { public static final Region US_EAST = new Region("eastus", "East US"); public static final Region US_EAST2 = new Region("eastus2", "East US 2"); diff --git a/azure-toolkit-libs/azure-toolkit-common-lib/src/main/java/com/microsoft/azure/toolkit/lib/common/validator/SchemaValidator.java b/azure-toolkit-libs/azure-toolkit-common-lib/src/main/java/com/microsoft/azure/toolkit/lib/common/validator/SchemaValidator.java index 70c7a9b6c2..8299caa1ca 100644 --- a/azure-toolkit-libs/azure-toolkit-common-lib/src/main/java/com/microsoft/azure/toolkit/lib/common/validator/SchemaValidator.java +++ b/azure-toolkit-libs/azure-toolkit-common-lib/src/main/java/com/microsoft/azure/toolkit/lib/common/validator/SchemaValidator.java @@ -115,7 +115,7 @@ public void validateAndThrow(@Nonnull final String schemaId, @Nonnull final Json } } - private static final String getSchemaId(final String path) { + private static String getSchemaId(final String path) { try { final Path schemaPath = Paths.get(FilenameUtils.removeExtension(path)); final Path relativePath = SCHEMA_ROOT.relativize(schemaPath); From 2c0e5a1e896c10e39d8be5c57ffa3f99149254ae Mon Sep 17 00:00:00 2001 From: shenqianjin Date: Fri, 20 Aug 2021 16:57:53 +0800 Subject: [PATCH 010/126] bump version for next release. --- .../azure-toolkit-applicationinsights-lib/pom.xml | 2 +- azure-toolkit-libs/azure-toolkit-appservice-lib/pom.xml | 2 +- azure-toolkit-libs/azure-toolkit-auth-lib/pom.xml | 2 +- azure-toolkit-libs/azure-toolkit-common-lib/pom.xml | 2 +- azure-toolkit-libs/azure-toolkit-database-lib/pom.xml | 2 +- azure-toolkit-libs/azure-toolkit-mysql-lib/pom.xml | 2 +- azure-toolkit-libs/azure-toolkit-resource-lib/pom.xml | 2 +- azure-toolkit-libs/azure-toolkit-springcloud-lib/pom.xml | 2 +- azure-toolkit-libs/azure-toolkit-sqlserver-lib/pom.xml | 2 +- azure-toolkit-libs/azure-toolkit-storage-lib/pom.xml | 2 +- azure-toolkit-libs/pom.xml | 2 +- pom.xml | 2 +- 12 files changed, 12 insertions(+), 12 deletions(-) diff --git a/azure-toolkit-libs/azure-toolkit-applicationinsights-lib/pom.xml b/azure-toolkit-libs/azure-toolkit-applicationinsights-lib/pom.xml index 69339e6f74..6eed0ab520 100644 --- a/azure-toolkit-libs/azure-toolkit-applicationinsights-lib/pom.xml +++ b/azure-toolkit-libs/azure-toolkit-applicationinsights-lib/pom.xml @@ -5,7 +5,7 @@ azure-toolkit-libs com.microsoft.azure - 0.11.0 + 0.12.0-SNAPSHOT 4.0.0 diff --git a/azure-toolkit-libs/azure-toolkit-appservice-lib/pom.xml b/azure-toolkit-libs/azure-toolkit-appservice-lib/pom.xml index 858b57c9f0..47904255fd 100644 --- a/azure-toolkit-libs/azure-toolkit-appservice-lib/pom.xml +++ b/azure-toolkit-libs/azure-toolkit-appservice-lib/pom.xml @@ -5,7 +5,7 @@ azure-toolkit-libs com.microsoft.azure - 0.11.0 + 0.12.0-SNAPSHOT 4.0.0 diff --git a/azure-toolkit-libs/azure-toolkit-auth-lib/pom.xml b/azure-toolkit-libs/azure-toolkit-auth-lib/pom.xml index 4d01040b2c..1ed4c28cfe 100644 --- a/azure-toolkit-libs/azure-toolkit-auth-lib/pom.xml +++ b/azure-toolkit-libs/azure-toolkit-auth-lib/pom.xml @@ -5,7 +5,7 @@ azure-toolkit-libs com.microsoft.azure - 0.11.0 + 0.12.0-SNAPSHOT 4.0.0 diff --git a/azure-toolkit-libs/azure-toolkit-common-lib/pom.xml b/azure-toolkit-libs/azure-toolkit-common-lib/pom.xml index 42c0f195df..fcf2002c2d 100644 --- a/azure-toolkit-libs/azure-toolkit-common-lib/pom.xml +++ b/azure-toolkit-libs/azure-toolkit-common-lib/pom.xml @@ -5,7 +5,7 @@ azure-toolkit-libs com.microsoft.azure - 0.11.0 + 0.12.0-SNAPSHOT 4.0.0 diff --git a/azure-toolkit-libs/azure-toolkit-database-lib/pom.xml b/azure-toolkit-libs/azure-toolkit-database-lib/pom.xml index dcddfc3072..d0e4795945 100644 --- a/azure-toolkit-libs/azure-toolkit-database-lib/pom.xml +++ b/azure-toolkit-libs/azure-toolkit-database-lib/pom.xml @@ -5,7 +5,7 @@ azure-toolkit-libs com.microsoft.azure - 0.11.0 + 0.12.0-SNAPSHOT 4.0.0 diff --git a/azure-toolkit-libs/azure-toolkit-mysql-lib/pom.xml b/azure-toolkit-libs/azure-toolkit-mysql-lib/pom.xml index 4b27002c93..c6c987658a 100644 --- a/azure-toolkit-libs/azure-toolkit-mysql-lib/pom.xml +++ b/azure-toolkit-libs/azure-toolkit-mysql-lib/pom.xml @@ -5,7 +5,7 @@ azure-toolkit-libs com.microsoft.azure - 0.11.0 + 0.12.0-SNAPSHOT 4.0.0 diff --git a/azure-toolkit-libs/azure-toolkit-resource-lib/pom.xml b/azure-toolkit-libs/azure-toolkit-resource-lib/pom.xml index 62aca0d1e5..03a793bf8b 100644 --- a/azure-toolkit-libs/azure-toolkit-resource-lib/pom.xml +++ b/azure-toolkit-libs/azure-toolkit-resource-lib/pom.xml @@ -5,7 +5,7 @@ azure-toolkit-libs com.microsoft.azure - 0.11.0 + 0.12.0-SNAPSHOT 4.0.0 diff --git a/azure-toolkit-libs/azure-toolkit-springcloud-lib/pom.xml b/azure-toolkit-libs/azure-toolkit-springcloud-lib/pom.xml index 00a3ba103d..cfd6da4a3f 100644 --- a/azure-toolkit-libs/azure-toolkit-springcloud-lib/pom.xml +++ b/azure-toolkit-libs/azure-toolkit-springcloud-lib/pom.xml @@ -5,7 +5,7 @@ azure-toolkit-libs com.microsoft.azure - 0.11.0 + 0.12.0-SNAPSHOT 4.0.0 diff --git a/azure-toolkit-libs/azure-toolkit-sqlserver-lib/pom.xml b/azure-toolkit-libs/azure-toolkit-sqlserver-lib/pom.xml index 4a144c0e97..86dd0d0551 100644 --- a/azure-toolkit-libs/azure-toolkit-sqlserver-lib/pom.xml +++ b/azure-toolkit-libs/azure-toolkit-sqlserver-lib/pom.xml @@ -5,7 +5,7 @@ azure-toolkit-libs com.microsoft.azure - 0.11.0 + 0.12.0-SNAPSHOT 4.0.0 diff --git a/azure-toolkit-libs/azure-toolkit-storage-lib/pom.xml b/azure-toolkit-libs/azure-toolkit-storage-lib/pom.xml index 3e341398c5..c3d60c1cb0 100644 --- a/azure-toolkit-libs/azure-toolkit-storage-lib/pom.xml +++ b/azure-toolkit-libs/azure-toolkit-storage-lib/pom.xml @@ -5,7 +5,7 @@ azure-toolkit-libs com.microsoft.azure - 0.11.0 + 0.12.0-SNAPSHOT 4.0.0 diff --git a/azure-toolkit-libs/pom.xml b/azure-toolkit-libs/pom.xml index 8e3f287b4b..1e51dfe604 100644 --- a/azure-toolkit-libs/pom.xml +++ b/azure-toolkit-libs/pom.xml @@ -5,7 +5,7 @@ 4.0.0 com.microsoft.azure azure-toolkit-libs - 0.11.0 + 0.12.0-SNAPSHOT pom Libs for Azure Toolkits Wrapped libs for Microsoft Azure Toolkits diff --git a/pom.xml b/pom.xml index d59ad831ad..8b9940d0f6 100644 --- a/pom.xml +++ b/pom.xml @@ -92,7 +92,7 @@ com.microsoft.azure azure-toolkit-libs - 0.11.0 + 0.12.0-SNAPSHOT pom import From 4efe435e5169440c9b27a695d1030585cb350b10 Mon Sep 17 00:00:00 2001 From: Hanxiao Liu Date: Mon, 23 Aug 2021 09:40:13 +0800 Subject: [PATCH 011/126] Remove wrong property `region` for App Service Plan schema --- .../src/main/resources/schema/appservice/AppServicePlan.json | 3 --- 1 file changed, 3 deletions(-) diff --git a/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/resources/schema/appservice/AppServicePlan.json b/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/resources/schema/appservice/AppServicePlan.json index 4120a435d2..109cd55b80 100644 --- a/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/resources/schema/appservice/AppServicePlan.json +++ b/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/resources/schema/appservice/AppServicePlan.json @@ -12,9 +12,6 @@ "servicePlanName": { "$ref": "classpath:///schema/appservice/AppServicePlanName.json" }, - "region": { - "$ref": "classpath:///schema/common/NonEmptyString.json" - }, "os": { "$ref": "classpath:///schema/appservice/Runtime.json#/definitions/os" }, From 256095ea12acfe18808f4cbb18631489ccc84c15 Mon Sep 17 00:00:00 2001 From: "Andy Xu(devdiv)" Date: Tue, 24 Aug 2021 09:08:24 +0800 Subject: [PATCH 012/126] Update README.md --- azure-webapp-maven-plugin/README.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/azure-webapp-maven-plugin/README.md b/azure-webapp-maven-plugin/README.md index d9bee75d41..73e85b25f6 100644 --- a/azure-webapp-maven-plugin/README.md +++ b/azure-webapp-maven-plugin/README.md @@ -25,7 +25,7 @@ Mavan plugins supports Azure Cli and some other auth methods, see [Authenticatio You can prepare your application for Azure Web App easily with one command: ```shell -mvn com.microsoft.azure:azure-webapp-maven-plugin:1.14.0:config +mvn com.microsoft.azure:azure-webapp-maven-plugin:2.1.0:config ``` This command adds a `azure-webapp-maven-plugin` plugin and related configuration by prompting you to select an existing Azure Web App or create a new one. Then you can deploy your Java app to Azure using the following command: @@ -72,12 +72,12 @@ Property | Required | Description `` | false | Specifies the target subscription.
Use this setting when you have multiple subscriptions in your authentication file.| `` | true | Azure Resource Group for your Web App. | `` | true | The name of your Web App. | -``| false | The pricing tier for your Web App. The default value is **P1V2**.| -``| false | Specifies the region where your Web App will be hosted; the default value is **westeurope**. All valid regions at [Supported Regions](#region) section. | -``| false | Specifies the os, supported values are *Linux*, *Windows* and *Docker*. | -``| false | Specifies the runtime stack, values for Linux are: *Tomcat 8.5*, *Tomcat 9.0*, *Java SE*, *JbossEAP 7.2*| -``| false | Specifies the java version, values are: *Java 8* or *Java 11*| -``| false | Specifies the target file to be deployed | +``| false | The pricing tier for your Web App. The default value is **P1V2**(**P1v3** for JBoss).| +``| false | Specifies the region where your Web App will be hosted; the default value is **westeurope**(or the first region available in your subscription). All valid regions at [Supported Regions](#region) section. | +``| false | Specifies the os, supported values are *Linux*, *Windows* and *Docker*. The default value is **linux**| +``| false | Specifies the runtime stack, values for Linux are: *Tomcat 8.5*, *Tomcat 9.0*, *Java SE*, *JbossEAP 7.2*, The default value would be **Tomcat 8.5** or **Java SE** according to your project type | +``| false | Specifies the java version, values are: *Java 8* or *Java 11*. The default value is **Java 11**| +``| false | Specifies the target file to be deployed. If it is not specified, a default webapp is created. | ## Feedback and Questions To report bugs or request new features, file issues on [Issues](https://github.com/microsoft/azure-maven-plugins/issues). Or, ask questions on [Stack Overflow with tag azure-java-tools](https://stackoverflow.com/questions/tagged/azure-java-tools). From 642c9c80425423d8dfc303b62444a43139365cf5 Mon Sep 17 00:00:00 2001 From: andxu Date: Mon, 30 Aug 2021 10:34:50 +0800 Subject: [PATCH 013/126] Add name check before creating webapp --- .../toolkit/lib/appservice/AzureAppService.java | 15 +++++++++++++-- .../appservice/task/CreateOrUpdateWebAppTask.java | 14 ++++++++++++-- .../operation/title/base/appservice.properties | 1 + .../microsoft/azure/maven/webapp/DeployMojo.java | 11 +++++++++++ 4 files changed, 37 insertions(+), 4 deletions(-) diff --git a/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/AzureAppService.java b/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/AzureAppService.java index 05082f2587..e07c695761 100644 --- a/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/AzureAppService.java +++ b/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/AzureAppService.java @@ -8,6 +8,8 @@ import com.azure.core.http.policy.HttpPipelinePolicy; import com.azure.core.management.profile.AzureProfile; import com.azure.resourcemanager.AzureResourceManager; +import com.azure.resourcemanager.appservice.fluent.models.ResourceNameAvailabilityInner; +import com.azure.resourcemanager.appservice.models.CheckNameResourceTypes; import com.microsoft.azure.toolkit.lib.Azure; import com.microsoft.azure.toolkit.lib.AzureConfiguration; import com.microsoft.azure.toolkit.lib.AzureService; @@ -31,6 +33,7 @@ import com.microsoft.azure.toolkit.lib.auth.AzureAccount; import com.microsoft.azure.toolkit.lib.common.cache.Cacheable; import com.microsoft.azure.toolkit.lib.common.cache.Preload; +import com.microsoft.azure.toolkit.lib.common.entity.CheckNameAvailabilityResultEntity; import com.microsoft.azure.toolkit.lib.common.model.Subscription; import com.microsoft.azure.toolkit.lib.common.operation.AzureOperation; import org.apache.commons.lang3.StringUtils; @@ -120,6 +123,14 @@ public List webapps(boolean... force) { .collect(Collectors.toList()); } + @AzureOperation(name = "appservice.check_name", params = "name", type = AzureOperation.Type.SERVICE) + public CheckNameAvailabilityResultEntity checkNameAvailability(String subscriptionId, String name) { + final AzureResourceManager azureResourceManager = getAzureResourceManager(subscriptionId); + final ResourceNameAvailabilityInner result = azureResourceManager.webApps().manager() + .serviceClient().getResourceProviders().checkNameAvailability(name, CheckNameResourceTypes.MICROSOFT_WEB_SITES); + return new CheckNameAvailabilityResultEntity(result.nameAvailable(), result.reason().toString(), result.message()); + } + @Cacheable(cacheName = "appservcie/{}/webapps", key = "$sid", condition = "!(force&&force[0])") @AzureOperation(name = "webapp.list.subscription", params = "sid", type = AzureOperation.Type.SERVICE) private List webapps(String sid, boolean... force) { @@ -130,8 +141,8 @@ private List webapps(String sid, boolean... force) { .collect(Collectors.toList()); } - public @Nonnull - @AzureOperation(name = "webapp|runtime.list.os|version", params = {"os.getValue()", "version.getValue()"}, type = AzureOperation.Type.SERVICE) + @Nonnull + public @AzureOperation(name = "webapp|runtime.list.os|version", params = {"os.getValue()", "version.getValue()"}, type = AzureOperation.Type.SERVICE) List listWebAppRuntimes(@Nonnull OperatingSystem os, @Nonnull JavaVersion version) { return Runtime.WEBAPP_RUNTIME.stream() .filter(runtime -> Objects.equals(os, runtime.getOperatingSystem()) && Objects.equals(version, runtime.getJavaVersion())) diff --git a/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/task/CreateOrUpdateWebAppTask.java b/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/task/CreateOrUpdateWebAppTask.java index dcbbe97d3f..d4a1784daf 100644 --- a/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/task/CreateOrUpdateWebAppTask.java +++ b/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/task/CreateOrUpdateWebAppTask.java @@ -18,6 +18,8 @@ import com.microsoft.azure.toolkit.lib.appservice.service.IAppServicePlan; import com.microsoft.azure.toolkit.lib.appservice.service.IWebApp; import com.microsoft.azure.toolkit.lib.common.bundle.AzureString; +import com.microsoft.azure.toolkit.lib.common.entity.CheckNameAvailabilityResultEntity; +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.operation.AzureOperation; import com.microsoft.azure.toolkit.lib.common.operation.AzureOperation.Type; @@ -56,12 +58,19 @@ private List> initTasks() { tasks.add(new CreateResourceGroupTask(this.config.subscriptionId(), this.config.servicePlanResourceGroup(), this.config.region())); } final AzureString title = AzureString.format("Create new web app({0})", this.config.appName()); - + AzureAppService az = Azure.az(AzureAppService.class); tasks.add(new AzureTask<>(title, () -> { - final IWebApp target = Azure.az(AzureAppService.class).subscription(config.subscriptionId()) + final IWebApp target = az.subscription(config.subscriptionId()) .webapp(config.resourceGroup(), config.appName()); if (!target.exists()) { + CheckNameAvailabilityResultEntity result = az.checkNameAvailability(config.subscriptionId(), config.appName()); + if (!result.isAvailable()) { + throw new AzureToolkitRuntimeException(AzureString.format("Cannot create webapp {0} due to error: {1}", + config.appName(), + result.getUnavailabilityReason()).getString()); + } return create(); + } return update(target); })); @@ -93,6 +102,7 @@ private IWebApp create() { AzureMessager.getMessager().info(String.format(CREATE_WEB_APP_DONE, result.name())); return result; } + @AzureOperation(name = "webapp.update", params = {"this.config.appName()"}, type = Type.SERVICE) private IWebApp update(final IWebApp webApp) { AzureMessager.getMessager().info(String.format(UPDATE_WEBAPP, webApp.name())); diff --git a/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/resources/com/microsoft/azure/toolkit/operation/title/base/appservice.properties b/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/resources/com/microsoft/azure/toolkit/operation/title/base/appservice.properties index e0efebd1d2..f5cecf0a35 100644 --- a/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/resources/com/microsoft/azure/toolkit/operation/title/base/appservice.properties +++ b/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/resources/com/microsoft/azure/toolkit/operation/title/base/appservice.properties @@ -11,3 +11,4 @@ appservice|deployment.get.id=get Azure App Service deployment slot by id({0}) appservice|deployment.get.name|app|rg|subscription=get Azure App Service deployment slot({0}) of app({1}) appservice.get_client.subscription=get Azure App Service rest client of subscription({0}) appservice|plan.create_update=create or update Azure App Service plan ({0}) from config +appservice.check_name=check name availability for ({0}) \ No newline at end of file diff --git a/azure-webapp-maven-plugin/src/main/java/com/microsoft/azure/maven/webapp/DeployMojo.java b/azure-webapp-maven-plugin/src/main/java/com/microsoft/azure/maven/webapp/DeployMojo.java index ee4e3c6422..c816176695 100644 --- a/azure-webapp-maven-plugin/src/main/java/com/microsoft/azure/maven/webapp/DeployMojo.java +++ b/azure-webapp-maven-plugin/src/main/java/com/microsoft/azure/maven/webapp/DeployMojo.java @@ -20,7 +20,10 @@ import com.microsoft.azure.toolkit.lib.appservice.service.IWebApp; import com.microsoft.azure.toolkit.lib.appservice.service.IWebAppBase; import com.microsoft.azure.toolkit.lib.appservice.service.IWebAppDeploymentSlot; +import com.microsoft.azure.toolkit.lib.common.bundle.AzureString; +import com.microsoft.azure.toolkit.lib.common.entity.CheckNameAvailabilityResultEntity; import com.microsoft.azure.toolkit.lib.common.exception.AzureExecutionException; +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 org.apache.commons.collections4.CollectionUtils; @@ -104,6 +107,14 @@ private IWebApp createWebApp(final IWebApp webApp, final WebAppConfig webAppConf if (webAppConfig.getRuntime() == null) { throw new AzureExecutionException(NO_RUNTIME_CONFIG); } + + CheckNameAvailabilityResultEntity checkNameResult = az.checkNameAvailability(webAppConfig.getSubscriptionId(), webAppConfig.getAppName()); + if (!checkNameResult.isAvailable()) { + throw new AzureToolkitRuntimeException(AzureString.format("Cannot create webapp {0} due to error: {1}", + webAppConfig.getAppName(), + checkNameResult.getUnavailabilityReason()).getString()); + } + getTelemetryProxy().addDefaultProperty(CREATE_NEW_WEB_APP, String.valueOf(true)); final ResourceGroup resourceGroup = getOrCreateResourceGroup(webAppConfig); final IAppServicePlan appServicePlan = getOrCreateAppServicePlan(webAppConfig); From 0fbccf8e8a8e0fdb53b16972517985f3c53f22b5 Mon Sep 17 00:00:00 2001 From: andxu Date: Tue, 31 Aug 2021 13:47:26 +0800 Subject: [PATCH 014/126] Migrate from AzureResourceManager to ResourceManager in auth-lib --- .../toolkit/lib/auth/TokenCredentialManager.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/azure-toolkit-libs/azure-toolkit-auth-lib/src/main/java/com/microsoft/azure/toolkit/lib/auth/TokenCredentialManager.java b/azure-toolkit-libs/azure-toolkit-auth-lib/src/main/java/com/microsoft/azure/toolkit/lib/auth/TokenCredentialManager.java index 0bb9a2f2bd..8182b3bcf2 100644 --- a/azure-toolkit-libs/azure-toolkit-auth-lib/src/main/java/com/microsoft/azure/toolkit/lib/auth/TokenCredentialManager.java +++ b/azure-toolkit-libs/azure-toolkit-auth-lib/src/main/java/com/microsoft/azure/toolkit/lib/auth/TokenCredentialManager.java @@ -14,7 +14,7 @@ import com.azure.core.management.AzureEnvironment; import com.azure.core.management.profile.AzureProfile; import com.azure.core.util.logging.ClientLogger; -import com.azure.resourcemanager.AzureResourceManager; +import com.azure.resourcemanager.resources.ResourceManager; import com.azure.resourcemanager.resources.models.Tenant; import com.microsoft.azure.toolkit.lib.Azure; import com.microsoft.azure.toolkit.lib.AzureConfiguration; @@ -70,7 +70,7 @@ public Mono> listSubscriptions(List tenantIds) { .collect(Collectors.toList())); } - private static Mono> listSubscriptionsInTenant(AzureResourceManager.Authenticated client, String tenantId) { + private static Mono> listSubscriptionsInTenant(ResourceManager.Authenticated client, String tenantId) { return client.subscriptions().listAsync() .map(s -> toSubscriptionEntity(tenantId, s)).collectList().onErrorResume(ex -> { // warn and ignore, should modify here if IMessage is ready @@ -89,12 +89,12 @@ private static Subscription toSubscriptionEntity(String tenantId, return subscriptionEntity; } - private AzureResourceManager.Authenticated createAzureClient(AzureEnvironment env, String tenantId) { + private ResourceManager.Authenticated createAzureClient(AzureEnvironment env, String tenantId) { AzureProfile profile = new AzureProfile(env); return configureAzure().authenticate(this.createTokenCredentialForTenant(tenantId), profile); } - private AzureResourceManager.Authenticated createAzureClient(AzureEnvironment env) { + private ResourceManager.Authenticated createAzureClient(AzureEnvironment env) { AzureProfile profile = new AzureProfile(env); return configureAzure().authenticate(this.rootCredentialSupplier.get(), profile); } @@ -102,7 +102,7 @@ private AzureResourceManager.Authenticated createAzureClient(AzureEnvironment en /** * TODO: share the same code for creating AzureResourceManager.Configurable */ - private static AzureResourceManager.Configurable configureAzure() { + private static ResourceManager.Configurable configureAzure() { OkHttpAsyncHttpClientBuilder builder = new OkHttpAsyncHttpClientBuilder(); final AzureConfiguration config = Azure.az().config(); if (StringUtils.isNotBlank(config.getProxySource())) { @@ -116,7 +116,7 @@ private static AzureResourceManager.Configurable configureAzure() { } // disable retry for getting tenant and subscriptions - return AzureResourceManager.configure() + return ResourceManager.configure() .withHttpClient(builder.build()) .withPolicy(createUserAgentPolicy()) .withRetryPolicy(new RetryPolicy(new FixedDelay(0, Duration.ofSeconds(0)))); From 8e3899326a599eefd7a4ba15263247151e3c41ca Mon Sep 17 00:00:00 2001 From: Hanxiao Liu Date: Thu, 2 Sep 2021 22:15:18 +0800 Subject: [PATCH 015/126] Migrate from AzureResourceManager to AppServiceManager in app service library --- .../ApplicationInsights.java | 2 +- .../lib/appservice/AzureAppService.java | 35 +++++++++---------- .../service/impl/AppServicePlan.java | 10 +++--- .../service/impl/AppServiceUtils.java | 4 +-- .../appservice/service/impl/FunctionApp.java | 26 ++++++-------- .../lib/appservice/service/impl/WebApp.java | 27 ++++++-------- .../service/impl/WebAppDeploymentSlot.java | 4 +-- .../azure/toolkit/lib/auth/Account.java | 8 ++--- .../microsoft/azure/toolkit/lib/Azure.java | 22 +++++++----- 9 files changed, 67 insertions(+), 71 deletions(-) diff --git a/azure-toolkit-libs/azure-toolkit-applicationinsights-lib/src/main/java/com/microsoft/azure/toolkit/lib/applicationinsights/ApplicationInsights.java b/azure-toolkit-libs/azure-toolkit-applicationinsights-lib/src/main/java/com/microsoft/azure/toolkit/lib/applicationinsights/ApplicationInsights.java index b70ae743cb..884eb4e512 100644 --- a/azure-toolkit-libs/azure-toolkit-applicationinsights-lib/src/main/java/com/microsoft/azure/toolkit/lib/applicationinsights/ApplicationInsights.java +++ b/azure-toolkit-libs/azure-toolkit-applicationinsights-lib/src/main/java/com/microsoft/azure/toolkit/lib/applicationinsights/ApplicationInsights.java @@ -94,7 +94,7 @@ public void delete(@Nonnull String subscriptionId, @Nonnull String resourceGroup getApplicationInsightsManager(subscriptionId).components().deleteByResourceGroup(resourceGroup, name); } - @Cacheable(cacheName = "ApplicationInsightsManager", key = "$subscriptionId") + @Cacheable(cacheName = "AzureResourceManager", key = "$subscriptionId") private ApplicationInsightsManager getApplicationInsightsManager(String subscriptionId) { final Account account = Azure.az(AzureAccount.class).account(); final String tenantId = account.getSubscription(subscriptionId).getTenantId(); diff --git a/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/AzureAppService.java b/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/AzureAppService.java index e07c695761..4a20a7b4dd 100644 --- a/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/AzureAppService.java +++ b/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/AzureAppService.java @@ -7,7 +7,7 @@ import com.azure.core.http.policy.HttpLogDetailLevel; import com.azure.core.http.policy.HttpPipelinePolicy; import com.azure.core.management.profile.AzureProfile; -import com.azure.resourcemanager.AzureResourceManager; +import com.azure.resourcemanager.appservice.AppServiceManager; import com.azure.resourcemanager.appservice.fluent.models.ResourceNameAvailabilityInner; import com.azure.resourcemanager.appservice.models.CheckNameResourceTypes; import com.microsoft.azure.toolkit.lib.Azure; @@ -57,7 +57,7 @@ private AzureAppService(@Nonnull final List subscriptions) { @Cacheable(cacheName = "appservcie/functionapp/{}", key = "$id") @AzureOperation(name = "functionapp.get.id", params = {"id"}, type = AzureOperation.Type.SERVICE) public IFunctionApp functionApp(String id) { - return new FunctionApp(id, getAzureResourceManager(Utils.getSubscriptionId(id))); + return new FunctionApp(id, getAppServiceManager(Utils.getSubscriptionId(id))); } public IFunctionApp functionApp(String resourceGroup, String name) { @@ -67,7 +67,7 @@ public IFunctionApp functionApp(String resourceGroup, String name) { @Cacheable(cacheName = "appservcie/{}/rg/{}/functionapp/{}", key = "$sid/$rg/$name") @AzureOperation(name = "functionapp.get.name|rg|sid", params = {"name", "rg", "sid"}, type = AzureOperation.Type.SERVICE) public IFunctionApp functionApp(String sid, String rg, String name) { - return new FunctionApp(sid, rg, name, getAzureResourceManager(sid)); + return new FunctionApp(sid, rg, name, getAppServiceManager(sid)); } public IFunctionApp functionApp(FunctionAppEntity entity) { @@ -86,7 +86,7 @@ public List functionApps(boolean... force) { @Cacheable(cacheName = "appservcie/{}/functionapps", key = "$sid", condition = "!(force&&force[0])") @AzureOperation(name = "functionapp.list.subscription", params = "sid", type = AzureOperation.Type.SERVICE) private List functionApps(String sid, boolean... force) { - final AzureResourceManager azureResourceManager = getAzureResourceManager(sid); + final AppServiceManager azureResourceManager = getAppServiceManager(sid); return azureResourceManager .functionApps().list().stream().parallel() .filter(functionAppBasic -> StringUtils.containsIgnoreCase(functionAppBasic.innerModel().kind(), "functionapp")) // Filter out function apps @@ -97,7 +97,7 @@ private List functionApps(String sid, boolean... force) { @Cacheable(cacheName = "appservcie/webapp/{}", key = "$id") @AzureOperation(name = "webapp.get.id", params = "id", type = AzureOperation.Type.SERVICE) public IWebApp webapp(String id) { - return new WebApp(id, getAzureResourceManager(Utils.getSubscriptionId(id))); + return new WebApp(id, getAppServiceManager(Utils.getSubscriptionId(id))); } public IWebApp webapp(String resourceGroup, String name) { @@ -107,7 +107,7 @@ public IWebApp webapp(String resourceGroup, String name) { @Cacheable(cacheName = "appservcie/{}/rg/{}/webapp/{}", key = "$sid/$rg/$name") @AzureOperation(name = "webapp.get.name|rg|sid", params = {"name", "rg", "sid"}, type = AzureOperation.Type.SERVICE) public IWebApp webapp(String sid, String rg, String name) { - return new WebApp(sid, rg, name, getAzureResourceManager(sid)); + return new WebApp(sid, rg, name, getAppServiceManager(sid)); } public IWebApp webapp(WebAppEntity webAppEntity) { @@ -125,7 +125,7 @@ public List webapps(boolean... force) { @AzureOperation(name = "appservice.check_name", params = "name", type = AzureOperation.Type.SERVICE) public CheckNameAvailabilityResultEntity checkNameAvailability(String subscriptionId, String name) { - final AzureResourceManager azureResourceManager = getAzureResourceManager(subscriptionId); + final AppServiceManager azureResourceManager = getAppServiceManager(subscriptionId); final ResourceNameAvailabilityInner result = azureResourceManager.webApps().manager() .serviceClient().getResourceProviders().checkNameAvailability(name, CheckNameResourceTypes.MICROSOFT_WEB_SITES); return new CheckNameAvailabilityResultEntity(result.nameAvailable(), result.reason().toString(), result.message()); @@ -134,7 +134,7 @@ public CheckNameAvailabilityResultEntity checkNameAvailability(String subscripti @Cacheable(cacheName = "appservcie/{}/webapps", key = "$sid", condition = "!(force&&force[0])") @AzureOperation(name = "webapp.list.subscription", params = "sid", type = AzureOperation.Type.SERVICE) private List webapps(String sid, boolean... force) { - final AzureResourceManager azureResourceManager = getAzureResourceManager(sid); + final AppServiceManager azureResourceManager = getAppServiceManager(sid); return azureResourceManager.webApps().list().stream().parallel() .filter(webAppBasic -> !StringUtils.containsIgnoreCase(webAppBasic.innerModel().kind(), "functionapp")) // Filter out function apps .map(webAppBasic -> new WebApp(webAppBasic, azureResourceManager)) @@ -152,7 +152,7 @@ List listWebAppRuntimes(@Nonnull OperatingSystem os, @Nonnull JavaVersi @Cacheable(cacheName = "appservcie/plan/{}", key = "$id") @AzureOperation(name = "appservice|plan.get.id", params = "id", type = AzureOperation.Type.SERVICE) public IAppServicePlan appServicePlan(String id) { - return new AppServicePlan(id, getAzureResourceManager(Utils.getSubscriptionId(id))); + return new AppServicePlan(id, getAppServiceManager(Utils.getSubscriptionId(id))); } public IAppServicePlan appServicePlan(String resourceGroup, String name) { @@ -162,7 +162,7 @@ public IAppServicePlan appServicePlan(String resourceGroup, String name) { @Cacheable(cacheName = "appservcie/{}/rg/{}/plan/{}", key = "$sid/$rg/$name") @AzureOperation(name = "appservice|plan.get.name|rg|sid", params = {"name", "rg", "sid"}, type = AzureOperation.Type.SERVICE) public IAppServicePlan appServicePlan(String sid, String rg, String name) { - return new AppServicePlan(sid, rg, name, getAzureResourceManager(sid)); + return new AppServicePlan(sid, rg, name, getAppServiceManager(sid)); } public IAppServicePlan appServicePlan(AppServicePlanEntity entity) { @@ -181,7 +181,7 @@ public List appServicePlans(boolean... force) { @Cacheable(cacheName = "appservcie/{}/plans", key = "$sid", condition = "!(force&&force[0])") @AzureOperation(name = "appservice|plan.list.subscription", params = "sid", type = AzureOperation.Type.SERVICE) public List appServicePlans(String sid, boolean... force) { - final AzureResourceManager azureResourceManager = getAzureResourceManager(sid); + final AppServiceManager azureResourceManager = getAppServiceManager(sid); return azureResourceManager.appServicePlans().list().stream().parallel() .map(appServicePlan -> new AppServicePlan(appServicePlan, azureResourceManager)) .collect(Collectors.toList()); @@ -191,7 +191,7 @@ public List appServicePlans(String sid, boolean... force) { @AzureOperation(name = "appservice|plan.list.rg", params = "rg", type = AzureOperation.Type.SERVICE) public List appServicePlansByResourceGroup(String rg, boolean... force) { return getSubscriptions().stream().parallel() - .map(subscription -> getAzureResourceManager(subscription.getId())) + .map(subscription -> getAppServiceManager(subscription.getId())) .flatMap(azureResourceManager -> azureResourceManager.appServicePlans().listByResourceGroup(rg).stream() .map(appServicePlan -> new AppServicePlan(appServicePlan, azureResourceManager))) .collect(Collectors.toList()); @@ -201,23 +201,22 @@ public List appServicePlansByResourceGroup(String rg, boolean.. @Cacheable(cacheName = "appservcie/slot/{}", key = "$id") @AzureOperation(name = "appservice|deployment.get.id", params = "id", type = AzureOperation.Type.SERVICE) public IWebAppDeploymentSlot deploymentSlot(String id) { - return new WebAppDeploymentSlot(id, getAzureResourceManager(Utils.getSubscriptionId(id))); + return new WebAppDeploymentSlot(id, getAppServiceManager(Utils.getSubscriptionId(id))); } // todo: share codes with other library which leverage track2 mgmt sdk @Cacheable(cacheName = "appservice/{}/manager", key = "$sid") @AzureOperation(name = "appservice.get_client.subscription", params = "sid", type = AzureOperation.Type.SERVICE) - public AzureResourceManager getAzureResourceManager(String sid) { + public AppServiceManager getAppServiceManager(String sid) { final Account account = Azure.az(AzureAccount.class).account(); final AzureConfiguration config = Azure.az().config(); final String userAgent = config.getUserAgent(); final HttpLogDetailLevel logLevel = Optional.ofNullable(config.getLogLevel()).map(HttpLogDetailLevel::valueOf).orElse(HttpLogDetailLevel.NONE); - final AzureProfile azureProfile = new AzureProfile(account.getEnvironment()); - return AzureResourceManager.configure() + final AzureProfile azureProfile = new AzureProfile(null, sid, account.getEnvironment()); + return AppServiceManager.configure() .withLogLevel(logLevel) .withPolicy(getUserAgentPolicy(userAgent)) // set user agent with policy - .authenticate(account.getTokenCredential(sid), azureProfile) - .withSubscription(sid); + .authenticate(account.getTokenCredential(sid), azureProfile); } private HttpPipelinePolicy getUserAgentPolicy(String userAgent) { diff --git a/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/service/impl/AppServicePlan.java b/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/service/impl/AppServicePlan.java index e4c857cbab..8cd0b2b861 100644 --- a/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/service/impl/AppServicePlan.java +++ b/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/service/impl/AppServicePlan.java @@ -4,7 +4,7 @@ */ package com.microsoft.azure.toolkit.lib.appservice.service.impl; -import com.azure.resourcemanager.AzureResourceManager; +import com.azure.resourcemanager.appservice.AppServiceManager; import com.microsoft.azure.toolkit.lib.appservice.entity.AppServicePlanEntity; import com.microsoft.azure.toolkit.lib.appservice.model.OperatingSystem; import com.microsoft.azure.toolkit.lib.appservice.model.PricingTier; @@ -23,21 +23,21 @@ public class AppServicePlan extends AbstractAzureManager implements IFunctionApp { public static final JavaVersion DEFAULT_JAVA_VERSION = JavaVersion.JAVA_8; private static final String UNSUPPORTED_OPERATING_SYSTEM = "Unsupported operating system %s"; - private final AzureResourceManager azureClient; + private final AppServiceManager azureClient; - public FunctionApp(@Nonnull final String id, @Nonnull final AzureResourceManager azureClient) { + public FunctionApp(@Nonnull final String id, @Nonnull final AppServiceManager azureClient) { super(id); this.azureClient = azureClient; } public FunctionApp(@Nonnull final String subscriptionId, @Nonnull final String resourceGroup, @Nonnull final String name, - @Nonnull final AzureResourceManager azureClient) { + @Nonnull final AppServiceManager azureClient) { super(subscriptionId, resourceGroup, name); this.azureClient = azureClient; } - public FunctionApp(@Nonnull WebSiteBase webSiteBase, @Nonnull final AzureResourceManager azureClient) { + public FunctionApp(@Nonnull WebSiteBase webSiteBase, @Nonnull final AppServiceManager azureClient) { super(webSiteBase); this.azureClient = azureClient; } @@ -199,18 +198,17 @@ public FunctionApp commit() { if (appServicePlan == null) { throw new AzureToolkitRuntimeException("Target app service plan not exists"); } - final ResourceGroup resourceGroup = FunctionApp.this.azureClient.resourceGroups().getByName(getResourceGroup()); final WithCreate withCreate; switch (runtime.getOperatingSystem()) { case LINUX: - withCreate = createLinuxFunctionApp(blank, resourceGroup, appServicePlan, runtime); + withCreate = createLinuxFunctionApp(blank, appServicePlan, runtime); break; case WINDOWS: - withCreate = createWindowsFunctionApp(blank, resourceGroup, appServicePlan, runtime); + withCreate = createWindowsFunctionApp(blank, appServicePlan, runtime); break; case DOCKER: final DockerConfiguration dockerConfiguration = getDockerConfiguration().get(); - withCreate = createDockerFunctionApp(blank, resourceGroup, appServicePlan, dockerConfiguration); + withCreate = createDockerFunctionApp(blank, appServicePlan, dockerConfiguration); break; default: throw new AzureToolkitRuntimeException(String.format(UNSUPPORTED_OPERATING_SYSTEM, runtime.getOperatingSystem())); @@ -227,22 +225,20 @@ public FunctionApp commit() { return FunctionApp.this; } - WithCreate createWindowsFunctionApp(Blank blank, ResourceGroup resourceGroup, com.azure.resourcemanager.appservice.models.AppServicePlan appServicePlan, - Runtime runtime) { + WithCreate createWindowsFunctionApp(Blank blank, com.azure.resourcemanager.appservice.models.AppServicePlan appServicePlan, Runtime runtime) { return (WithCreate) blank.withExistingAppServicePlan(appServicePlan) .withExistingResourceGroup(resourceGroup) .withJavaVersion(AppServiceUtils.toJavaVersion(runtime.getJavaVersion())) .withWebContainer(null); } - WithCreate createLinuxFunctionApp(Blank blank, ResourceGroup resourceGroup, com.azure.resourcemanager.appservice.models.AppServicePlan appServicePlan, - Runtime runtime) { + WithCreate createLinuxFunctionApp(Blank blank, com.azure.resourcemanager.appservice.models.AppServicePlan appServicePlan, Runtime runtime) { return blank.withExistingLinuxAppServicePlan(appServicePlan) .withExistingResourceGroup(resourceGroup) .withBuiltInImage(AppServiceUtils.toFunctionRuntimeStack(runtime)); } - WithCreate createDockerFunctionApp(Blank blank, ResourceGroup resourceGroup, com.azure.resourcemanager.appservice.models.AppServicePlan appServicePlan, + WithCreate createDockerFunctionApp(Blank blank, com.azure.resourcemanager.appservice.models.AppServicePlan appServicePlan, DockerConfiguration dockerConfiguration) { // check service plan, consumption is not supported if (StringUtils.equalsIgnoreCase(appServicePlan.pricingTier().toSkuDescription().tier(), "Dynamic")) { diff --git a/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/service/impl/WebApp.java b/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/service/impl/WebApp.java index 2e523ede58..2613143c20 100644 --- a/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/service/impl/WebApp.java +++ b/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/service/impl/WebApp.java @@ -5,13 +5,12 @@ package com.microsoft.azure.toolkit.lib.appservice.service.impl; import com.azure.core.util.logging.ClientLogger; -import com.azure.resourcemanager.AzureResourceManager; +import com.azure.resourcemanager.appservice.AppServiceManager; import com.azure.resourcemanager.appservice.models.AppServicePlan; import com.azure.resourcemanager.appservice.models.DeployOptions; import com.azure.resourcemanager.appservice.models.WebApp.DefinitionStages; import com.azure.resourcemanager.appservice.models.WebApp.Update; import com.azure.resourcemanager.appservice.models.WebSiteBase; -import com.azure.resourcemanager.resources.models.ResourceGroup; import com.microsoft.azure.toolkit.lib.Azure; import com.microsoft.azure.toolkit.lib.appservice.AzureAppService; import com.microsoft.azure.toolkit.lib.appservice.entity.AppServicePlanEntity; @@ -48,20 +47,20 @@ public class WebApp extends AbstractAppService selectedSubscriptionIds) { } if (entity.getSubscriptions().stream().anyMatch(s -> Utils.containsIgnoreCase(selectedSubscriptionIds, s.getId()))) { selectSubscriptionInner(this.getSubscriptions(), selectedSubscriptionIds); - final AzureTaskManager manager = AzureTaskManager.getInstance(); - if (Objects.nonNull(manager)) { - manager.runOnPooledThread(Preloader::load); - } +// final AzureTaskManager manager = AzureTaskManager.getInstance(); +// if (Objects.nonNull(manager)) { +// manager.runOnPooledThread(Preloader::load); +// } } else { throw new AzureToolkitAuthenticationException("no subscriptions are selected, " + "make sure you have provided valid subscription list"); diff --git a/azure-toolkit-libs/azure-toolkit-common-lib/src/main/java/com/microsoft/azure/toolkit/lib/Azure.java b/azure-toolkit-libs/azure-toolkit-common-lib/src/main/java/com/microsoft/azure/toolkit/lib/Azure.java index cfd39c20c1..739fc5d4c0 100644 --- a/azure-toolkit-libs/azure-toolkit-common-lib/src/main/java/com/microsoft/azure/toolkit/lib/Azure.java +++ b/azure-toolkit-libs/azure-toolkit-common-lib/src/main/java/com/microsoft/azure/toolkit/lib/Azure.java @@ -19,15 +19,21 @@ private Azure() { } public static synchronized T az(final Class clazz) { - T service = getService(clazz); - if (service == null) { - Holder.loader.reload(); - service = getService(clazz); - } - if (service != null) { - return service; + long start = System.currentTimeMillis(); + try { + T service = getService(clazz); + if (service == null) { + Holder.loader.reload(); + service = getService(clazz); + } + if (service != null) { + return service; + } + throw new AzureToolkitRuntimeException(String.format("Azure service(%s) not supported", clazz.getSimpleName())); + } finally { + long end = System.currentTimeMillis(); + } - throw new AzureToolkitRuntimeException(String.format("Azure service(%s) not supported", clazz.getSimpleName())); } @Nullable From b30269907239e3668d87e67a91c6976dad1d08f4 Mon Sep 17 00:00:00 2001 From: Hanxiao Liu Date: Mon, 30 Aug 2021 13:47:31 +0800 Subject: [PATCH 016/126] Migrate to resource group creation task in web app maven plugin --- .../azure/maven/webapp/DeployMojo.java | 19 ++++--------------- 1 file changed, 4 insertions(+), 15 deletions(-) diff --git a/azure-webapp-maven-plugin/src/main/java/com/microsoft/azure/maven/webapp/DeployMojo.java b/azure-webapp-maven-plugin/src/main/java/com/microsoft/azure/maven/webapp/DeployMojo.java index c816176695..92b852ced2 100644 --- a/azure-webapp-maven-plugin/src/main/java/com/microsoft/azure/maven/webapp/DeployMojo.java +++ b/azure-webapp-maven-plugin/src/main/java/com/microsoft/azure/maven/webapp/DeployMojo.java @@ -5,9 +5,6 @@ package com.microsoft.azure.maven.webapp; -import com.azure.core.management.exception.ManagementException; -import com.azure.resourcemanager.AzureResourceManager; -import com.azure.resourcemanager.resources.models.ResourceGroup; import com.microsoft.azure.maven.model.DeploymentResource; import com.microsoft.azure.maven.webapp.utils.DeployUtils; import com.microsoft.azure.maven.webapp.utils.Utils; @@ -26,6 +23,8 @@ 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.model.ResourceGroup; +import com.microsoft.azure.toolkit.lib.resource.task.CreateResourceGroupTask; import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.io.FileUtils; import org.apache.commons.lang3.StringUtils; @@ -120,7 +119,7 @@ private IWebApp createWebApp(final IWebApp webApp, final WebAppConfig webAppConf final IAppServicePlan appServicePlan = getOrCreateAppServicePlan(webAppConfig); AzureMessager.getMessager().info(String.format(CREATE_WEBAPP, webAppConfig.getAppName())); final IWebApp result = webApp.create().withName(webAppConfig.getAppName()) - .withResourceGroup(resourceGroup.name()) + .withResourceGroup(resourceGroup.getName()) .withPlan(appServicePlan.id()) .withRuntime(webAppConfig.getRuntime()) .withDockerConfiguration(webAppConfig.getDockerConfiguration()) @@ -160,17 +159,7 @@ private IWebApp updateWebApp(final IWebApp webApp, final WebAppConfig webAppConf private ResourceGroup getOrCreateResourceGroup(final WebAppConfig webAppConfig) { // todo: Extract resource group logic to library - final AzureResourceManager azureResourceManager = az.getAzureResourceManager(webAppConfig.getSubscriptionId()); - try { - return azureResourceManager.resourceGroups().getByName(webAppConfig.getResourceGroup()); - } catch (ManagementException e) { - AzureMessager.getMessager().info(String.format(CREATE_RESOURCE_GROUP, webAppConfig.getResourceGroup(), webAppConfig.getRegion().getName())); - getTelemetryProxy().addDefaultProperty(CREATE_NEW_RESOURCE_GROUP, String.valueOf(true)); - final ResourceGroup result = azureResourceManager.resourceGroups().define(webAppConfig.getResourceGroup()) - .withRegion(webAppConfig.getRegion().getName()).create(); - AzureMessager.getMessager().info(String.format(CREATE_RESOURCE_GROUP_DONE, webAppConfig.getResourceGroup())); - return result; - } + return new CreateResourceGroupTask(webAppConfig.getSubscriptionId(), webAppConfig.getResourceGroup(), webAppConfig.getRegion()).execute(); } private IAppServicePlan getOrCreateAppServicePlan(final WebAppConfig webAppConfig) { From 73c078fa49189aa293743bd1a6bc5d25f899109f Mon Sep 17 00:00:00 2001 From: Hanxiao Liu Date: Mon, 30 Aug 2021 19:02:01 +0800 Subject: [PATCH 017/126] Revert test changes --- .../azure/toolkit/lib/auth/Account.java | 8 +++---- .../microsoft/azure/toolkit/lib/Azure.java | 22 +++++++------------ 2 files changed, 12 insertions(+), 18 deletions(-) diff --git a/azure-toolkit-libs/azure-toolkit-auth-lib/src/main/java/com/microsoft/azure/toolkit/lib/auth/Account.java b/azure-toolkit-libs/azure-toolkit-auth-lib/src/main/java/com/microsoft/azure/toolkit/lib/auth/Account.java index 0edcf59afc..dcab44036f 100644 --- a/azure-toolkit-libs/azure-toolkit-auth-lib/src/main/java/com/microsoft/azure/toolkit/lib/auth/Account.java +++ b/azure-toolkit-libs/azure-toolkit-auth-lib/src/main/java/com/microsoft/azure/toolkit/lib/auth/Account.java @@ -119,10 +119,10 @@ public void selectSubscription(List selectedSubscriptionIds) { } if (entity.getSubscriptions().stream().anyMatch(s -> Utils.containsIgnoreCase(selectedSubscriptionIds, s.getId()))) { selectSubscriptionInner(this.getSubscriptions(), selectedSubscriptionIds); -// final AzureTaskManager manager = AzureTaskManager.getInstance(); -// if (Objects.nonNull(manager)) { -// manager.runOnPooledThread(Preloader::load); -// } + final AzureTaskManager manager = AzureTaskManager.getInstance(); + if (Objects.nonNull(manager)) { + manager.runOnPooledThread(Preloader::load); + } } else { throw new AzureToolkitAuthenticationException("no subscriptions are selected, " + "make sure you have provided valid subscription list"); diff --git a/azure-toolkit-libs/azure-toolkit-common-lib/src/main/java/com/microsoft/azure/toolkit/lib/Azure.java b/azure-toolkit-libs/azure-toolkit-common-lib/src/main/java/com/microsoft/azure/toolkit/lib/Azure.java index 739fc5d4c0..cfd39c20c1 100644 --- a/azure-toolkit-libs/azure-toolkit-common-lib/src/main/java/com/microsoft/azure/toolkit/lib/Azure.java +++ b/azure-toolkit-libs/azure-toolkit-common-lib/src/main/java/com/microsoft/azure/toolkit/lib/Azure.java @@ -19,21 +19,15 @@ private Azure() { } public static synchronized T az(final Class clazz) { - long start = System.currentTimeMillis(); - try { - T service = getService(clazz); - if (service == null) { - Holder.loader.reload(); - service = getService(clazz); - } - if (service != null) { - return service; - } - throw new AzureToolkitRuntimeException(String.format("Azure service(%s) not supported", clazz.getSimpleName())); - } finally { - long end = System.currentTimeMillis(); - + T service = getService(clazz); + if (service == null) { + Holder.loader.reload(); + service = getService(clazz); + } + if (service != null) { + return service; } + throw new AzureToolkitRuntimeException(String.format("Azure service(%s) not supported", clazz.getSimpleName())); } @Nullable From 7ab7c0431b3289d8fc6471310b45c3fac86b051c Mon Sep 17 00:00:00 2001 From: Hanxiao Liu Date: Tue, 31 Aug 2021 10:00:23 +0800 Subject: [PATCH 018/126] Resolve checkstyle issues --- .../toolkit/lib/applicationinsights/ApplicationInsights.java | 4 ++++ .../azure/toolkit/lib/appservice/AzureAppService.java | 4 ++-- .../toolkit/lib/appservice/service/impl/AppServiceUtils.java | 2 +- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/azure-toolkit-libs/azure-toolkit-applicationinsights-lib/src/main/java/com/microsoft/azure/toolkit/lib/applicationinsights/ApplicationInsights.java b/azure-toolkit-libs/azure-toolkit-applicationinsights-lib/src/main/java/com/microsoft/azure/toolkit/lib/applicationinsights/ApplicationInsights.java index 884eb4e512..ab2a805097 100644 --- a/azure-toolkit-libs/azure-toolkit-applicationinsights-lib/src/main/java/com/microsoft/azure/toolkit/lib/applicationinsights/ApplicationInsights.java +++ b/azure-toolkit-libs/azure-toolkit-applicationinsights-lib/src/main/java/com/microsoft/azure/toolkit/lib/applicationinsights/ApplicationInsights.java @@ -1,3 +1,7 @@ +/* + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + */ package com.microsoft.azure.toolkit.lib.applicationinsights; import com.azure.core.http.policy.HttpLogDetailLevel; diff --git a/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/AzureAppService.java b/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/AzureAppService.java index 4a20a7b4dd..4c841b4c4c 100644 --- a/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/AzureAppService.java +++ b/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/AzureAppService.java @@ -142,8 +142,8 @@ private List webapps(String sid, boolean... force) { } @Nonnull - public @AzureOperation(name = "webapp|runtime.list.os|version", params = {"os.getValue()", "version.getValue()"}, type = AzureOperation.Type.SERVICE) - List listWebAppRuntimes(@Nonnull OperatingSystem os, @Nonnull JavaVersion version) { + @AzureOperation(name = "webapp|runtime.list.os|version", params = {"os.getValue()", "version.getValue()"}, type = AzureOperation.Type.SERVICE) + public List listWebAppRuntimes(@Nonnull OperatingSystem os, @Nonnull JavaVersion version) { return Runtime.WEBAPP_RUNTIME.stream() .filter(runtime -> Objects.equals(os, runtime.getOperatingSystem()) && Objects.equals(version, runtime.getJavaVersion())) .collect(Collectors.toList()); diff --git a/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/service/impl/AppServiceUtils.java b/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/service/impl/AppServiceUtils.java index 2bd08203af..dddf1a054f 100644 --- a/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/service/impl/AppServiceUtils.java +++ b/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/service/impl/AppServiceUtils.java @@ -71,7 +71,7 @@ private static Runtime getRuntimeFromLinuxAppService(WebAppBase webAppBase) { } final String linuxFxVersion = webAppBase.linuxFxVersion(); return StringUtils.containsIgnoreCase(webAppBase.innerModel().kind(), "function") ? - getRuntimeFromLinuxFunctionApp(linuxFxVersion) : Runtime.getRuntimeFromLinuxFxVersion(linuxFxVersion); + getRuntimeFromLinuxFunctionApp(linuxFxVersion) : Runtime.getRuntimeFromLinuxFxVersion(linuxFxVersion); } private static Runtime getRuntimeFromLinuxFunctionApp(String linuxFxVersion) { From 0261871083e77c612f13e035c6570c472ca80769 Mon Sep 17 00:00:00 2001 From: Hanxiao Liu Date: Wed, 1 Sep 2021 17:12:56 +0800 Subject: [PATCH 019/126] Fix cache name for application insights --- .../toolkit/lib/applicationinsights/ApplicationInsights.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/azure-toolkit-libs/azure-toolkit-applicationinsights-lib/src/main/java/com/microsoft/azure/toolkit/lib/applicationinsights/ApplicationInsights.java b/azure-toolkit-libs/azure-toolkit-applicationinsights-lib/src/main/java/com/microsoft/azure/toolkit/lib/applicationinsights/ApplicationInsights.java index ab2a805097..860e6acd4c 100644 --- a/azure-toolkit-libs/azure-toolkit-applicationinsights-lib/src/main/java/com/microsoft/azure/toolkit/lib/applicationinsights/ApplicationInsights.java +++ b/azure-toolkit-libs/azure-toolkit-applicationinsights-lib/src/main/java/com/microsoft/azure/toolkit/lib/applicationinsights/ApplicationInsights.java @@ -98,7 +98,7 @@ public void delete(@Nonnull String subscriptionId, @Nonnull String resourceGroup getApplicationInsightsManager(subscriptionId).components().deleteByResourceGroup(resourceGroup, name); } - @Cacheable(cacheName = "AzureResourceManager", key = "$subscriptionId") + @Cacheable(cacheName = "applicationinsights/{}/manager", key = "$subscriptionId") private ApplicationInsightsManager getApplicationInsightsManager(String subscriptionId) { final Account account = Azure.az(AzureAccount.class).account(); final String tenantId = account.getSubscription(subscriptionId).getTenantId(); From 870ce26221c1c66f10be14d396f29f6e3a31b73c Mon Sep 17 00:00:00 2001 From: Hanxiao Liu Date: Wed, 1 Sep 2021 17:13:56 +0800 Subject: [PATCH 020/126] Fix typo in cache name --- .../lib/appservice/AzureAppService.java | 22 +++++++++---------- .../appservice/service/impl/FunctionApp.java | 2 +- .../lib/appservice/service/impl/WebApp.java | 2 +- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/AzureAppService.java b/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/AzureAppService.java index 4c841b4c4c..2787ef964b 100644 --- a/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/AzureAppService.java +++ b/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/AzureAppService.java @@ -54,7 +54,7 @@ private AzureAppService(@Nonnull final List subscriptions) { super(AzureAppService::new, subscriptions); } - @Cacheable(cacheName = "appservcie/functionapp/{}", key = "$id") + @Cacheable(cacheName = "appservice/functionapp/{}", key = "$id") @AzureOperation(name = "functionapp.get.id", params = {"id"}, type = AzureOperation.Type.SERVICE) public IFunctionApp functionApp(String id) { return new FunctionApp(id, getAppServiceManager(Utils.getSubscriptionId(id))); @@ -64,7 +64,7 @@ public IFunctionApp functionApp(String resourceGroup, String name) { return functionApp(getDefaultSubscription().getId(), resourceGroup, name); } - @Cacheable(cacheName = "appservcie/{}/rg/{}/functionapp/{}", key = "$sid/$rg/$name") + @Cacheable(cacheName = "appservice/{}/rg/{}/functionapp/{}", key = "$sid/$rg/$name") @AzureOperation(name = "functionapp.get.name|rg|sid", params = {"name", "rg", "sid"}, type = AzureOperation.Type.SERVICE) public IFunctionApp functionApp(String sid, String rg, String name) { return new FunctionApp(sid, rg, name, getAppServiceManager(sid)); @@ -83,7 +83,7 @@ public List functionApps(boolean... force) { .collect(Collectors.toList()); } - @Cacheable(cacheName = "appservcie/{}/functionapps", key = "$sid", condition = "!(force&&force[0])") + @Cacheable(cacheName = "appservice/{}/functionapps", key = "$sid", condition = "!(force&&force[0])") @AzureOperation(name = "functionapp.list.subscription", params = "sid", type = AzureOperation.Type.SERVICE) private List functionApps(String sid, boolean... force) { final AppServiceManager azureResourceManager = getAppServiceManager(sid); @@ -94,7 +94,7 @@ private List functionApps(String sid, boolean... force) { .collect(Collectors.toList()); } - @Cacheable(cacheName = "appservcie/webapp/{}", key = "$id") + @Cacheable(cacheName = "appservice/webapp/{}", key = "$id") @AzureOperation(name = "webapp.get.id", params = "id", type = AzureOperation.Type.SERVICE) public IWebApp webapp(String id) { return new WebApp(id, getAppServiceManager(Utils.getSubscriptionId(id))); @@ -104,7 +104,7 @@ public IWebApp webapp(String resourceGroup, String name) { return webapp(getDefaultSubscription().getId(), resourceGroup, name); } - @Cacheable(cacheName = "appservcie/{}/rg/{}/webapp/{}", key = "$sid/$rg/$name") + @Cacheable(cacheName = "appservice/{}/rg/{}/webapp/{}", key = "$sid/$rg/$name") @AzureOperation(name = "webapp.get.name|rg|sid", params = {"name", "rg", "sid"}, type = AzureOperation.Type.SERVICE) public IWebApp webapp(String sid, String rg, String name) { return new WebApp(sid, rg, name, getAppServiceManager(sid)); @@ -131,7 +131,7 @@ public CheckNameAvailabilityResultEntity checkNameAvailability(String subscripti return new CheckNameAvailabilityResultEntity(result.nameAvailable(), result.reason().toString(), result.message()); } - @Cacheable(cacheName = "appservcie/{}/webapps", key = "$sid", condition = "!(force&&force[0])") + @Cacheable(cacheName = "appservice/{}/webapps", key = "$sid", condition = "!(force&&force[0])") @AzureOperation(name = "webapp.list.subscription", params = "sid", type = AzureOperation.Type.SERVICE) private List webapps(String sid, boolean... force) { final AppServiceManager azureResourceManager = getAppServiceManager(sid); @@ -149,7 +149,7 @@ public List listWebAppRuntimes(@Nonnull OperatingSystem os, @Nonnull Ja .collect(Collectors.toList()); } - @Cacheable(cacheName = "appservcie/plan/{}", key = "$id") + @Cacheable(cacheName = "appservice/plan/{}", key = "$id") @AzureOperation(name = "appservice|plan.get.id", params = "id", type = AzureOperation.Type.SERVICE) public IAppServicePlan appServicePlan(String id) { return new AppServicePlan(id, getAppServiceManager(Utils.getSubscriptionId(id))); @@ -159,7 +159,7 @@ public IAppServicePlan appServicePlan(String resourceGroup, String name) { return appServicePlan(getDefaultSubscription().getId(), resourceGroup, name); } - @Cacheable(cacheName = "appservcie/{}/rg/{}/plan/{}", key = "$sid/$rg/$name") + @Cacheable(cacheName = "appservice/{}/rg/{}/plan/{}", key = "$sid/$rg/$name") @AzureOperation(name = "appservice|plan.get.name|rg|sid", params = {"name", "rg", "sid"}, type = AzureOperation.Type.SERVICE) public IAppServicePlan appServicePlan(String sid, String rg, String name) { return new AppServicePlan(sid, rg, name, getAppServiceManager(sid)); @@ -178,7 +178,7 @@ public List appServicePlans(boolean... force) { .collect(Collectors.toList()); } - @Cacheable(cacheName = "appservcie/{}/plans", key = "$sid", condition = "!(force&&force[0])") + @Cacheable(cacheName = "appservice/{}/plans", key = "$sid", condition = "!(force&&force[0])") @AzureOperation(name = "appservice|plan.list.subscription", params = "sid", type = AzureOperation.Type.SERVICE) public List appServicePlans(String sid, boolean... force) { final AppServiceManager azureResourceManager = getAppServiceManager(sid); @@ -187,7 +187,7 @@ public List appServicePlans(String sid, boolean... force) { .collect(Collectors.toList()); } - @Cacheable(cacheName = "appservcie/rg/{}/plans", key = "$rg", condition = "!(force&&force[0])") + @Cacheable(cacheName = "appservice/rg/{}/plans", key = "$rg", condition = "!(force&&force[0])") @AzureOperation(name = "appservice|plan.list.rg", params = "rg", type = AzureOperation.Type.SERVICE) public List appServicePlansByResourceGroup(String rg, boolean... force) { return getSubscriptions().stream().parallel() @@ -198,7 +198,7 @@ public List appServicePlansByResourceGroup(String rg, boolean.. } @Deprecated - @Cacheable(cacheName = "appservcie/slot/{}", key = "$id") + @Cacheable(cacheName = "appservice/slot/{}", key = "$id") @AzureOperation(name = "appservice|deployment.get.id", params = "id", type = AzureOperation.Type.SERVICE) public IWebAppDeploymentSlot deploymentSlot(String id) { return new WebAppDeploymentSlot(id, getAppServiceManager(Utils.getSubscriptionId(id))); diff --git a/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/service/impl/FunctionApp.java b/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/service/impl/FunctionApp.java index e5626f263b..d2f2913ddf 100644 --- a/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/service/impl/FunctionApp.java +++ b/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/service/impl/FunctionApp.java @@ -136,7 +136,7 @@ public AbstractAppService Date: Fri, 3 Sep 2021 09:52:50 +0800 Subject: [PATCH 021/126] Migrate from AzureResourceManager to ResourceManager in auth-lib(2) --- .../azure/toolkit/lib/auth/AzureAccount.java | 13 ++++++------- .../toolkit/lib/auth/TokenCredentialManager.java | 2 +- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/azure-toolkit-libs/azure-toolkit-auth-lib/src/main/java/com/microsoft/azure/toolkit/lib/auth/AzureAccount.java b/azure-toolkit-libs/azure-toolkit-auth-lib/src/main/java/com/microsoft/azure/toolkit/lib/auth/AzureAccount.java index d7a6f3b9c2..ee9c1700b6 100644 --- a/azure-toolkit-libs/azure-toolkit-auth-lib/src/main/java/com/microsoft/azure/toolkit/lib/auth/AzureAccount.java +++ b/azure-toolkit-libs/azure-toolkit-auth-lib/src/main/java/com/microsoft/azure/toolkit/lib/auth/AzureAccount.java @@ -13,7 +13,7 @@ import com.azure.identity.SharedTokenCacheCredential; import com.azure.identity.SharedTokenCacheCredentialBuilder; import com.azure.identity.TokenCachePersistenceOptions; -import com.azure.resourcemanager.AzureResourceManager; +import com.azure.resourcemanager.resources.ResourceManager; import com.azure.resourcemanager.resources.fluentcore.policy.ProviderRegistrationPolicy; import com.azure.resourcemanager.resources.models.Location; import com.azure.resourcemanager.resources.models.Providers; @@ -276,12 +276,11 @@ private static Map> buildAccountMap() { // todo: share codes with other library which leverage track2 mgmt sdk @Cacheable(cacheName = "Subscription", key = "$subscriptionId") private Subscription getSubscription(String subscriptionId) { - return getAzureResourceManager(subscriptionId).subscriptions().getById(subscriptionId); + return getResourceManager(subscriptionId).subscriptions().getById(subscriptionId); } - // todo: share codes with other library which leverage track2 mgmt sdk - @Cacheable(cacheName = "AzureResourceManager", key = "$subscriptionId") - private AzureResourceManager getAzureResourceManager(String subscriptionId) { + @Cacheable(cacheName = "resource/{}/manager", key = "$subscriptionId") + private ResourceManager getResourceManager(String subscriptionId) { // make sure it is signed in. account(); final AzureConfiguration config = Azure.az().config(); @@ -290,11 +289,11 @@ private AzureResourceManager getAzureResourceManager(String subscriptionId) { HttpLogDetailLevel.NONE : HttpLogDetailLevel.valueOf(config.getLogLevel()); final AzureProfile azureProfile = new AzureProfile(account.getEnvironment()); - final Providers providers = AzureResourceManager.configure() + final Providers providers = ResourceManager.configure() .withPolicy(getUserAgentPolicy(userAgent)) .authenticate(account.getTokenCredential(subscriptionId), azureProfile) .withSubscription(subscriptionId).providers(); - return AzureResourceManager.configure() + return ResourceManager.configure() .withLogLevel(logDetailLevel) .withPolicy(getUserAgentPolicy(userAgent)) // set user agent with policy .withPolicy(new ProviderRegistrationPolicy(providers)) // add policy to auto register resource providers diff --git a/azure-toolkit-libs/azure-toolkit-auth-lib/src/main/java/com/microsoft/azure/toolkit/lib/auth/TokenCredentialManager.java b/azure-toolkit-libs/azure-toolkit-auth-lib/src/main/java/com/microsoft/azure/toolkit/lib/auth/TokenCredentialManager.java index 8182b3bcf2..42fb822a28 100644 --- a/azure-toolkit-libs/azure-toolkit-auth-lib/src/main/java/com/microsoft/azure/toolkit/lib/auth/TokenCredentialManager.java +++ b/azure-toolkit-libs/azure-toolkit-auth-lib/src/main/java/com/microsoft/azure/toolkit/lib/auth/TokenCredentialManager.java @@ -100,7 +100,7 @@ private ResourceManager.Authenticated createAzureClient(AzureEnvironment env) { } /** - * TODO: share the same code for creating AzureResourceManager.Configurable + * TODO: share the same code for creating ResourceManager.Configurable */ private static ResourceManager.Configurable configureAzure() { OkHttpAsyncHttpClientBuilder builder = new OkHttpAsyncHttpClientBuilder(); From 284d2fb1cd8293226027b6c50a809254fc8e7fa1 Mon Sep 17 00:00:00 2001 From: Hanxiao Liu Date: Fri, 3 Sep 2021 13:36:08 +0800 Subject: [PATCH 022/126] Update checkstyle rules --- .../checkstyle/checkstyle-suppressions.xml | 3 +- .../main/resources/checkstyle/checkstyle.xml | 135 ++++++++++-------- 2 files changed, 79 insertions(+), 59 deletions(-) diff --git a/build-tools/src/main/resources/checkstyle/checkstyle-suppressions.xml b/build-tools/src/main/resources/checkstyle/checkstyle-suppressions.xml index 628f7bbf21..6303c32f8a 100644 --- a/build-tools/src/main/resources/checkstyle/checkstyle-suppressions.xml +++ b/build-tools/src/main/resources/checkstyle/checkstyle-suppressions.xml @@ -4,5 +4,6 @@ "https://checkstyle.org/dtds/suppressions_1_1.dtd"> - + + diff --git a/build-tools/src/main/resources/checkstyle/checkstyle.xml b/build-tools/src/main/resources/checkstyle/checkstyle.xml index a944eae803..6fd52915b5 100644 --- a/build-tools/src/main/resources/checkstyle/checkstyle.xml +++ b/build-tools/src/main/resources/checkstyle/checkstyle.xml @@ -10,7 +10,7 @@ page at https://checkstyle.org/config.html --> - + @@ -26,17 +26,17 @@ page at https://checkstyle.org/config.html --> - - - + + + - - - - - + + + + + + + @@ -51,19 +51,19 @@ page at https://checkstyle.org/config.html --> - - - - - + + + + + + + + - + - + - - - - - + + + + + - - - - - - - - - - - --> - + @@ -212,7 +200,7 @@ page at https://checkstyle.org/config.html --> --> - + @@ -234,7 +222,7 @@ page at https://checkstyle.org/config.html --> --> - + @@ -268,7 +256,7 @@ page at https://checkstyle.org/config.html --> + value="WhitespaceAround: ''{0}'' is not preceded with whitespace."/> @@ -301,14 +289,15 @@ page at https://checkstyle.org/config.html --> - + + - + - - - + + + - + - - - - - + + + + + @@ -414,17 +403,47 @@ page at https://checkstyle.org/config.html --> - + - + - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From f2e0ddc5efe378f52dcf0458612f5b23f61c111f Mon Sep 17 00:00:00 2001 From: Mingliang Wang Date: Sat, 4 Sep 2021 23:10:34 +0800 Subject: [PATCH 023/126] remove parameter `force` which is only used by cache manager. --- .../lib/springcloud/AzureSpringCloud.java | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/azure-toolkit-libs/azure-toolkit-springcloud-lib/src/main/java/com/microsoft/azure/toolkit/lib/springcloud/AzureSpringCloud.java b/azure-toolkit-libs/azure-toolkit-springcloud-lib/src/main/java/com/microsoft/azure/toolkit/lib/springcloud/AzureSpringCloud.java index 8c76356444..f1091c7f86 100644 --- a/azure-toolkit-libs/azure-toolkit-springcloud-lib/src/main/java/com/microsoft/azure/toolkit/lib/springcloud/AzureSpringCloud.java +++ b/azure-toolkit-libs/azure-toolkit-springcloud-lib/src/main/java/com/microsoft/azure/toolkit/lib/springcloud/AzureSpringCloud.java @@ -18,6 +18,8 @@ import com.microsoft.azure.toolkit.lib.SubscriptionScoped; import com.microsoft.azure.toolkit.lib.auth.Account; import com.microsoft.azure.toolkit.lib.auth.AzureAccount; +import com.microsoft.azure.toolkit.lib.common.cache.CacheEvict; +import com.microsoft.azure.toolkit.lib.common.cache.CacheManager; import com.microsoft.azure.toolkit.lib.common.cache.Cacheable; import com.microsoft.azure.toolkit.lib.common.cache.Preload; import com.microsoft.azure.toolkit.lib.common.event.AzureOperationEvent; @@ -32,6 +34,7 @@ import java.util.List; import java.util.Objects; import java.util.Optional; +import java.util.concurrent.ExecutionException; import java.util.stream.Collectors; @Slf4j @@ -68,16 +71,16 @@ private SpringCloudCluster cluster(@Nonnull SpringCloudClusterEntity cluster) { @Nonnull @Preload @AzureOperation(name = "springcloud|cluster.list.subscription|selected", type = AzureOperation.Type.SERVICE) - public List clusters(boolean... force) { + public List clusters() { return this.getSubscriptions().stream().parallel() - .flatMap(s -> clusters(s.getId(), force).stream()) + .flatMap(s -> clusters(s.getId()).stream()) .collect(Collectors.toList()); } @Nonnull - @Cacheable(cacheName = "asc/{}/clusters", key = "$subscriptionId", condition = "!(force&&force[0])") + @Cacheable(cacheName = "asc/{}/clusters", key = "$subscriptionId") @AzureOperation(name = "springcloud|cluster.list.subscription", params = "subscriptionId", type = AzureOperation.Type.SERVICE) - private List clusters(@Nonnull String subscriptionId, boolean... force) { + private List clusters(@Nonnull String subscriptionId) { try { return getClient(subscriptionId).list().stream() .map(this::cluster) @@ -93,7 +96,11 @@ private List clusters(@Nonnull String subscriptionId, boolea @AzureOperation(name = "common|service.refresh", params = "this.name()", type = AzureOperation.Type.SERVICE) public void refresh() { - this.clusters(true); + try { + CacheManager.evictCache("asc/{}/clusters", CacheEvict.ALL); + } catch (ExecutionException e) { + log.warn("failed to evict cache", e); + } } @Override From 641e0b6aecef0a3178170416306dc880a2abc634 Mon Sep 17 00:00:00 2001 From: Mingliang Wang Date: Sat, 4 Sep 2021 23:12:02 +0800 Subject: [PATCH 024/126] storage account modularization --- .../storage/service/AzureStorageAccount.java | 50 +++++++++++++------ .../lib/storage/service/StorageAccount.java | 19 +++++-- 2 files changed, 50 insertions(+), 19 deletions(-) diff --git a/azure-toolkit-libs/azure-toolkit-storage-lib/src/main/java/com/microsoft/azure/toolkit/lib/storage/service/AzureStorageAccount.java b/azure-toolkit-libs/azure-toolkit-storage-lib/src/main/java/com/microsoft/azure/toolkit/lib/storage/service/AzureStorageAccount.java index d87d6aefd0..5d254e537d 100644 --- a/azure-toolkit-libs/azure-toolkit-storage-lib/src/main/java/com/microsoft/azure/toolkit/lib/storage/service/AzureStorageAccount.java +++ b/azure-toolkit-libs/azure-toolkit-storage-lib/src/main/java/com/microsoft/azure/toolkit/lib/storage/service/AzureStorageAccount.java @@ -5,7 +5,6 @@ package com.microsoft.azure.toolkit.lib.storage.service; - import com.azure.resourcemanager.resources.fluentcore.arm.ResourceId; import com.azure.resourcemanager.storage.StorageManager; import com.azure.resourcemanager.storage.models.CheckNameAvailabilityResult; @@ -14,6 +13,9 @@ import com.azure.resourcemanager.storage.models.StorageAccountSkuType; import com.microsoft.azure.toolkit.lib.AzureService; import com.microsoft.azure.toolkit.lib.SubscriptionScoped; +import com.microsoft.azure.toolkit.lib.common.cache.CacheEvict; +import com.microsoft.azure.toolkit.lib.common.cache.CacheManager; +import com.microsoft.azure.toolkit.lib.common.cache.Cacheable; import com.microsoft.azure.toolkit.lib.common.entity.CheckNameAvailabilityResultEntity; import com.microsoft.azure.toolkit.lib.common.event.AzureOperationEvent; import com.microsoft.azure.toolkit.lib.common.model.Subscription; @@ -24,15 +26,20 @@ import com.microsoft.azure.toolkit.lib.storage.model.Performance; import com.microsoft.azure.toolkit.lib.storage.model.Redundancy; import com.microsoft.azure.toolkit.lib.storage.model.StorageAccountConfig; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; import javax.annotation.Nonnull; import javax.annotation.Nullable; import java.util.List; import java.util.Objects; import java.util.Optional; +import java.util.concurrent.ExecutionException; import java.util.stream.Collectors; -public class AzureStorageAccount extends SubscriptionScoped implements AzureService { +@Slf4j +public class AzureStorageAccount extends SubscriptionScoped + implements AzureService, AzureOperationEvent.Source { public AzureStorageAccount() { super(AzureStorageAccount::new); @@ -44,22 +51,27 @@ private AzureStorageAccount(@Nonnull final List subscriptions) { public List list() { return getSubscriptions().stream() - .map(subscription -> StorageManagerFactory.create(subscription.getId())) - .flatMap(manager -> manager.storageAccounts().list().stream()) - .map(account -> new StorageAccount(account.manager(), account)) + .flatMap(s -> list(s.getId()).stream()) + .collect(Collectors.toList()); + } + + @Cacheable(cacheName = "storage/{}/accounts", key = "$sid") + public List list(String sid) { + return StorageManagerFactory.create(sid).storageAccounts().list().stream() + .map(StorageAccount::new) .collect(Collectors.toList()); } public StorageAccount get(@Nonnull String id) { final com.azure.resourcemanager.storage.models.StorageAccount account = StorageManagerFactory.create(ResourceId.fromString(id).subscriptionId()).storageAccounts().getById(id); - return new StorageAccount(account.manager(), account); + return new StorageAccount(account); } public StorageAccount get(@Nonnull final String resourceGroup, @Nonnull final String name) { final com.azure.resourcemanager.storage.models.StorageAccount account = StorageManagerFactory.create(getDefaultSubscription().getId()).storageAccounts().getByResourceGroup(resourceGroup, name); - return new StorageAccount(account.manager(), account); + return new StorageAccount(account); } public CheckNameAvailabilityResultEntity checkNameAvailability(String subscriptionId, String name) { @@ -84,17 +96,23 @@ public List listSupportedRedundancies(@Nonnull Performance performan .collect(Collectors.toList()); } + @AzureOperation(name = "common|service.refresh", params = "this.name()", type = AzureOperation.Type.SERVICE) + public void refresh() { + try { + CacheManager.evictCache("storage/{}/accounts", CacheEvict.ALL); + } catch (ExecutionException e) { + log.warn("failed to evict cache", e); + } + } + public Creator create(StorageAccountConfig config) { return new Creator(config); } - public class Creator implements ICommittable, AzureOperationEvent.Source { + @RequiredArgsConstructor + public static class Creator implements ICommittable, AzureOperationEvent.Source { - private StorageAccountConfig config; - - Creator(StorageAccountConfig config) { - this.config = config; - } + private final StorageAccountConfig config; @Override @AzureOperation(name = "storage|account.create", params = {"this.config.getName()"}, type = AzureOperation.Type.SERVICE) @@ -115,11 +133,13 @@ public StorageAccount commit() { withCreate = withCreate.withGeneralPurposeAccountKindV2(); } com.azure.resourcemanager.storage.models.StorageAccount account = withCreate.create(); - return new StorageAccount(account.manager(), account); + return new StorageAccount(account); } + @Nonnull public AzureOperationEvent.Source getEventSource() { - return new AzureOperationEvent.Source() {}; + return new AzureOperationEvent.Source() { + }; } } diff --git a/azure-toolkit-libs/azure-toolkit-storage-lib/src/main/java/com/microsoft/azure/toolkit/lib/storage/service/StorageAccount.java b/azure-toolkit-libs/azure-toolkit-storage-lib/src/main/java/com/microsoft/azure/toolkit/lib/storage/service/StorageAccount.java index f3c0c71ea0..7294a22007 100644 --- a/azure-toolkit-libs/azure-toolkit-storage-lib/src/main/java/com/microsoft/azure/toolkit/lib/storage/service/StorageAccount.java +++ b/azure-toolkit-libs/azure-toolkit-storage-lib/src/main/java/com/microsoft/azure/toolkit/lib/storage/service/StorageAccount.java @@ -7,8 +7,10 @@ import com.azure.core.management.exception.ManagementException; import com.azure.resourcemanager.storage.StorageManager; +import com.microsoft.azure.toolkit.lib.Azure; import com.microsoft.azure.toolkit.lib.common.entity.AbstractAzureResource; import com.microsoft.azure.toolkit.lib.common.entity.IAzureResource; +import com.microsoft.azure.toolkit.lib.common.entity.Removable; import com.microsoft.azure.toolkit.lib.common.event.AzureOperationEvent; import com.microsoft.azure.toolkit.lib.common.operation.AzureOperation; import com.microsoft.azure.toolkit.lib.storage.model.StorageAccountEntity; @@ -17,13 +19,13 @@ import javax.annotation.Nonnull; public class StorageAccount extends AbstractAzureResource - implements AzureOperationEvent.Source, IAzureResource { + implements Removable, AzureOperationEvent.Source, IAzureResource { @Nonnull private final StorageManager manager; - public StorageAccount(@Nonnull StorageManager manager, @Nonnull com.azure.resourcemanager.storage.models.StorageAccount server) { + public StorageAccount(@Nonnull com.azure.resourcemanager.storage.models.StorageAccount server) { super(new StorageAccountEntity(server)); - this.manager = manager; + this.manager = server.manager(); } @Override @@ -42,6 +44,15 @@ protected com.azure.resourcemanager.storage.models.StorageAccount loadRemote() { @AzureOperation(name = "storage|account.delete", params = {"this.entity().getName()"}, type = AzureOperation.Type.SERVICE) public void delete() { - manager.storageAccounts().deleteById(this.entity.getId()); + if (this.exists()) { + this.status(Status.PENDING); + manager.storageAccounts().deleteById(this.entity.getId()); + Azure.az(AzureStorageAccount.class).refresh(); + } + } + + @Override + public void remove() { + this.delete(); } } From 58f25a90c0f3e8c52eeb1b5184773f781dd853a4 Mon Sep 17 00:00:00 2001 From: andxu Date: Thu, 2 Sep 2021 16:28:59 +0800 Subject: [PATCH 025/126] [Task 1871987] add redis track2 lib --- .../azure-toolkit-redis-lib/pom.xml | 119 ++++++++++++++++++ .../azure/toolkit/redis/AzureRedis.java | 102 +++++++++++++++ .../azure/toolkit/redis/PricingTier.java | 83 ++++++++++++ .../azure/toolkit/redis/RedisCache.java | 50 ++++++++ .../azure/toolkit/redis/RedisCacheEntity.java | 50 ++++++++ .../azure/toolkit/redis/RedisConfig.java | 27 ++++ .../toolkit/redis/RedisManagerFactory.java | 45 +++++++ ...m.microsoft.azure.toolkit.lib.AzureService | 1 + .../operation/title/base/redis.properties | 4 + azure-toolkit-libs/pom.xml | 7 ++ 10 files changed, 488 insertions(+) create mode 100644 azure-toolkit-libs/azure-toolkit-redis-lib/pom.xml create mode 100644 azure-toolkit-libs/azure-toolkit-redis-lib/src/main/java/com/microsoft/azure/toolkit/redis/AzureRedis.java create mode 100644 azure-toolkit-libs/azure-toolkit-redis-lib/src/main/java/com/microsoft/azure/toolkit/redis/PricingTier.java create mode 100644 azure-toolkit-libs/azure-toolkit-redis-lib/src/main/java/com/microsoft/azure/toolkit/redis/RedisCache.java create mode 100644 azure-toolkit-libs/azure-toolkit-redis-lib/src/main/java/com/microsoft/azure/toolkit/redis/RedisCacheEntity.java create mode 100644 azure-toolkit-libs/azure-toolkit-redis-lib/src/main/java/com/microsoft/azure/toolkit/redis/RedisConfig.java create mode 100644 azure-toolkit-libs/azure-toolkit-redis-lib/src/main/java/com/microsoft/azure/toolkit/redis/RedisManagerFactory.java create mode 100644 azure-toolkit-libs/azure-toolkit-redis-lib/src/main/resources/META-INF/services/com.microsoft.azure.toolkit.lib.AzureService create mode 100644 azure-toolkit-libs/azure-toolkit-redis-lib/src/main/resources/com/microsoft/azure/toolkit/operation/title/base/redis.properties diff --git a/azure-toolkit-libs/azure-toolkit-redis-lib/pom.xml b/azure-toolkit-libs/azure-toolkit-redis-lib/pom.xml new file mode 100644 index 0000000000..bf83c2cdf6 --- /dev/null +++ b/azure-toolkit-libs/azure-toolkit-redis-lib/pom.xml @@ -0,0 +1,119 @@ + + + + azure-toolkit-libs + com.microsoft.azure + 0.12.0-SNAPSHOT + + 4.0.0 + + azure-toolkit-redis-lib + + + + + com.microsoft.azure + azure-toolkit-common-lib + + + + com.microsoft.azure + azure-toolkit-auth-lib + + + + org.projectlombok + lombok + provided + + + + com.azure.resourcemanager + azure-resourcemanager-redis + + + + + + + org.apache.maven.plugins + maven-dependency-plugin + + + org.apache.maven.plugins + maven-source-plugin + + + + + com.nickwongdev + aspectj-maven-plugin + + false + 1.8 + 1.8 + ignore + 1.8 + UTF-8 + false + true + true + + + + com.microsoft.azure + azure-toolkit-common-lib + + + + + + compile-with-aspectj + process-classes + + + ${project.build.directory}/classes + + + + compile + + + + test-compile-with-aspectj + process-test-classes + + test-compile + + + + ${project.build.directory}/test-classes + + + + + + + org.apache.maven.plugins + maven-javadoc-plugin + + private + false + + + + attach-javadocs + + jar + + + ${javadoc.opts} + + + + + + + diff --git a/azure-toolkit-libs/azure-toolkit-redis-lib/src/main/java/com/microsoft/azure/toolkit/redis/AzureRedis.java b/azure-toolkit-libs/azure-toolkit-redis-lib/src/main/java/com/microsoft/azure/toolkit/redis/AzureRedis.java new file mode 100644 index 0000000000..ac3eb8a667 --- /dev/null +++ b/azure-toolkit-libs/azure-toolkit-redis-lib/src/main/java/com/microsoft/azure/toolkit/redis/AzureRedis.java @@ -0,0 +1,102 @@ +/* + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + */ + +package com.microsoft.azure.toolkit.redis; + +import com.azure.core.management.exception.ManagementError; +import com.azure.core.management.exception.ManagementException; +import com.azure.resourcemanager.redis.RedisManager; +import com.azure.resourcemanager.redis.fluent.RedisClient; +import com.azure.resourcemanager.redis.models.CheckNameAvailabilityParameters; +import com.microsoft.azure.toolkit.lib.AzureService; +import com.microsoft.azure.toolkit.lib.SubscriptionScoped; +import com.microsoft.azure.toolkit.lib.common.entity.CheckNameAvailabilityResultEntity; +import com.microsoft.azure.toolkit.lib.common.event.AzureOperationEvent; +import com.microsoft.azure.toolkit.lib.common.model.Subscription; +import com.microsoft.azure.toolkit.lib.common.operation.AzureOperation; +import com.microsoft.azure.toolkit.lib.common.task.ICommittable; +import lombok.AccessLevel; +import lombok.AllArgsConstructor; + +import javax.annotation.Nonnull; +import java.util.List; +import java.util.stream.Collectors; + +public class AzureRedis extends SubscriptionScoped implements AzureService, AzureOperationEvent.Source { + public AzureRedis() { + super(AzureRedis::new); + } + + private AzureRedis(@Nonnull final List subscriptions) { + super(AzureRedis::new, subscriptions); + } + + @Nonnull + @AzureOperation(name = "redis.list.subscription|selected", type = AzureOperation.Type.SERVICE) + public List list() { + return getSubscriptions().stream() + .map(subscription -> RedisManagerFactory.create(subscription.getId())) + .flatMap(manager -> manager.redisCaches().list().stream()) + .map(redis -> new RedisCache(redis.manager(), redis)) + .collect(Collectors.toList()); + } + + @AzureOperation(name = "redis.check_name", params = "name", type = AzureOperation.Type.SERVICE) + public CheckNameAvailabilityResultEntity checkNameAvailability(String subscriptionId, String name) { + final RedisManager redisManager = RedisManagerFactory.create(subscriptionId); + RedisClient redis = redisManager.redisCaches().manager().serviceClient().getRedis(); + try { + redis.checkNameAvailability(new CheckNameAvailabilityParameters().withName(name).withType("Microsoft.Cache/redis")); + return new CheckNameAvailabilityResultEntity(true, null); + } catch (ManagementException ex) { + ManagementError value = ex.getValue(); + if (value != null && "NameNotAvailable".equals(value.getCode())) { + return new CheckNameAvailabilityResultEntity(false, String.format("The name '%s' for Redis Cache is not available", name), value.getMessage()); + } + throw ex; + } + } + + public Creator create(RedisConfig config) { + return new Creator(config); + } + + @AllArgsConstructor(access = AccessLevel.PRIVATE) + public class Creator implements ICommittable, AzureOperationEvent.Source { + + private RedisConfig config; + + @Override + @AzureOperation(name = "redis.create", params = {"this.config.getName()"}, type = AzureOperation.Type.SERVICE) + public RedisCache commit() { + final com.azure.resourcemanager.redis.models.RedisCache.DefinitionStages.WithSku toCreate = + RedisManagerFactory.create(config.getSubscription().getId()).redisCaches().define(config.getName()) + .withRegion(config.getRegion().getName()) + .withExistingResourceGroup(config.getResourceGroup().getName()); + com.azure.resourcemanager.redis.models.RedisCache.DefinitionStages.WithCreate withCreate = null; + if (config.getPricingTier().isBasic()) { + withCreate = toCreate.withBasicSku(config.getPricingTier().getSize()); + } else if (config.getPricingTier().isStandard()) { + withCreate = toCreate.withStandardSku(config.getPricingTier().getSize()); + } else if (config.getPricingTier().isPremium()) { + withCreate = toCreate.withPremiumSku(config.getPricingTier().getSize()); + } + if (config.isEnableNonSslPort()) { + withCreate = withCreate.withNonSslPort(); + } + final com.azure.resourcemanager.redis.models.RedisCache redisCache = withCreate.create(); + return new RedisCache(redisCache.manager(), redisCache); + } + + public AzureOperationEvent.Source getEventSource() { + return new AzureOperationEvent.Source() {}; + } + } + + @Override + public String name() { + return "Redis Caches"; + } +} diff --git a/azure-toolkit-libs/azure-toolkit-redis-lib/src/main/java/com/microsoft/azure/toolkit/redis/PricingTier.java b/azure-toolkit-libs/azure-toolkit-redis-lib/src/main/java/com/microsoft/azure/toolkit/redis/PricingTier.java new file mode 100644 index 0000000000..6333cce6e4 --- /dev/null +++ b/azure-toolkit-libs/azure-toolkit-redis-lib/src/main/java/com/microsoft/azure/toolkit/redis/PricingTier.java @@ -0,0 +1,83 @@ +/* + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + */ + +package com.microsoft.azure.toolkit.redis; + +import com.google.common.collect.ImmutableList; +import lombok.AccessLevel; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import org.apache.commons.lang3.StringUtils; + +import java.util.List; + +@Getter +@Setter +@NoArgsConstructor +@AllArgsConstructor(access = AccessLevel.PRIVATE) +public class PricingTier { + private static final String BASIC = "Basic"; + private static final String STANDARD = "Standard"; + private static final String PREMIUM = "Premium"; + private String family; + private String capacity; + private String memory; + private boolean replication; + + public static final PricingTier BASIC_C0 = new PricingTier(BASIC, "C0", "250MB", false); + public static final PricingTier BASIC_C1 = new PricingTier(BASIC, "C1", "1GB", false); + public static final PricingTier BASIC_C2 = new PricingTier(BASIC, "C2", "2.5GB", false); + public static final PricingTier BASIC_C3 = new PricingTier(BASIC, "C3", "6GB", false); + public static final PricingTier BASIC_C4 = new PricingTier(BASIC, "C4", "13GB", false); + public static final PricingTier BASIC_C5 = new PricingTier(BASIC, "C5", "26GB", false); + public static final PricingTier BASIC_C6 = new PricingTier(BASIC, "C6", "53GB", false); + + public static final PricingTier STANDARD_C0 = new PricingTier(STANDARD, "C0", "250MB", true); + public static final PricingTier STANDARD_C1 = new PricingTier(STANDARD, "C1", "1GB", true); + public static final PricingTier STANDARD_C2 = new PricingTier(STANDARD, "C2", "2.5GB", true); + public static final PricingTier STANDARD_C3 = new PricingTier(STANDARD, "C3", "6GB", true); + public static final PricingTier STANDARD_C4 = new PricingTier(STANDARD, "C4", "13GB", true); + public static final PricingTier STANDARD_C5 = new PricingTier(STANDARD, "C5", "26GB", true); + public static final PricingTier STANDARD_C6 = new PricingTier(STANDARD, "C6", "53GB", true); + + public static final PricingTier PREMIUM_C1 = new PricingTier(PREMIUM, "C1", "6GB", true); + public static final PricingTier PREMIUM_C2 = new PricingTier(PREMIUM, "C2", "13GB", true); + public static final PricingTier PREMIUM_C3 = new PricingTier(PREMIUM, "C3", "26GB", true); + public static final PricingTier PREMIUM_C4 = new PricingTier(PREMIUM, "C4", "53GB", true); + public static final PricingTier PREMIUM_C5 = new PricingTier(PREMIUM, "C5", "120GB", true); + + public boolean isBasic() { + return StringUtils.equals(family, BASIC); + } + + public boolean isStandard() { + return StringUtils.equals(family, STANDARD); + } + + public boolean isPremium() { + return StringUtils.equals(family, PREMIUM); + } + + public int getSize() { + return Integer.getInteger(this.capacity.substring(1)); + } + + private static final List values = new ImmutableList.Builder().add( + BASIC_C0, BASIC_C1, BASIC_C2, BASIC_C3, BASIC_C4, BASIC_C5, BASIC_C6, + STANDARD_C0, STANDARD_C1, STANDARD_C2, STANDARD_C3, STANDARD_C4, STANDARD_C5, STANDARD_C6, + PREMIUM_C1, PREMIUM_C2, PREMIUM_C3, PREMIUM_C4 + ).build(); + + public static List values() { + return values; + } + + @Override + public String toString() { + return String.format("%s %s (%s)", family, capacity, replication ? (memory + ", Replication") : memory); + } +} diff --git a/azure-toolkit-libs/azure-toolkit-redis-lib/src/main/java/com/microsoft/azure/toolkit/redis/RedisCache.java b/azure-toolkit-libs/azure-toolkit-redis-lib/src/main/java/com/microsoft/azure/toolkit/redis/RedisCache.java new file mode 100644 index 0000000000..8744697d0a --- /dev/null +++ b/azure-toolkit-libs/azure-toolkit-redis-lib/src/main/java/com/microsoft/azure/toolkit/redis/RedisCache.java @@ -0,0 +1,50 @@ +/* + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + */ + +package com.microsoft.azure.toolkit.redis; + +import com.azure.core.management.exception.ManagementException; +import com.azure.resourcemanager.redis.RedisManager; +import com.microsoft.azure.toolkit.lib.common.entity.AbstractAzureResource; +import com.microsoft.azure.toolkit.lib.common.entity.IAzureResource; +import com.microsoft.azure.toolkit.lib.common.event.AzureOperationEvent; +import com.microsoft.azure.toolkit.lib.common.operation.AzureOperation; +import org.apache.http.HttpStatus; +import org.jetbrains.annotations.Nullable; + +import javax.annotation.Nonnull; + +public class RedisCache extends AbstractAzureResource + implements AzureOperationEvent.Source, IAzureResource { + + @Nonnull + private final RedisManager manager; + + public RedisCache(RedisManager manager, com.azure.resourcemanager.redis.models.RedisCache redis) { + super(new RedisCacheEntity(redis)); + this.manager = manager; + } + + @AzureOperation(name = "redis.delete", params = {"this.name()"}, type = AzureOperation.Type.SERVICE) + public void delete() { + manager.redisCaches().deleteById(this.id()); + refresh(); + } + + @Nullable + @Override + protected com.azure.resourcemanager.redis.models.RedisCache loadRemote() { + try { + this.entity().setRemote(manager.redisCaches().getById(this.entity.getId())); + } catch (ManagementException ex) { + if (HttpStatus.SC_NOT_FOUND == ex.getResponse().getStatusCode()) { + return null; + } else { + throw ex; + } + } + return entity.getRemote(); + } +} diff --git a/azure-toolkit-libs/azure-toolkit-redis-lib/src/main/java/com/microsoft/azure/toolkit/redis/RedisCacheEntity.java b/azure-toolkit-libs/azure-toolkit-redis-lib/src/main/java/com/microsoft/azure/toolkit/redis/RedisCacheEntity.java new file mode 100644 index 0000000000..18ccf908ca --- /dev/null +++ b/azure-toolkit-libs/azure-toolkit-redis-lib/src/main/java/com/microsoft/azure/toolkit/redis/RedisCacheEntity.java @@ -0,0 +1,50 @@ +/* + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + */ + +package com.microsoft.azure.toolkit.redis; + +import com.azure.resourcemanager.resources.fluentcore.arm.ResourceId; +import com.microsoft.azure.toolkit.lib.common.entity.AbstractAzureResource; +import com.microsoft.azure.toolkit.lib.common.model.Region; + +import javax.annotation.Nonnull; +import java.util.Optional; + +public class RedisCacheEntity extends AbstractAzureResource.RemoteAwareResourceEntity { + + @Nonnull + private final ResourceId resourceId; + + public RedisCacheEntity(com.azure.resourcemanager.redis.models.RedisCache redis) { + this.resourceId = ResourceId.fromString(redis.id()); + this.remote = redis; + } + + @Override + public String getSubscriptionId() { + return resourceId.subscriptionId(); + } + + public String getId() { + return resourceId.id(); + } + + @Override + public String getName() { + return resourceId.name(); + } + + public String getResourceGroupName() { + return resourceId.resourceGroupName(); + } + + public Region getRegion() { + return remoteOptional().map(remote -> Region.fromName(remote.regionName())).orElse(null); + } + + private Optional remoteOptional() { + return Optional.ofNullable(this.remote); + } +} diff --git a/azure-toolkit-libs/azure-toolkit-redis-lib/src/main/java/com/microsoft/azure/toolkit/redis/RedisConfig.java b/azure-toolkit-libs/azure-toolkit-redis-lib/src/main/java/com/microsoft/azure/toolkit/redis/RedisConfig.java new file mode 100644 index 0000000000..796a0a2fab --- /dev/null +++ b/azure-toolkit-libs/azure-toolkit-redis-lib/src/main/java/com/microsoft/azure/toolkit/redis/RedisConfig.java @@ -0,0 +1,27 @@ +/* + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + */ + +package com.microsoft.azure.toolkit.redis; + + +import com.microsoft.azure.toolkit.lib.common.model.Region; +import com.microsoft.azure.toolkit.lib.common.model.ResourceGroup; +import com.microsoft.azure.toolkit.lib.common.model.Subscription; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@NoArgsConstructor +@AllArgsConstructor +public class RedisConfig { + private String name; + private String id; + private ResourceGroup resourceGroup; + private Subscription subscription; + private Region region; + private PricingTier pricingTier; + private boolean enableNonSslPort; +} diff --git a/azure-toolkit-libs/azure-toolkit-redis-lib/src/main/java/com/microsoft/azure/toolkit/redis/RedisManagerFactory.java b/azure-toolkit-libs/azure-toolkit-redis-lib/src/main/java/com/microsoft/azure/toolkit/redis/RedisManagerFactory.java new file mode 100644 index 0000000000..df62013548 --- /dev/null +++ b/azure-toolkit-libs/azure-toolkit-redis-lib/src/main/java/com/microsoft/azure/toolkit/redis/RedisManagerFactory.java @@ -0,0 +1,45 @@ +/* + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + */ + +package com.microsoft.azure.toolkit.redis; + +import com.azure.core.http.policy.HttpLogDetailLevel; +import com.azure.core.http.policy.HttpPipelinePolicy; +import com.azure.core.management.profile.AzureProfile; +import com.azure.resourcemanager.redis.RedisManager; +import com.microsoft.azure.toolkit.lib.Azure; +import com.microsoft.azure.toolkit.lib.AzureConfiguration; +import com.microsoft.azure.toolkit.lib.auth.Account; +import com.microsoft.azure.toolkit.lib.auth.AzureAccount; +import com.microsoft.azure.toolkit.lib.common.cache.Cacheable; + +import java.util.Optional; + +public final class RedisManagerFactory { + + private RedisManagerFactory() { + } + + @Cacheable(cacheName = "RedisManager", key = "$subscriptionId") + public static RedisManager create(String subscriptionId) { + final Account account = Azure.az(AzureAccount.class).account(); + final AzureConfiguration config = Azure.az().config(); + final String userAgent = config.getUserAgent(); + final HttpLogDetailLevel logLevel = Optional.ofNullable(config.getLogLevel()).map(HttpLogDetailLevel::valueOf).orElse(HttpLogDetailLevel.NONE); + final AzureProfile azureProfile = new AzureProfile(null, subscriptionId, account.getEnvironment()); + return RedisManager.configure() + .withLogLevel(logLevel) + .withPolicy(getUserAgentPolicy(userAgent)) + .authenticate(account.getTokenCredential(subscriptionId), azureProfile); + } + + private static HttpPipelinePolicy getUserAgentPolicy(String userAgent) { + return (httpPipelineCallContext, httpPipelineNextPolicy) -> { + final String previousUserAgent = httpPipelineCallContext.getHttpRequest().getHeaders().getValue("User-Agent"); + httpPipelineCallContext.getHttpRequest().setHeader("User-Agent", String.format("%s %s", userAgent, previousUserAgent)); + return httpPipelineNextPolicy.process(); + }; + } +} diff --git a/azure-toolkit-libs/azure-toolkit-redis-lib/src/main/resources/META-INF/services/com.microsoft.azure.toolkit.lib.AzureService b/azure-toolkit-libs/azure-toolkit-redis-lib/src/main/resources/META-INF/services/com.microsoft.azure.toolkit.lib.AzureService new file mode 100644 index 0000000000..eefbfb0023 --- /dev/null +++ b/azure-toolkit-libs/azure-toolkit-redis-lib/src/main/resources/META-INF/services/com.microsoft.azure.toolkit.lib.AzureService @@ -0,0 +1 @@ +com.microsoft.azure.toolkit.redis.AzureRedis diff --git a/azure-toolkit-libs/azure-toolkit-redis-lib/src/main/resources/com/microsoft/azure/toolkit/operation/title/base/redis.properties b/azure-toolkit-libs/azure-toolkit-redis-lib/src/main/resources/com/microsoft/azure/toolkit/operation/title/base/redis.properties new file mode 100644 index 0000000000..cbb1bffee2 --- /dev/null +++ b/azure-toolkit-libs/azure-toolkit-redis-lib/src/main/resources/com/microsoft/azure/toolkit/operation/title/base/redis.properties @@ -0,0 +1,4 @@ +redis.create=create redis cache({0}) +redis.delete=delete redis cache({0}) +redis.list.subscription|selected=list Redis Caches of selected subscriptions +redis.check_name=check name availability for redis cahe({0}) \ No newline at end of file diff --git a/azure-toolkit-libs/pom.xml b/azure-toolkit-libs/pom.xml index 1e51dfe604..0dcda587ff 100644 --- a/azure-toolkit-libs/pom.xml +++ b/azure-toolkit-libs/pom.xml @@ -45,6 +45,7 @@ azure-toolkit-applicationinsights-lib azure-toolkit-storage-lib azure-toolkit-database-lib + azure-toolkit-redis-lib @@ -140,6 +141,7 @@ 2.0.9 1.0.0 1.0.57 + 2.7.0 @@ -535,6 +537,11 @@ azure-resourcemanager-mysql ${azure-resourcemanager-mysql.version} + + com.azure.resourcemanager + azure-resourcemanager-redis + ${azure-resourcemanager-redis.version} + com.azure.resourcemanager azure-resourcemanager-appplatform From c37a93fda8c3d2344e011bb669739945eef42ba2 Mon Sep 17 00:00:00 2001 From: andxu Date: Fri, 3 Sep 2021 16:13:59 +0800 Subject: [PATCH 026/126] provide get by id api and retrieve more properties from redis cache. --- .../azure/toolkit/redis/AzureRedis.java | 8 +++++ .../azure/toolkit/redis/RedisCacheEntity.java | 30 +++++++++++++++++++ .../operation/title/base/redis.properties | 3 +- 3 files changed, 40 insertions(+), 1 deletion(-) diff --git a/azure-toolkit-libs/azure-toolkit-redis-lib/src/main/java/com/microsoft/azure/toolkit/redis/AzureRedis.java b/azure-toolkit-libs/azure-toolkit-redis-lib/src/main/java/com/microsoft/azure/toolkit/redis/AzureRedis.java index ac3eb8a667..1fe6d86e48 100644 --- a/azure-toolkit-libs/azure-toolkit-redis-lib/src/main/java/com/microsoft/azure/toolkit/redis/AzureRedis.java +++ b/azure-toolkit-libs/azure-toolkit-redis-lib/src/main/java/com/microsoft/azure/toolkit/redis/AzureRedis.java @@ -10,6 +10,7 @@ import com.azure.resourcemanager.redis.RedisManager; import com.azure.resourcemanager.redis.fluent.RedisClient; import com.azure.resourcemanager.redis.models.CheckNameAvailabilityParameters; +import com.azure.resourcemanager.resources.fluentcore.arm.ResourceId; import com.microsoft.azure.toolkit.lib.AzureService; import com.microsoft.azure.toolkit.lib.SubscriptionScoped; import com.microsoft.azure.toolkit.lib.common.entity.CheckNameAvailabilityResultEntity; @@ -43,6 +44,13 @@ public List list() { .collect(Collectors.toList()); } + @AzureOperation(name = "redis.get.id", params = {"id"}, type = AzureOperation.Type.SERVICE) + public RedisCache get(@Nonnull String id) { + com.azure.resourcemanager.redis.models.RedisCache redisCache = + RedisManagerFactory.create(ResourceId.fromString(id).subscriptionId()).redisCaches().getById(id); + return new RedisCache(redisCache.manager(), redisCache); + } + @AzureOperation(name = "redis.check_name", params = "name", type = AzureOperation.Type.SERVICE) public CheckNameAvailabilityResultEntity checkNameAvailability(String subscriptionId, String name) { final RedisManager redisManager = RedisManagerFactory.create(subscriptionId); diff --git a/azure-toolkit-libs/azure-toolkit-redis-lib/src/main/java/com/microsoft/azure/toolkit/redis/RedisCacheEntity.java b/azure-toolkit-libs/azure-toolkit-redis-lib/src/main/java/com/microsoft/azure/toolkit/redis/RedisCacheEntity.java index 18ccf908ca..8da6a6c6cb 100644 --- a/azure-toolkit-libs/azure-toolkit-redis-lib/src/main/java/com/microsoft/azure/toolkit/redis/RedisCacheEntity.java +++ b/azure-toolkit-libs/azure-toolkit-redis-lib/src/main/java/com/microsoft/azure/toolkit/redis/RedisCacheEntity.java @@ -5,7 +5,9 @@ package com.microsoft.azure.toolkit.redis; +import com.azure.resourcemanager.redis.models.RedisCache; import com.azure.resourcemanager.resources.fluentcore.arm.ResourceId; +import com.azure.resourcemanager.resources.fluentcore.arm.models.Resource; import com.microsoft.azure.toolkit.lib.common.entity.AbstractAzureResource; import com.microsoft.azure.toolkit.lib.common.model.Region; @@ -44,6 +46,34 @@ public Region getRegion() { return remoteOptional().map(remote -> Region.fromName(remote.regionName())).orElse(null); } + public String getType() { + return remoteOptional().map(Resource::type).orElse(null); + } + + public int getSSLPort() { + return remoteOptional().map(RedisCache::sslPort).orElse(-1); + } + + public boolean getNonSslPortEnabled() { + return remoteOptional().map(RedisCache::nonSslPort).orElse(false); + } + + public String getRedisVersion() { + return remoteOptional().map(RedisCache::redisVersion).orElse(null); + } + + public String getPrimaryKey() { + return remoteOptional().map(remote -> remote.keys().primaryKey()).orElse(null); + } + + public String getSecondaryKey() { + return remoteOptional().map(remote -> remote.keys().secondaryKey()).orElse(null); + } + + public String getHostName() { + return remoteOptional().map(RedisCache::hostname).orElse(null); + } + private Optional remoteOptional() { return Optional.ofNullable(this.remote); } diff --git a/azure-toolkit-libs/azure-toolkit-redis-lib/src/main/resources/com/microsoft/azure/toolkit/operation/title/base/redis.properties b/azure-toolkit-libs/azure-toolkit-redis-lib/src/main/resources/com/microsoft/azure/toolkit/operation/title/base/redis.properties index cbb1bffee2..72d04c000f 100644 --- a/azure-toolkit-libs/azure-toolkit-redis-lib/src/main/resources/com/microsoft/azure/toolkit/operation/title/base/redis.properties +++ b/azure-toolkit-libs/azure-toolkit-redis-lib/src/main/resources/com/microsoft/azure/toolkit/operation/title/base/redis.properties @@ -1,4 +1,5 @@ redis.create=create redis cache({0}) redis.delete=delete redis cache({0}) redis.list.subscription|selected=list Redis Caches of selected subscriptions -redis.check_name=check name availability for redis cahe({0}) \ No newline at end of file +redis.check_name=check name availability for redis cahe({0}) +redis.get.id=get Redis cache({0}) \ No newline at end of file From fcc75a617b4ceeacba4e79e8561df5670e05183d Mon Sep 17 00:00:00 2001 From: andxu Date: Mon, 6 Sep 2021 11:21:33 +0800 Subject: [PATCH 027/126] Reflect new lib conventions --- .../java/com/microsoft/azure/toolkit/redis/AzureRedis.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/azure-toolkit-libs/azure-toolkit-redis-lib/src/main/java/com/microsoft/azure/toolkit/redis/AzureRedis.java b/azure-toolkit-libs/azure-toolkit-redis-lib/src/main/java/com/microsoft/azure/toolkit/redis/AzureRedis.java index 1fe6d86e48..3d3061fbf4 100644 --- a/azure-toolkit-libs/azure-toolkit-redis-lib/src/main/java/com/microsoft/azure/toolkit/redis/AzureRedis.java +++ b/azure-toolkit-libs/azure-toolkit-redis-lib/src/main/java/com/microsoft/azure/toolkit/redis/AzureRedis.java @@ -67,12 +67,12 @@ public CheckNameAvailabilityResultEntity checkNameAvailability(String subscripti } } - public Creator create(RedisConfig config) { - return new Creator(config); + public RedisCache create(RedisConfig config) { + return new Creator(config).commit(); } @AllArgsConstructor(access = AccessLevel.PRIVATE) - public class Creator implements ICommittable, AzureOperationEvent.Source { + private class Creator implements ICommittable, AzureOperationEvent.Source { private RedisConfig config; From 90edc05523aa408e75e5a23443aa2eeb4f2e7df1 Mon Sep 17 00:00:00 2001 From: andxu Date: Mon, 6 Sep 2021 12:12:30 +0800 Subject: [PATCH 028/126] Fix a bug of Integer.getInteger doesn't parse the integer --- .../java/com/microsoft/azure/toolkit/redis/PricingTier.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/azure-toolkit-libs/azure-toolkit-redis-lib/src/main/java/com/microsoft/azure/toolkit/redis/PricingTier.java b/azure-toolkit-libs/azure-toolkit-redis-lib/src/main/java/com/microsoft/azure/toolkit/redis/PricingTier.java index 6333cce6e4..20c156e3f7 100644 --- a/azure-toolkit-libs/azure-toolkit-redis-lib/src/main/java/com/microsoft/azure/toolkit/redis/PricingTier.java +++ b/azure-toolkit-libs/azure-toolkit-redis-lib/src/main/java/com/microsoft/azure/toolkit/redis/PricingTier.java @@ -63,7 +63,7 @@ public boolean isPremium() { } public int getSize() { - return Integer.getInteger(this.capacity.substring(1)); + return Integer.parseInt(this.capacity.substring(1)); } private static final List values = new ImmutableList.Builder().add( From df825df920abc981dfb206921382dc0db94143fe Mon Sep 17 00:00:00 2001 From: andxu Date: Mon, 6 Sep 2021 12:34:39 +0800 Subject: [PATCH 029/126] add redis module to parent pom --- azure-toolkit-libs/pom.xml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/azure-toolkit-libs/pom.xml b/azure-toolkit-libs/pom.xml index 0dcda587ff..f36e1cce39 100644 --- a/azure-toolkit-libs/pom.xml +++ b/azure-toolkit-libs/pom.xml @@ -208,6 +208,11 @@ azure-toolkit-storage-lib ${azure.toolkit-lib.version} + + com.microsoft.azure + azure-toolkit-redis-lib + ${azure.toolkit-lib.version} + com.microsoft.azure From 52fb01925a1d1dd69a0cf8165576dcbe1b773245 Mon Sep 17 00:00:00 2001 From: Mingliang Wang Date: Mon, 6 Sep 2021 15:37:51 +0800 Subject: [PATCH 030/126] move action framework to toolkit-lib --- .../toolkit/lib/common/action/Action.java | 144 ++++++++++++++++++ .../lib/common/action/ActionGroup.java | 57 +++++++ .../toolkit/lib/common/action/ActionView.java | 76 +++++++++ .../lib/common/action/AzureActionManager.java | 51 +++++++ .../azure/toolkit/lib/common/view/IView.java | 75 +++++++++ 5 files changed, 403 insertions(+) create mode 100644 azure-toolkit-libs/azure-toolkit-common-lib/src/main/java/com/microsoft/azure/toolkit/lib/common/action/Action.java create mode 100644 azure-toolkit-libs/azure-toolkit-common-lib/src/main/java/com/microsoft/azure/toolkit/lib/common/action/ActionGroup.java create mode 100644 azure-toolkit-libs/azure-toolkit-common-lib/src/main/java/com/microsoft/azure/toolkit/lib/common/action/ActionView.java create mode 100644 azure-toolkit-libs/azure-toolkit-common-lib/src/main/java/com/microsoft/azure/toolkit/lib/common/action/AzureActionManager.java create mode 100644 azure-toolkit-libs/azure-toolkit-common-lib/src/main/java/com/microsoft/azure/toolkit/lib/common/view/IView.java diff --git a/azure-toolkit-libs/azure-toolkit-common-lib/src/main/java/com/microsoft/azure/toolkit/lib/common/action/Action.java b/azure-toolkit-libs/azure-toolkit-common-lib/src/main/java/com/microsoft/azure/toolkit/lib/common/action/Action.java new file mode 100644 index 0000000000..9b012fb119 --- /dev/null +++ b/azure-toolkit-libs/azure-toolkit-common-lib/src/main/java/com/microsoft/azure/toolkit/lib/common/action/Action.java @@ -0,0 +1,144 @@ +/* + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + */ + +package com.microsoft.azure.toolkit.lib.common.action; + +import com.microsoft.azure.toolkit.lib.common.bundle.AzureString; +import com.microsoft.azure.toolkit.lib.common.entity.IAzureResource; +import com.microsoft.azure.toolkit.lib.common.operation.AzureOperation; +import com.microsoft.azure.toolkit.lib.common.operation.IAzureOperation; +import com.microsoft.azure.toolkit.lib.common.task.AzureTask; +import com.microsoft.azure.toolkit.lib.common.task.AzureTaskManager; +import com.microsoft.azure.toolkit.lib.common.telemetry.AzureTelemetry; +import com.microsoft.azure.toolkit.lib.common.view.IView; +import lombok.Getter; +import lombok.experimental.Accessors; +import org.apache.commons.lang3.StringUtils; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.util.AbstractMap; +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; +import java.util.Optional; +import java.util.function.BiConsumer; +import java.util.function.BiPredicate; +import java.util.function.Consumer; +import java.util.function.Predicate; + +@Accessors(chain = true, fluent = true) +public class Action { + public static final String SOURCE = "ACTION_SOURCE"; + @Nonnull + private List, BiConsumer>> handlers = new ArrayList<>(); + @Nullable + @Getter + private ActionView.Builder view; + + public Action(@Nullable ActionView.Builder view) { + this.view = view; + } + + public Action(@Nonnull Consumer handler) { + this.registerHandler((d, e) -> true, (d, e) -> handler.accept(d)); + } + + public Action(@Nonnull BiConsumer handler) { + this.registerHandler((d, e) -> true, handler); + } + + public Action(@Nonnull Consumer handler, @Nullable ActionView.Builder view) { + this.view = view; + this.registerHandler((d, e) -> true, (d, e) -> handler.accept(d)); + } + + public Action(@Nonnull BiConsumer handler, @Nullable ActionView.Builder view) { + this.view = view; + this.registerHandler((d, e) -> true, handler); + } + + private Action(@Nonnull List, BiConsumer>> handlers, @Nullable ActionView.Builder view) { + this.view = view; + this.handlers = handlers; + } + + @Nullable + public IView.Label view(D source) { + return Objects.nonNull(this.view) ? this.view.toActionView(source) : null; + } + + @SuppressWarnings("unchecked") + public void handle(D source, Object e) { + for (int i = this.handlers.size() - 1; i >= 0; i--) { + final AbstractMap.SimpleEntry, BiConsumer> p = this.handlers.get(i); + final BiPredicate condition = (BiPredicate) p.getKey(); + final BiConsumer handler = (BiConsumer) p.getValue(); + if (condition.test(source, e)) { + final AzureString title = Optional.ofNullable(this.view).map(b -> b.title).map(t -> t.apply(source)) + .orElse(AzureString.fromString(IAzureOperation.UNKNOWN_NAME)); + final AzureTask task = new AzureTask<>(title, () -> handle(source, e, handler)); + task.setType(AzureOperation.Type.ACTION.name()); + AzureTaskManager.getInstance().runInBackground(task); + return; + } + } + } + + protected void handle(D source, Object e, BiConsumer handler) { + if (source instanceof IAzureResource) { + AzureTelemetry.getActionContext().setProperty("subscriptionId", ((IAzureResource) source).subscriptionId()); + AzureTelemetry.getActionContext().setProperty("resourceType", source.getClass().getSimpleName()); + } + handler.accept(source, e); + } + + public void handle(D source) { + this.handle(source, null); + } + + public void registerHandler(@Nonnull Predicate condition, @Nonnull Consumer handler) { + this.handlers.add(new AbstractMap.SimpleEntry<>((d, e) -> condition.test(d), (d, e) -> handler.accept(d))); + } + + public void registerHandler(@Nonnull BiPredicate condition, @Nonnull BiConsumer handler) { + this.handlers.add(new AbstractMap.SimpleEntry<>(condition, handler)); + } + + @Getter + @Accessors(chain = true, fluent = true) + public static class Delegate extends Action { + @Nonnull + private final String id; + @Nonnull + private final Action action; + + public Delegate(@Nonnull Action action, @Nonnull String id) { + super(action.handlers, action.view); + this.id = id; + this.action = action; + } + } + + public static class Id { + @Nonnull + private final String id; + + private Id(@Nonnull String id) { + this.id = id; + } + + public static Id of(@Nonnull String id) { + assert StringUtils.isNotBlank(id) : "action id can not be blank"; + return new Id<>(id); + } + + @Nonnull + public String getId() { + return id; + } + } +} + diff --git a/azure-toolkit-libs/azure-toolkit-common-lib/src/main/java/com/microsoft/azure/toolkit/lib/common/action/ActionGroup.java b/azure-toolkit-libs/azure-toolkit-common-lib/src/main/java/com/microsoft/azure/toolkit/lib/common/action/ActionGroup.java new file mode 100644 index 0000000000..5c6c39957e --- /dev/null +++ b/azure-toolkit-libs/azure-toolkit-common-lib/src/main/java/com/microsoft/azure/toolkit/lib/common/action/ActionGroup.java @@ -0,0 +1,57 @@ +/* + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + */ + +package com.microsoft.azure.toolkit.lib.common.action; + +import com.microsoft.azure.toolkit.lib.common.view.IView; +import lombok.Getter; +import lombok.experimental.Accessors; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.util.Arrays; +import java.util.List; + +@Getter +@Accessors(chain = true, fluent = true) +public class ActionGroup { + @Nullable + private IView.Label view; + private final List actions; + + public ActionGroup(@Nonnull List actions) { + this.actions = actions; + } + + public ActionGroup(@Nonnull Object... actions) { + this.actions = Arrays.asList(actions); + } + + public ActionGroup(@Nonnull List actions, @Nullable IView.Label view) { + this.view = view; + this.actions = actions; + } + + @Getter + @Accessors(chain = true, fluent = true) + public static class Proxy extends ActionGroup { + @Nullable + private final String id; + @Nonnull + private final ActionGroup group; + + public Proxy(@Nonnull ActionGroup group) { + super(group.actions, group.view); + this.id = null; + this.group = group; + } + + public Proxy(@Nonnull ActionGroup group, @Nonnull String id) { + super(group.actions, group.view); + this.id = id; + this.group = group; + } + } +} diff --git a/azure-toolkit-libs/azure-toolkit-common-lib/src/main/java/com/microsoft/azure/toolkit/lib/common/action/ActionView.java b/azure-toolkit-libs/azure-toolkit-common-lib/src/main/java/com/microsoft/azure/toolkit/lib/common/action/ActionView.java new file mode 100644 index 0000000000..d53f19f252 --- /dev/null +++ b/azure-toolkit-libs/azure-toolkit-common-lib/src/main/java/com/microsoft/azure/toolkit/lib/common/action/ActionView.java @@ -0,0 +1,76 @@ +/* + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + */ + +package com.microsoft.azure.toolkit.lib.common.action; + +import com.microsoft.azure.toolkit.lib.common.bundle.AzureString; +import com.microsoft.azure.toolkit.lib.common.view.IView; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.RequiredArgsConstructor; +import lombok.Setter; +import lombok.experimental.Accessors; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.util.Optional; +import java.util.function.Function; + +@Getter +@RequiredArgsConstructor +@AllArgsConstructor +public class ActionView implements IView.Label { + + @Nonnull + private final String label; + private final String iconPath; + @Nullable + private AzureString title; + private final boolean enabled; + + @Override + public String getDescription() { + return Optional.ofNullable(this.title).map(AzureString::toString).orElse(null); + } + + @Override + public void dispose() { + } + + @RequiredArgsConstructor + @Setter + @Getter + @Accessors(chain = true, fluent = true) + public static class Builder { + @Nonnull + protected final Function label; + @Nullable + protected Function iconPath; + @Nullable + protected Function title; + @Nullable + protected Function enabled = s -> true; + + public Builder(String label) { + this(s -> label); + } + + public Builder(String label, String iconPath) { + this(s -> label); + this.iconPath = (s) -> iconPath; + } + + public ActionView toActionView(Object s) { + try { + final Boolean e = Optional.ofNullable(this.enabled).map(p -> p.apply(s)).orElse(true); + final String i = Optional.ofNullable(this.iconPath).map(p -> p.apply(s)).orElse(null); + final AzureString t = Optional.ofNullable(this.title).map(p -> p.apply(s)).orElse(null); + return new ActionView(this.label.apply(s), i, t, e); + } catch (final Exception e) { + return new ActionView("", "", false); + } + } + } +} diff --git a/azure-toolkit-libs/azure-toolkit-common-lib/src/main/java/com/microsoft/azure/toolkit/lib/common/action/AzureActionManager.java b/azure-toolkit-libs/azure-toolkit-common-lib/src/main/java/com/microsoft/azure/toolkit/lib/common/action/AzureActionManager.java new file mode 100644 index 0000000000..9dda6eaee0 --- /dev/null +++ b/azure-toolkit-libs/azure-toolkit-common-lib/src/main/java/com/microsoft/azure/toolkit/lib/common/action/AzureActionManager.java @@ -0,0 +1,51 @@ +/* + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + */ + +package com.microsoft.azure.toolkit.lib.common.action; + +import com.microsoft.azure.toolkit.lib.common.messager.AzureMessager; +import lombok.Getter; + +import javax.annotation.Nonnull; +import java.util.function.BiConsumer; +import java.util.function.BiPredicate; +import java.util.function.Consumer; +import java.util.function.Predicate; + +public abstract class AzureActionManager { + + @Getter + private static AzureActionManager instance; + + protected static void register(AzureActionManager manager) { + if (instance != null) { + AzureMessager.getDefaultMessager().warning("ActionManager is already registered", null); + return; + } + instance = manager; + } + + public abstract void registerAction(Action.Id id, Action action); + + public void registerAction(Action.Id id, Consumer action) { + this.registerAction(id, new Action<>(action)); + } + + public abstract Action getAction(Action.Id id); + + public abstract void registerGroup(String id, ActionGroup group); + + public abstract ActionGroup getGroup(String id); + + public void registerHandler(@Nonnull Action.Id id, @Nonnull Predicate condition, @Nonnull Consumer handler) { + final Action action = this.getAction(id); + action.registerHandler(condition, handler); + } + + public void registerHandler(@Nonnull Action.Id id, @Nonnull BiPredicate condition, @Nonnull BiConsumer handler) { + final Action action = this.getAction(id); + action.registerHandler(condition, handler); + } +} diff --git a/azure-toolkit-libs/azure-toolkit-common-lib/src/main/java/com/microsoft/azure/toolkit/lib/common/view/IView.java b/azure-toolkit-libs/azure-toolkit-common-lib/src/main/java/com/microsoft/azure/toolkit/lib/common/view/IView.java new file mode 100644 index 0000000000..eb52946bf1 --- /dev/null +++ b/azure-toolkit-libs/azure-toolkit-common-lib/src/main/java/com/microsoft/azure/toolkit/lib/common/view/IView.java @@ -0,0 +1,75 @@ +/* + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + */ + +package com.microsoft.azure.toolkit.lib.common.view; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.util.Optional; + +public interface IView { + + void dispose(); + + interface Dynamic extends IView { + + default void updateView() { + Optional.ofNullable(this.getUpdater()).ifPresent(Updater::updateView); + } + + default void updateChildren() { + Optional.ofNullable(this.getUpdater()).ifPresent(Updater::updateChildren); + } + + void setUpdater(Updater updater); + + @Nullable + Updater getUpdater(); + + interface Updater { + default void updateView() { + } + + default void updateChildren() { + } + } + } + + interface Label extends IView { + String getLabel(); + + String getIconPath(); + + String getDescription(); + + default boolean isEnabled() { + return true; + } + + @Getter + @RequiredArgsConstructor + @AllArgsConstructor + class Static implements Label { + @Nonnull + protected final String label; + @Nullable + protected String iconPath; + @Nullable + protected String description; + + public Static(String title, String iconPath) { + this(title, iconPath, null); + } + + @Override + public void dispose() { + } + } + } +} From 9d7307e680265c0073aba28b24847e0bb51a7070 Mon Sep 17 00:00:00 2001 From: Mingliang Wang Date: Mon, 6 Sep 2021 17:08:04 +0800 Subject: [PATCH 031/126] remove IAzureMessage.Action and use new action framework --- .../lib/common/messager/AzureMessage.java | 5 ++- .../lib/common/messager/IAzureMessage.java | 11 +---- .../lib/common/messager/IAzureMessager.java | 44 +++++++++++-------- .../messager/OpenInBrowserMessageAction.java | 33 -------------- .../common/messager/SimpleMessageAction.java | 28 ------------ 5 files changed, 30 insertions(+), 91 deletions(-) delete mode 100644 azure-toolkit-libs/azure-toolkit-common-lib/src/main/java/com/microsoft/azure/toolkit/lib/common/messager/OpenInBrowserMessageAction.java delete mode 100644 azure-toolkit-libs/azure-toolkit-common-lib/src/main/java/com/microsoft/azure/toolkit/lib/common/messager/SimpleMessageAction.java diff --git a/azure-toolkit-libs/azure-toolkit-common-lib/src/main/java/com/microsoft/azure/toolkit/lib/common/messager/AzureMessage.java b/azure-toolkit-libs/azure-toolkit-common-lib/src/main/java/com/microsoft/azure/toolkit/lib/common/messager/AzureMessage.java index 320f2bda99..c694c30b21 100644 --- a/azure-toolkit-libs/azure-toolkit-common-lib/src/main/java/com/microsoft/azure/toolkit/lib/common/messager/AzureMessage.java +++ b/azure-toolkit-libs/azure-toolkit-common-lib/src/main/java/com/microsoft/azure/toolkit/lib/common/messager/AzureMessage.java @@ -8,6 +8,7 @@ import com.azure.core.exception.HttpResponseException; import com.azure.core.management.exception.ManagementException; import com.google.common.collect.Streams; +import com.microsoft.azure.toolkit.lib.common.action.Action; import com.microsoft.azure.toolkit.lib.common.bundle.AzureString; import com.microsoft.azure.toolkit.lib.common.cache.Cacheable; import com.microsoft.azure.toolkit.lib.common.exception.AzureToolkitException; @@ -52,7 +53,7 @@ public class AzureMessage implements IAzureMessage { @Nullable protected Object payload; @Nullable - protected Action[] actions; + protected Action[] actions; protected ValueDecorator valueDecorator; @Nonnull @@ -189,7 +190,7 @@ public String getTitle() { @Nonnull @Override - public Action[] getActions() { + public Action[] getActions() { return ObjectUtils.firstNonNull(this.actions, new Action[0]); } diff --git a/azure-toolkit-libs/azure-toolkit-common-lib/src/main/java/com/microsoft/azure/toolkit/lib/common/messager/IAzureMessage.java b/azure-toolkit-libs/azure-toolkit-common-lib/src/main/java/com/microsoft/azure/toolkit/lib/common/messager/IAzureMessage.java index 44e75b96dd..2ca2449c4d 100644 --- a/azure-toolkit-libs/azure-toolkit-common-lib/src/main/java/com/microsoft/azure/toolkit/lib/common/messager/IAzureMessage.java +++ b/azure-toolkit-libs/azure-toolkit-common-lib/src/main/java/com/microsoft/azure/toolkit/lib/common/messager/IAzureMessage.java @@ -5,13 +5,12 @@ package com.microsoft.azure.toolkit.lib.common.messager; -import com.microsoft.azure.toolkit.lib.common.bundle.AzureBundle; +import com.microsoft.azure.toolkit.lib.common.action.Action; import com.microsoft.azure.toolkit.lib.common.bundle.AzureString; import com.microsoft.azure.toolkit.lib.common.bundle.CustomDecoratable; import javax.annotation.Nonnull; import javax.annotation.Nullable; -import java.text.MessageFormat; import java.util.Arrays; import java.util.Objects; import java.util.function.Supplier; @@ -35,7 +34,7 @@ default String getContent() { Object getPayload(); @Nullable - Action[] getActions(); + Action[] getActions(); default boolean show() { return AzureMessager.getMessager().show(this); @@ -82,10 +81,4 @@ enum Type { interface ValueDecorator { String decorateValue(@Nonnull Object p, @Nullable IAzureMessage message); } - - interface Action { - String name(); - - void actionPerformed(IAzureMessage message); - } } diff --git a/azure-toolkit-libs/azure-toolkit-common-lib/src/main/java/com/microsoft/azure/toolkit/lib/common/messager/IAzureMessager.java b/azure-toolkit-libs/azure-toolkit-common-lib/src/main/java/com/microsoft/azure/toolkit/lib/common/messager/IAzureMessager.java index 392ca54359..d4e8eaff93 100644 --- a/azure-toolkit-libs/azure-toolkit-common-lib/src/main/java/com/microsoft/azure/toolkit/lib/common/messager/IAzureMessager.java +++ b/azure-toolkit-libs/azure-toolkit-common-lib/src/main/java/com/microsoft/azure/toolkit/lib/common/messager/IAzureMessager.java @@ -1,5 +1,11 @@ +/* + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + */ + package com.microsoft.azure.toolkit.lib.common.messager; +import com.microsoft.azure.toolkit.lib.common.action.Action; import com.microsoft.azure.toolkit.lib.common.bundle.AzureString; import javax.annotation.Nonnull; @@ -9,39 +15,39 @@ public interface IAzureMessager { String DEFAULT_TITLE = "Azure"; - default void success(@Nonnull String message, String title, IAzureMessage.Action... actions) { + default void success(@Nonnull String message, String title, Action... actions) { this.show(this.buildMessage(IAzureMessage.Type.SUCCESS, AzureString.fromString(message), title, actions, null)); } - default void success(@Nonnull AzureString message, String title, IAzureMessage.Action... actions) { + default void success(@Nonnull AzureString message, String title, Action... actions) { this.show(this.buildMessage(IAzureMessage.Type.SUCCESS, message, title, actions, null)); } - default void info(@Nonnull String message, String title, IAzureMessage.Action... actions) { + default void info(@Nonnull String message, String title, Action... actions) { this.show(this.buildMessage(IAzureMessage.Type.INFO, AzureString.fromString(message), title, actions, null)); } - default void info(@Nonnull AzureString message, String title, IAzureMessage.Action... actions) { + default void info(@Nonnull AzureString message, String title, Action... actions) { this.show(this.buildMessage(IAzureMessage.Type.INFO, message, title, actions, null)); } - default void warning(@Nonnull String message, String title, IAzureMessage.Action... actions) { + default void warning(@Nonnull String message, String title, Action... actions) { this.show(this.buildMessage(IAzureMessage.Type.WARNING, AzureString.fromString(message), title, actions, null)); } - default void warning(@Nonnull AzureString message, String title, IAzureMessage.Action... actions) { + default void warning(@Nonnull AzureString message, String title, Action... actions) { this.show(this.buildMessage(IAzureMessage.Type.WARNING, message, title, actions, null)); } - default void error(@Nonnull String message, String title, IAzureMessage.Action... actions) { + default void error(@Nonnull String message, String title, Action... actions) { this.show(this.buildMessage(IAzureMessage.Type.ERROR, AzureString.fromString(message), title, actions, null)); } - default void error(@Nonnull AzureString message, String title, IAzureMessage.Action... actions) { + default void error(@Nonnull AzureString message, String title, Action... actions) { this.show(this.buildMessage(IAzureMessage.Type.ERROR, message, title, actions, null)); } - default void error(@Nonnull Throwable throwable, String title, IAzureMessage.Action... actions) { + default void error(@Nonnull Throwable throwable, String title, Action... actions) { final String message = Optional.ofNullable(throwable.getMessage()).orElse(throwable.getClass().getSimpleName()); this.show(this.buildMessage(IAzureMessage.Type.ERROR, AzureString.fromString(message), title, actions, throwable)); } @@ -63,39 +69,39 @@ default void alert(@Nonnull AzureString message, String title) { } default void success(@Nonnull String message, String title) { - this.success(message, title, new IAzureMessage.Action[0]); + this.success(message, title, new Action[0]); } default void success(@Nonnull AzureString message, String title) { - this.success(message, title, new IAzureMessage.Action[0]); + this.success(message, title, new Action[0]); } default void info(@Nonnull String message, String title) { - this.info(message, title, new IAzureMessage.Action[0]); + this.info(message, title, new Action[0]); } default void info(@Nonnull AzureString message, String title) { - this.info(message, title, new IAzureMessage.Action[0]); + this.info(message, title, new Action[0]); } default void warning(@Nonnull String message, String title) { - this.warning(message, title, new IAzureMessage.Action[0]); + this.warning(message, title, new Action[0]); } default void warning(@Nonnull AzureString message, String title) { - this.warning(message, title, new IAzureMessage.Action[0]); + this.warning(message, title, new Action[0]); } default void error(@Nonnull String message, String title) { - this.error(message, title, new IAzureMessage.Action[0]); + this.error(message, title, new Action[0]); } default void error(@Nonnull AzureString message, String title) { - this.error(message, title, new IAzureMessage.Action[0]); + this.error(message, title, new Action[0]); } default void error(@Nonnull Throwable throwable, String title) { - this.error(throwable, title, new IAzureMessage.Action[0]); + this.error(throwable, title, new Action[0]); } default boolean confirm(@Nonnull String message) { @@ -151,7 +157,7 @@ default void error(@Nonnull Throwable throwable) { } default IAzureMessage buildMessage(@Nonnull IAzureMessage.Type type, @Nonnull AzureString content, - @Nullable String title, @Nullable IAzureMessage.Action[] actions, @Nullable Object payload) { + @Nullable String title, @Nullable Action[] actions, @Nullable Object payload) { final AzureMessage message = new AzureMessage(type, content).setPayload(payload).setActions(actions).setTitle(title); if (this instanceof IAzureMessage.ValueDecorator) { message.setValueDecorator((IAzureMessage.ValueDecorator) this); diff --git a/azure-toolkit-libs/azure-toolkit-common-lib/src/main/java/com/microsoft/azure/toolkit/lib/common/messager/OpenInBrowserMessageAction.java b/azure-toolkit-libs/azure-toolkit-common-lib/src/main/java/com/microsoft/azure/toolkit/lib/common/messager/OpenInBrowserMessageAction.java deleted file mode 100644 index 645c4da27b..0000000000 --- a/azure-toolkit-libs/azure-toolkit-common-lib/src/main/java/com/microsoft/azure/toolkit/lib/common/messager/OpenInBrowserMessageAction.java +++ /dev/null @@ -1,33 +0,0 @@ -package com.microsoft.azure.toolkit.lib.common.messager; - -import lombok.Getter; -import lombok.RequiredArgsConstructor; -import lombok.SneakyThrows; - -import java.awt.*; -import java.net.URI; - -@RequiredArgsConstructor -@Getter -public class OpenInBrowserMessageAction implements IAzureMessage.Action { - private final String name; - private final String url; - - @Override - public String name() { - return this.name; - } - - @SneakyThrows - @Override - public void actionPerformed(IAzureMessage message) { - if (Desktop.isDesktopSupported() && Desktop.getDesktop().isSupported(Desktop.Action.BROWSE)) { - Desktop.getDesktop().browse(new URI(this.url)); - } - } - - @Override - public String toString() { - return String.format("[%s](%s)", this.name, this.url); - } -} \ No newline at end of file diff --git a/azure-toolkit-libs/azure-toolkit-common-lib/src/main/java/com/microsoft/azure/toolkit/lib/common/messager/SimpleMessageAction.java b/azure-toolkit-libs/azure-toolkit-common-lib/src/main/java/com/microsoft/azure/toolkit/lib/common/messager/SimpleMessageAction.java deleted file mode 100644 index 0cedfe72e6..0000000000 --- a/azure-toolkit-libs/azure-toolkit-common-lib/src/main/java/com/microsoft/azure/toolkit/lib/common/messager/SimpleMessageAction.java +++ /dev/null @@ -1,28 +0,0 @@ -package com.microsoft.azure.toolkit.lib.common.messager; - -import lombok.Getter; -import lombok.RequiredArgsConstructor; - -import java.util.function.Consumer; - -@RequiredArgsConstructor -@Getter -public class SimpleMessageAction implements IAzureMessage.Action { - private final String name; - private final Consumer handler; - - @Override - public String name() { - return this.name; - } - - @Override - public void actionPerformed(IAzureMessage payload) { - this.handler.accept(payload); - } - - @Override - public String toString() { - return String.format("[%s]", this.name); - } -} \ No newline at end of file From f4e84e22b3c1a5ce2f010bd6a717b6d52aa56842 Mon Sep 17 00:00:00 2001 From: Mingliang Wang Date: Tue, 7 Sep 2021 15:47:40 +0800 Subject: [PATCH 032/126] extract common AzureHtmlMessage --- .../lib/common/messager/AzureHtmlMessage.java | 95 +++++++++++++++++++ 1 file changed, 95 insertions(+) create mode 100644 azure-toolkit-libs/azure-toolkit-common-lib/src/main/java/com/microsoft/azure/toolkit/lib/common/messager/AzureHtmlMessage.java diff --git a/azure-toolkit-libs/azure-toolkit-common-lib/src/main/java/com/microsoft/azure/toolkit/lib/common/messager/AzureHtmlMessage.java b/azure-toolkit-libs/azure-toolkit-common-lib/src/main/java/com/microsoft/azure/toolkit/lib/common/messager/AzureHtmlMessage.java new file mode 100644 index 0000000000..1baf361ccf --- /dev/null +++ b/azure-toolkit-libs/azure-toolkit-common-lib/src/main/java/com/microsoft/azure/toolkit/lib/common/messager/AzureHtmlMessage.java @@ -0,0 +1,95 @@ +/* + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + */ + +package com.microsoft.azure.toolkit.lib.common.messager; + +import com.microsoft.azure.toolkit.lib.common.bundle.AzureString; +import com.microsoft.azure.toolkit.lib.common.operation.IAzureOperation; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.util.Objects; +import java.util.Optional; +import java.util.function.Supplier; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import static java.util.regex.Pattern.compile; + +public class AzureHtmlMessage extends AzureMessage { + static final Pattern URL_PATTERN = compile("\\s+https?://(www\\.)?[-a-zA-Z0-9@:%._+~#=]{1,256}\\.[a-zA-Z0-9()]{1,6}\\b([-a-zA-Z0-9()@:%_+.~#?&//=]*)"); + + public AzureHtmlMessage(@Nonnull Type type, @Nonnull AzureString message) { + super(type, message); + } + + public AzureHtmlMessage(IAzureMessage raw) { + super(raw.getType(), raw.getMessage()); + if (raw instanceof AzureMessage) { + this.setValueDecorator(((AzureMessage) raw).getValueDecorator()); + } + this.setTitle(raw.getTitle()); + this.setPayload(raw.getPayload()); + this.setActions(raw.getActions()); + } + + @Nonnull + @Override + public String getContent() { + return transformURLIntoLinks(super.getContent()); + } + + @Nullable + @Override + protected String getCause(@Nonnull Throwable throwable) { + final String color = getErrorColor(); + return Optional.ofNullable(super.getCause(throwable)) + .map(cause -> String.format("%s", color, cause)) + .orElse(null); + } + + @Nullable + @Override + protected String getErrorAction(@Nonnull Throwable throwable) { + return Optional.ofNullable(super.getErrorAction(throwable)) + .map(a -> String.format("

%s

", a)) + .orElse(null); + } + + @Override + protected String getDetailItem(IAzureOperation o) { + return String.format("
  • %s
  • ", super.getDetailItem(o)); + } + + @Override + public String decorateValue(@Nonnull Object p, @Nullable Supplier dft) { + String result = super.decorateValue(p, null); + if (Objects.isNull(result)) { + final String color = getValueColor(); + final String font = "'JetBrains Mono', Consolas, 'Liberation Mono', Menlo, Courier, monospace"; + result = String.format("%s", color, font, p.toString()); + } + return Objects.isNull(result) && Objects.nonNull(dft) ? dft.get() : result; + } + + private static String transformURLIntoLinks(String text) { + final Matcher m = URL_PATTERN.matcher(text); + final StringBuffer sb = new StringBuffer(); + while (m.find()) { + final String found = m.group(0); + m.appendReplacement(sb, "" + found + ""); + } + m.appendTail(sb); + return sb.toString(); + } + + protected String getErrorColor() { + return "#FF0000"; + } + + protected String getValueColor() { + return "#0000FF"; + } +} From 171478cbb00dc62532dfa591a8ef3b2b1a602ed6 Mon Sep 17 00:00:00 2001 From: andxu Date: Wed, 8 Sep 2021 16:25:48 +0800 Subject: [PATCH 033/126] Fix cve errors --- .../src/it/3-eventhub-trigger/pom.xml | 2 +- .../maven/projects/parent-project/core/pom.xml | 2 +- .../projects/parent-project/service/pom.xml | 2 +- .../azure-toolkit-appservice-lib/pom.xml | 11 ----------- azure-toolkit-libs/pom.xml | 18 +++--------------- 5 files changed, 6 insertions(+), 29 deletions(-) diff --git a/azure-functions-maven-plugin/src/it/3-eventhub-trigger/pom.xml b/azure-functions-maven-plugin/src/it/3-eventhub-trigger/pom.xml index 630fe4ee77..976c142edc 100644 --- a/azure-functions-maven-plugin/src/it/3-eventhub-trigger/pom.xml +++ b/azure-functions-maven-plugin/src/it/3-eventhub-trigger/pom.xml @@ -45,7 +45,7 @@ org.codehaus.plexus plexus-utils - 3.0.20 + 3.0.24 diff --git a/azure-spring-cloud-maven-plugin/src/test/resources/maven/projects/parent-project/core/pom.xml b/azure-spring-cloud-maven-plugin/src/test/resources/maven/projects/parent-project/core/pom.xml index bd07da9cb2..ca70e228b1 100644 --- a/azure-spring-cloud-maven-plugin/src/test/resources/maven/projects/parent-project/core/pom.xml +++ b/azure-spring-cloud-maven-plugin/src/test/resources/maven/projects/parent-project/core/pom.xml @@ -25,7 +25,7 @@ junit junit - 4.11 + 4.13.1 test diff --git a/azure-spring-cloud-maven-plugin/src/test/resources/maven/projects/parent-project/service/pom.xml b/azure-spring-cloud-maven-plugin/src/test/resources/maven/projects/parent-project/service/pom.xml index b56e0f8b18..629561377c 100644 --- a/azure-spring-cloud-maven-plugin/src/test/resources/maven/projects/parent-project/service/pom.xml +++ b/azure-spring-cloud-maven-plugin/src/test/resources/maven/projects/parent-project/service/pom.xml @@ -25,7 +25,7 @@ junit junit - 4.11 + 4.13.1 test diff --git a/azure-toolkit-libs/azure-toolkit-appservice-lib/pom.xml b/azure-toolkit-libs/azure-toolkit-appservice-lib/pom.xml index 47904255fd..c7f31b0038 100644 --- a/azure-toolkit-libs/azure-toolkit-appservice-lib/pom.xml +++ b/azure-toolkit-libs/azure-toolkit-appservice-lib/pom.xml @@ -78,17 +78,6 @@ commons-codec commons-codec - - com.google.errorprone - error_prone_core - ${error.prone.core.version} - - - com.google.guava - guava - - - org.zeroturnaround zt-zip diff --git a/azure-toolkit-libs/pom.xml b/azure-toolkit-libs/pom.xml index f36e1cce39..2d7c4cd290 100644 --- a/azure-toolkit-libs/pom.xml +++ b/azure-toolkit-libs/pom.xml @@ -101,7 +101,6 @@ 1.21 2.7 2.1.3 - 2.7.1 2.8.7 30.1.1-jre 4.5.13 @@ -111,7 +110,7 @@ 2.3.2 21.0.1 2.2.14 - 2.5.11 + 2.5.14 4.13.2 1.18.20 3.10.0 @@ -124,14 +123,14 @@ 0.9.1 0.9.12 1.9.2 - 9.7 + 9.15 3.1.0 9.9.3 2.10.10 4.4.14 1.2.2 3.0.2-b01 - 3.0.2-b01 + 3.0.2 3.0.1 5.87.0.RELEASE 0.9.0 @@ -674,17 +673,6 @@ httpcore ${httpcore.version} - - com.google.errorprone - error_prone_core - ${error.prone.core.version} - - - com.google.guava - guava - - - com.microsoft.azure azure-arm-client-runtime From 30fac0d3446cb54e976f3c2c4d7eb6f6e7b87146 Mon Sep 17 00:00:00 2001 From: Hanxiao Liu Date: Wed, 8 Sep 2021 17:00:17 +0800 Subject: [PATCH 034/126] Exclude dependencies missing legal information --- azure-toolkit-libs/pom.xml | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/azure-toolkit-libs/pom.xml b/azure-toolkit-libs/pom.xml index 2d7c4cd290..3b5d35dad7 100644 --- a/azure-toolkit-libs/pom.xml +++ b/azure-toolkit-libs/pom.xml @@ -713,6 +713,16 @@ com.networknt json-schema-validator ${networknt.json-schema-validator.version} + + + com.sun.mail + mailapi + + + org.mozilla + rhino + + com.github.java-json-tools From b065ade04658e42a26cfd6bf100d35781fe3128d Mon Sep 17 00:00:00 2001 From: Hanxiao Liu Date: Wed, 8 Sep 2021 17:08:56 +0800 Subject: [PATCH 035/126] Add library for azure compute service in azure toolkit libs --- .../azure-toolkit-compute-lib/pom.xml | 113 ++++++++++++++++++ .../lib/compute/ComputeManagerFactory.java | 44 +++++++ azure-toolkit-libs/pom.xml | 6 + 3 files changed, 163 insertions(+) create mode 100644 azure-toolkit-libs/azure-toolkit-compute-lib/pom.xml create mode 100644 azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/ComputeManagerFactory.java diff --git a/azure-toolkit-libs/azure-toolkit-compute-lib/pom.xml b/azure-toolkit-libs/azure-toolkit-compute-lib/pom.xml new file mode 100644 index 0000000000..d3bda02402 --- /dev/null +++ b/azure-toolkit-libs/azure-toolkit-compute-lib/pom.xml @@ -0,0 +1,113 @@ + + + + azure-toolkit-libs + com.microsoft.azure + 0.12.0-SNAPSHOT + + 4.0.0 + + azure-toolkit-compute-lib + + + + + org.apache.maven.plugins + maven-dependency-plugin + + + org.apache.maven.plugins + maven-source-plugin + + + + + com.nickwongdev + aspectj-maven-plugin + + false + 1.8 + 1.8 + ignore + 1.8 + UTF-8 + false + true + true + + + + com.microsoft.azure + azure-toolkit-common-lib + + + + + + compile-with-aspectj + process-classes + + + ${project.build.directory}/classes + + + + compile + + + + test-compile-with-aspectj + process-test-classes + + test-compile + + + + ${project.build.directory}/test-classes + + + + + + + org.apache.maven.plugins + maven-javadoc-plugin + 2.9.1 + + private + false + + + + attach-javadocs + + jar + + + + + + + + + org.projectlombok + lombok + compile + + + com.azure.resourcemanager + azure-resourcemanager-compute + + + com.microsoft.azure + azure-toolkit-auth-lib + + + com.microsoft.azure + azure-toolkit-common-lib + + + + \ No newline at end of file diff --git a/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/ComputeManagerFactory.java b/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/ComputeManagerFactory.java new file mode 100644 index 0000000000..d59dc04d5b --- /dev/null +++ b/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/ComputeManagerFactory.java @@ -0,0 +1,44 @@ +/* + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + */ + +package com.microsoft.azure.toolkit.lib.compute; + +import com.azure.core.http.policy.HttpLogDetailLevel; +import com.azure.core.http.policy.HttpPipelinePolicy; +import com.azure.core.management.profile.AzureProfile; +import com.azure.resourcemanager.compute.ComputeManager; +import com.microsoft.azure.toolkit.lib.Azure; +import com.microsoft.azure.toolkit.lib.AzureConfiguration; +import com.microsoft.azure.toolkit.lib.auth.Account; +import com.microsoft.azure.toolkit.lib.auth.AzureAccount; +import com.microsoft.azure.toolkit.lib.common.cache.Cacheable; + +import java.util.Optional; + +public class ComputeManagerFactory { + private ComputeManagerFactory() { + } + + @Cacheable(cacheName = "ComputeManager", key = "$subscriptionId") + public static ComputeManager create(String subscriptionId) { + final Account account = Azure.az(AzureAccount.class).account(); + final AzureConfiguration config = Azure.az().config(); + final String userAgent = config.getUserAgent(); + final HttpLogDetailLevel logLevel = Optional.ofNullable(config.getLogLevel()).map(HttpLogDetailLevel::valueOf).orElse(HttpLogDetailLevel.NONE); + final AzureProfile azureProfile = new AzureProfile(null, subscriptionId, account.getEnvironment()); + return ComputeManager.configure() + .withLogLevel(logLevel) + .withPolicy(getUserAgentPolicy(userAgent)) + .authenticate(account.getTokenCredential(subscriptionId), azureProfile); + } + + private static HttpPipelinePolicy getUserAgentPolicy(String userAgent) { + return (httpPipelineCallContext, httpPipelineNextPolicy) -> { + final String previousUserAgent = httpPipelineCallContext.getHttpRequest().getHeaders().getValue("User-Agent"); + httpPipelineCallContext.getHttpRequest().setHeader("User-Agent", String.format("%s %s", userAgent, previousUserAgent)); + return httpPipelineNextPolicy.process(); + }; + } +} diff --git a/azure-toolkit-libs/pom.xml b/azure-toolkit-libs/pom.xml index 3b5d35dad7..bc972d626e 100644 --- a/azure-toolkit-libs/pom.xml +++ b/azure-toolkit-libs/pom.xml @@ -46,6 +46,7 @@ azure-toolkit-storage-lib azure-toolkit-database-lib azure-toolkit-redis-lib + azure-toolkit-compute-lib @@ -551,6 +552,11 @@ azure-resourcemanager-appplatform ${azure.resourcemanager.version} + + com.azure.resourcemanager + azure-resourcemanager-compute + ${azure.resourcemanager.version} + com.azure azure-identity From cf519efd1e964d5da6f60774352010584fd354d0 Mon Sep 17 00:00:00 2001 From: Hanxiao Liu Date: Wed, 8 Sep 2021 17:17:53 +0800 Subject: [PATCH 036/126] Update Azure resource and service interfaces --- .../azure/toolkit/lib/auth/AzureAccount.java | 3 +- .../azure/toolkit/lib/AzureService.java | 14 +--- .../azure/toolkit/lib/SubscriptionScoped.java | 2 +- .../lib/common/entity/IAzureBaseResource.java | 80 +++++++++++++++++++ .../lib/common/entity/IAzureModule.java | 27 +++++++ .../lib/common/entity/IAzureResource.java | 60 +++----------- 6 files changed, 123 insertions(+), 63 deletions(-) create mode 100644 azure-toolkit-libs/azure-toolkit-common-lib/src/main/java/com/microsoft/azure/toolkit/lib/common/entity/IAzureBaseResource.java create mode 100644 azure-toolkit-libs/azure-toolkit-common-lib/src/main/java/com/microsoft/azure/toolkit/lib/common/entity/IAzureModule.java diff --git a/azure-toolkit-libs/azure-toolkit-auth-lib/src/main/java/com/microsoft/azure/toolkit/lib/auth/AzureAccount.java b/azure-toolkit-libs/azure-toolkit-auth-lib/src/main/java/com/microsoft/azure/toolkit/lib/auth/AzureAccount.java index ee9c1700b6..4c5e1a4512 100644 --- a/azure-toolkit-libs/azure-toolkit-auth-lib/src/main/java/com/microsoft/azure/toolkit/lib/auth/AzureAccount.java +++ b/azure-toolkit-libs/azure-toolkit-auth-lib/src/main/java/com/microsoft/azure/toolkit/lib/auth/AzureAccount.java @@ -241,7 +241,8 @@ public List listRegions(String subscriptionId) { * see doc for: az account list-locations -o table */ public List listRegions() { - return Flux.fromIterable(getSubscriptions()).parallel().map(com.microsoft.azure.toolkit.lib.common.model.Subscription::getId) + return Flux.fromIterable(Azure.az(IAzureAccount.class).account().getSelectedSubscriptions()) + .parallel().map(com.microsoft.azure.toolkit.lib.common.model.Subscription::getId) .map(this::listRegions) .sequential().collectList() .map(regionSet -> regionSet.stream() diff --git a/azure-toolkit-libs/azure-toolkit-common-lib/src/main/java/com/microsoft/azure/toolkit/lib/AzureService.java b/azure-toolkit-libs/azure-toolkit-common-lib/src/main/java/com/microsoft/azure/toolkit/lib/AzureService.java index 0b6d63ecd1..e7fae4d021 100644 --- a/azure-toolkit-libs/azure-toolkit-common-lib/src/main/java/com/microsoft/azure/toolkit/lib/AzureService.java +++ b/azure-toolkit-libs/azure-toolkit-common-lib/src/main/java/com/microsoft/azure/toolkit/lib/AzureService.java @@ -6,21 +6,15 @@ package com.microsoft.azure.toolkit.lib; import com.microsoft.azure.toolkit.lib.account.IAzureAccount; +import com.microsoft.azure.toolkit.lib.common.entity.IAzureBaseResource; +import com.microsoft.azure.toolkit.lib.common.entity.IAzureModule; import com.microsoft.azure.toolkit.lib.common.model.Subscription; -import com.microsoft.azure.toolkit.lib.common.operation.AzureOperation; import java.util.List; -public interface AzureService { +public interface AzureService extends IAzureModule { default List getSubscriptions() { return Azure.az(IAzureAccount.class).account().getSelectedSubscriptions(); } - - default String name() { - return this.getClass().getSimpleName(); - } - - @AzureOperation(name = "common|service.refresh", params = "this.name()", type = AzureOperation.Type.SERVICE) - default void refresh() { - } } + diff --git a/azure-toolkit-libs/azure-toolkit-common-lib/src/main/java/com/microsoft/azure/toolkit/lib/SubscriptionScoped.java b/azure-toolkit-libs/azure-toolkit-common-lib/src/main/java/com/microsoft/azure/toolkit/lib/SubscriptionScoped.java index bb6a6a594f..4fc66d38cc 100644 --- a/azure-toolkit-libs/azure-toolkit-common-lib/src/main/java/com/microsoft/azure/toolkit/lib/SubscriptionScoped.java +++ b/azure-toolkit-libs/azure-toolkit-common-lib/src/main/java/com/microsoft/azure/toolkit/lib/SubscriptionScoped.java @@ -22,7 +22,7 @@ import java.util.stream.Collectors; @RequiredArgsConstructor -public abstract class SubscriptionScoped { +public abstract class SubscriptionScoped { @Nonnull private final Function, T> creator; @Nullable diff --git a/azure-toolkit-libs/azure-toolkit-common-lib/src/main/java/com/microsoft/azure/toolkit/lib/common/entity/IAzureBaseResource.java b/azure-toolkit-libs/azure-toolkit-common-lib/src/main/java/com/microsoft/azure/toolkit/lib/common/entity/IAzureBaseResource.java new file mode 100644 index 0000000000..b40d5896aa --- /dev/null +++ b/azure-toolkit-libs/azure-toolkit-common-lib/src/main/java/com/microsoft/azure/toolkit/lib/common/entity/IAzureBaseResource.java @@ -0,0 +1,80 @@ +/* + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + */ + +package com.microsoft.azure.toolkit.lib.common.entity; + +import com.azure.resourcemanager.resources.fluentcore.arm.ResourceId; +import com.microsoft.azure.toolkit.lib.Azure; +import com.microsoft.azure.toolkit.lib.account.IAccount; +import com.microsoft.azure.toolkit.lib.account.IAzureAccount; +import com.microsoft.azure.toolkit.lib.common.model.Subscription; + +import javax.annotation.Nullable; + +public interface IAzureBaseResource { + String REST_SEGMENT_JOB_MANAGEMENT_TENANTID = "/#@"; + String REST_SEGMENT_JOB_MANAGEMENT_RESOURCE = "/resource"; + + @Nullable + default P parent() { + return null; + } + + // todo: Change to Nonnull + @Nullable + default IAzureModule module() { + return null; + } + + IAzureBaseResource refresh(); + + boolean exists(); + + String name(); + + String id(); + + default String status() { + return null; + } + + default void refreshStatus() { + } + + default String subscriptionId() { + return ResourceId.fromString(id()).subscriptionId(); + } + + default String resourceGroup() { + return ResourceId.fromString(id()).resourceGroupName(); + } + + default Subscription subscription() { + return Azure.az(IAzureAccount.class).account().getSubscription(this.subscriptionId()); + } + + default String portalUrl() { + final IAccount account = Azure.az(IAzureAccount.class).account(); + Subscription subscription = account.getSubscription(this.subscriptionId()); + return account.portalUrl() + REST_SEGMENT_JOB_MANAGEMENT_TENANTID + subscription.getTenantId() + REST_SEGMENT_JOB_MANAGEMENT_RESOURCE + this.id(); + } + + interface Status { + // unstable states + String UNSTABLE = "UNSTABLE"; + String PENDING = "PENDING"; + + // Draft + String DRAFT = "DRAFT"; + + // stable states + String STABLE = "STABLE"; + String LOADING = "LOADING"; + String ERROR = "ERROR"; + String RUNNING = "RUNNING"; + String STOPPED = "STOPPED"; + String UNKNOWN = "UNKNOWN"; + } +} diff --git a/azure-toolkit-libs/azure-toolkit-common-lib/src/main/java/com/microsoft/azure/toolkit/lib/common/entity/IAzureModule.java b/azure-toolkit-libs/azure-toolkit-common-lib/src/main/java/com/microsoft/azure/toolkit/lib/common/entity/IAzureModule.java new file mode 100644 index 0000000000..63ddc83881 --- /dev/null +++ b/azure-toolkit-libs/azure-toolkit-common-lib/src/main/java/com/microsoft/azure/toolkit/lib/common/entity/IAzureModule.java @@ -0,0 +1,27 @@ +/* + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + */ + +package com.microsoft.azure.toolkit.lib.common.entity; + +import com.microsoft.azure.toolkit.lib.common.operation.AzureOperation; + +import javax.annotation.Nullable; + +public interface IAzureModule { + + @Nullable + default P getParent() { + return null; + } + + default String name() { + return this.getClass().getSimpleName(); + } + + @AzureOperation(name = "common|service.refresh", params = "this.name()", type = AzureOperation.Type.SERVICE) + default void refresh() { + } +} + diff --git a/azure-toolkit-libs/azure-toolkit-common-lib/src/main/java/com/microsoft/azure/toolkit/lib/common/entity/IAzureResource.java b/azure-toolkit-libs/azure-toolkit-common-lib/src/main/java/com/microsoft/azure/toolkit/lib/common/entity/IAzureResource.java index e30f3ab3ea..2c6b2c56d0 100644 --- a/azure-toolkit-libs/azure-toolkit-common-lib/src/main/java/com/microsoft/azure/toolkit/lib/common/entity/IAzureResource.java +++ b/azure-toolkit-libs/azure-toolkit-common-lib/src/main/java/com/microsoft/azure/toolkit/lib/common/entity/IAzureResource.java @@ -5,30 +5,14 @@ package com.microsoft.azure.toolkit.lib.common.entity; -import com.azure.resourcemanager.resources.fluentcore.arm.ResourceId; -import com.microsoft.azure.toolkit.lib.Azure; -import com.microsoft.azure.toolkit.lib.account.IAccount; -import com.microsoft.azure.toolkit.lib.account.IAzureAccount; -import com.microsoft.azure.toolkit.lib.common.model.Subscription; - -public interface IAzureResource { - - String REST_SEGMENT_JOB_MANAGEMENT_TENANTID = "/#@"; - String REST_SEGMENT_JOB_MANAGEMENT_RESOURCE = "/resource"; +import org.apache.commons.lang3.NotImplementedException; +import javax.annotation.Nullable; +public interface IAzureResource extends IAzureBaseResource { IAzureResource refresh(); - boolean exists(); - T entity(); - default String status() { - return null; - } - - default void refreshStatus() { - } - default String name() { return this.entity().getName(); } @@ -37,39 +21,13 @@ default String id() { return this.entity().getId(); } - default String subscriptionId() { - return ResourceId.fromString(id()).subscriptionId(); + @Nullable + default IAzureBaseResource parent() { + throw new NotImplementedException(); } - default String resourceGroup() { - return ResourceId.fromString(id()).resourceGroupName(); - } - - default Subscription subscription() { - return Azure.az(IAzureAccount.class).account().getSubscription(this.subscriptionId()); - } - - default String portalUrl() { - final IAccount account = Azure.az(IAzureAccount.class).account(); - Subscription subscription = account.getSubscription(this.subscriptionId()); - return account.portalUrl() - + REST_SEGMENT_JOB_MANAGEMENT_TENANTID - + subscription.getTenantId() - + REST_SEGMENT_JOB_MANAGEMENT_RESOURCE - + this.id(); - } - - interface Status { - // unstable states - String UNSTABLE = "UNSTABLE"; - String PENDING = "PENDING"; - - // stable states - String STABLE = "STABLE"; - String LOADING = "LOADING"; - String ERROR = "ERROR"; - String RUNNING = "RUNNING"; - String STOPPED = "STOPPED"; - String UNKNOWN = "UNKNOWN"; + @Nullable + default IAzureModule module() { + throw new NotImplementedException(); } } From a62e4601caaa55462cd7a037e38a08ceafab7e29 Mon Sep 17 00:00:00 2001 From: Hanxiao Liu Date: Wed, 8 Sep 2021 17:18:33 +0800 Subject: [PATCH 037/126] Add abstract implementation for azure resource and resource module --- .../lib/compute/AbstractAzureResource.java | 124 ++++++++++++++++++ .../compute/AbstractAzureResourceModule.java | 53 ++++++++ .../lib/compute/AzureResourceDraft.java | 12 ++ 3 files changed, 189 insertions(+) create mode 100644 azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/AbstractAzureResource.java create mode 100644 azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/AbstractAzureResourceModule.java create mode 100644 azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/AzureResourceDraft.java diff --git a/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/AbstractAzureResource.java b/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/AbstractAzureResource.java new file mode 100644 index 0000000000..a0672ca261 --- /dev/null +++ b/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/AbstractAzureResource.java @@ -0,0 +1,124 @@ +/* + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + */ + +package com.microsoft.azure.toolkit.lib.compute; + +import com.azure.core.management.exception.ManagementException; +import com.azure.resourcemanager.resources.fluentcore.arm.ResourceId; +import com.azure.resourcemanager.resources.fluentcore.arm.models.HasId; +import com.microsoft.azure.toolkit.lib.common.entity.IAzureBaseResource; +import com.microsoft.azure.toolkit.lib.common.event.AzureEventBus; +import com.microsoft.azure.toolkit.lib.common.exception.AzureToolkitRuntimeException; +import com.microsoft.azure.toolkit.lib.common.task.AzureTaskManager; +import lombok.Getter; +import org.apache.commons.lang3.StringUtils; +import org.apache.http.HttpStatus; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.util.Objects; + +public abstract class AbstractAzureResource implements IAzureBaseResource, P> { + @Nonnull + @Getter + protected final String name; + @Getter + @Nonnull + protected final String resourceGroup; + @Getter + @Nonnull + protected final String subscriptionId; + @Getter + protected String id; + + protected T remote; + protected String status = null; + protected boolean isRefreshed = false; + + public AbstractAzureResource(@Nonnull final String id) { + final ResourceId resourceId = ResourceId.fromString(id); + this.id = id; + this.name = resourceId.name(); + this.resourceGroup = resourceId.resourceGroupName(); + this.subscriptionId = resourceId.subscriptionId(); + } + + public AbstractAzureResource(@Nonnull final T resource) { + this(resource.id()); + this.remote = resource; + this.id = resource.id(); + } + + @Override + public AbstractAzureResource refresh() { + try { + this.remote = loadRemote(); + this.isRefreshed = true; + } catch (final ManagementException e) { + if (HttpStatus.SC_NOT_FOUND == e.getResponse().getStatusCode()) { + this.remote = null; + this.isRefreshed = true; + } else { + throw e; + } + } + return this; + } + + @Override + public boolean exists() { + if (Objects.isNull(this.remote) && !this.isRefreshed) { + this.refresh(); + } + return Objects.nonNull(this.remote); + } + + @Override + public String name() { + return this.name; + } + + @Override + public String id() { + return getId(); + } + + @Nonnull + protected final T remote() { + if (!exists()) { + throw new AzureToolkitRuntimeException(String.format("Target resource %s does not exist.", name)); + } + return this.remote; + } + + @Override + public final String status() { + if (Objects.nonNull(this.status)) { + return this.status; + } else { + this.refreshStatus(); + return Status.LOADING; + } + } + + public final void refreshStatus() { + AzureTaskManager.getInstance().runOnPooledThread(() -> this.status(this.loadStatus())); + } + + protected final void status(@Nonnull String status) { + final String oldStatus = this.status; + this.status = status; + if (!StringUtils.equalsIgnoreCase(oldStatus, this.status)) { + AzureEventBus.emit("common|resource.status_changed", this); + } + } + + @Nullable + protected abstract T loadRemote(); + + protected String loadStatus() { + return Status.RUNNING; + } +} diff --git a/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/AbstractAzureResourceModule.java b/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/AbstractAzureResourceModule.java new file mode 100644 index 0000000000..db757fa6b9 --- /dev/null +++ b/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/AbstractAzureResourceModule.java @@ -0,0 +1,53 @@ +/* + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + */ +package com.microsoft.azure.toolkit.lib.compute; + +import com.azure.resourcemanager.resources.fluentcore.arm.ResourceId; +import com.microsoft.azure.toolkit.lib.AzureService; +import com.microsoft.azure.toolkit.lib.SubscriptionScoped; +import com.microsoft.azure.toolkit.lib.common.entity.IAzureBaseResource; +import com.microsoft.azure.toolkit.lib.common.model.Subscription; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import javax.annotation.Nonnull; +import java.util.List; +import java.util.function.Function; +import java.util.stream.Collectors; + +public abstract class AbstractAzureResourceModule extends SubscriptionScoped> + implements AzureService { + + public AbstractAzureResourceModule(@NotNull Function, AbstractAzureResourceModule> creator, + @Nullable List subscriptions) { + super(creator, subscriptions); + } + + public AbstractAzureResourceModule(@NotNull Function, AbstractAzureResourceModule> creator) { + super(creator); + } + + public List list() { + return getSubscriptions().stream().parallel() + .flatMap(subscription -> list(subscription.getId()).stream()) + .collect(Collectors.toList()); + } + + @Nonnull + public T get(@Nonnull final String id) { + final ResourceId resourceId = ResourceId.fromString(id); + return get(resourceId.subscriptionId(), resourceId.resourceGroupName(), resourceId.name()); + } + + @Nonnull + public T get(@Nonnull final String resourceGroup, @Nonnull final String name) { + return get(getDefaultSubscription().getId(), resourceGroup, name); + } + + public abstract List list(@Nonnull final String subscriptionId); + + @Nonnull + public abstract T get(@Nonnull final String subscriptionId, @Nonnull final String resourceGroup, @Nonnull final String name); +} diff --git a/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/AzureResourceDraft.java b/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/AzureResourceDraft.java new file mode 100644 index 0000000000..ab556b56ba --- /dev/null +++ b/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/AzureResourceDraft.java @@ -0,0 +1,12 @@ +/* + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + */ + +package com.microsoft.azure.toolkit.lib.compute; + +import com.microsoft.azure.toolkit.lib.common.entity.IAzureBaseResource; + +public interface AzureResourceDraft { + +} From ac2497e82d8276f63199b0c5ccd086b06dd9b23c Mon Sep 17 00:00:00 2001 From: Hanxiao Liu Date: Wed, 8 Sep 2021 17:32:06 +0800 Subject: [PATCH 038/126] Revert limitation for subscription scoped --- .../com/microsoft/azure/toolkit/lib/SubscriptionScoped.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/azure-toolkit-libs/azure-toolkit-common-lib/src/main/java/com/microsoft/azure/toolkit/lib/SubscriptionScoped.java b/azure-toolkit-libs/azure-toolkit-common-lib/src/main/java/com/microsoft/azure/toolkit/lib/SubscriptionScoped.java index 4fc66d38cc..bb6a6a594f 100644 --- a/azure-toolkit-libs/azure-toolkit-common-lib/src/main/java/com/microsoft/azure/toolkit/lib/SubscriptionScoped.java +++ b/azure-toolkit-libs/azure-toolkit-common-lib/src/main/java/com/microsoft/azure/toolkit/lib/SubscriptionScoped.java @@ -22,7 +22,7 @@ import java.util.stream.Collectors; @RequiredArgsConstructor -public abstract class SubscriptionScoped { +public abstract class SubscriptionScoped { @Nonnull private final Function, T> creator; @Nullable From 1b0e044931d70189c9ea9a73d290ad5f3b7bb2ae Mon Sep 17 00:00:00 2001 From: Hanxiao Liu Date: Fri, 10 Sep 2021 09:58:40 +0800 Subject: [PATCH 039/126] Resolve comments --- .../azure/toolkit/lib/AzureService.java | 2 +- .../compute/AbstractAzureResourceModule.java | 38 +++++++++++++++++-- 2 files changed, 36 insertions(+), 4 deletions(-) diff --git a/azure-toolkit-libs/azure-toolkit-common-lib/src/main/java/com/microsoft/azure/toolkit/lib/AzureService.java b/azure-toolkit-libs/azure-toolkit-common-lib/src/main/java/com/microsoft/azure/toolkit/lib/AzureService.java index e7fae4d021..c1173bd389 100644 --- a/azure-toolkit-libs/azure-toolkit-common-lib/src/main/java/com/microsoft/azure/toolkit/lib/AzureService.java +++ b/azure-toolkit-libs/azure-toolkit-common-lib/src/main/java/com/microsoft/azure/toolkit/lib/AzureService.java @@ -12,7 +12,7 @@ import java.util.List; -public interface AzureService extends IAzureModule { +public interface AzureService extends IAzureModule { default List getSubscriptions() { return Azure.az(IAzureAccount.class).account().getSelectedSubscriptions(); } diff --git a/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/AbstractAzureResourceModule.java b/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/AbstractAzureResourceModule.java index db757fa6b9..d4c2ba363e 100644 --- a/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/AbstractAzureResourceModule.java +++ b/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/AbstractAzureResourceModule.java @@ -4,9 +4,20 @@ */ package com.microsoft.azure.toolkit.lib.compute; +import com.azure.core.http.policy.HttpLogDetailLevel; +import com.azure.core.http.policy.HttpPipelinePolicy; +import com.azure.core.management.profile.AzureProfile; +import com.azure.resourcemanager.appservice.models.LogLevel; +import com.azure.resourcemanager.compute.ComputeManager; +import com.azure.resourcemanager.resources.fluentcore.arm.AzureConfigurable; import com.azure.resourcemanager.resources.fluentcore.arm.ResourceId; +import com.azure.resourcemanager.resources.fluentcore.arm.implementation.AzureConfigurableImpl; +import com.microsoft.azure.toolkit.lib.Azure; +import com.microsoft.azure.toolkit.lib.AzureConfiguration; import com.microsoft.azure.toolkit.lib.AzureService; import com.microsoft.azure.toolkit.lib.SubscriptionScoped; +import com.microsoft.azure.toolkit.lib.auth.Account; +import com.microsoft.azure.toolkit.lib.auth.AzureAccount; import com.microsoft.azure.toolkit.lib.common.entity.IAzureBaseResource; import com.microsoft.azure.toolkit.lib.common.model.Subscription; import org.jetbrains.annotations.NotNull; @@ -14,11 +25,12 @@ import javax.annotation.Nonnull; import java.util.List; +import java.util.Optional; import java.util.function.Function; import java.util.stream.Collectors; public abstract class AbstractAzureResourceModule extends SubscriptionScoped> - implements AzureService { + implements AzureService { public AbstractAzureResourceModule(@NotNull Function, AbstractAzureResourceModule> creator, @Nullable List subscriptions) { @@ -46,8 +58,28 @@ public T get(@Nonnull final String resourceGroup, @Nonnull final String name) { return get(getDefaultSubscription().getId(), resourceGroup, name); } - public abstract List list(@Nonnull final String subscriptionId); + protected abstract List list(@Nonnull final String subscriptionId); @Nonnull - public abstract T get(@Nonnull final String subscriptionId, @Nonnull final String resourceGroup, @Nonnull final String name); + protected abstract T get(@Nonnull final String subscriptionId, @Nonnull final String resourceGroup, @Nonnull final String name); + + protected static > R getResourceManager(String subscriptionId, AzureConfigurableImpl configurable) { + final AzureConfiguration config = Azure.az().config(); + final String userAgent = config.getUserAgent(); + final HttpLogDetailLevel logLevel = Optional.ofNullable(config.getLogLevel()).map(HttpLogDetailLevel::valueOf).orElse(HttpLogDetailLevel.NONE); + return configurable.withLogLevel(logLevel).withPolicy(getUserAgentPolicy(userAgent)); + } + + protected static AzureProfile getAzureProfile(final String subscriptionId) { + final Account account = Azure.az(AzureAccount.class).account(); + return new AzureProfile(null, subscriptionId, account.getEnvironment()); + } + + protected static HttpPipelinePolicy getUserAgentPolicy(String userAgent) { + return (httpPipelineCallContext, httpPipelineNextPolicy) -> { + final String previousUserAgent = httpPipelineCallContext.getHttpRequest().getHeaders().getValue("User-Agent"); + httpPipelineCallContext.getHttpRequest().setHeader("User-Agent", String.format("%s %s", userAgent, previousUserAgent)); + return httpPipelineNextPolicy.process(); + }; + } } From a737e5821083d63516da13eecf40853fa46bbb5f Mon Sep 17 00:00:00 2001 From: Hanxiao Liu Date: Fri, 10 Sep 2021 11:28:34 +0800 Subject: [PATCH 040/126] Add generic resource manager getter in abstract resource module and remove compute manager factory --- .../compute/AbstractAzureResourceModule.java | 21 +++++---- .../lib/compute/ComputeManagerFactory.java | 44 ------------------- 2 files changed, 13 insertions(+), 52 deletions(-) delete mode 100644 azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/ComputeManagerFactory.java diff --git a/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/AbstractAzureResourceModule.java b/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/AbstractAzureResourceModule.java index d4c2ba363e..fd1f571442 100644 --- a/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/AbstractAzureResourceModule.java +++ b/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/AbstractAzureResourceModule.java @@ -4,14 +4,13 @@ */ package com.microsoft.azure.toolkit.lib.compute; +import com.azure.core.credential.TokenCredential; import com.azure.core.http.policy.HttpLogDetailLevel; import com.azure.core.http.policy.HttpPipelinePolicy; import com.azure.core.management.profile.AzureProfile; -import com.azure.resourcemanager.appservice.models.LogLevel; -import com.azure.resourcemanager.compute.ComputeManager; import com.azure.resourcemanager.resources.fluentcore.arm.AzureConfigurable; +import com.azure.resourcemanager.resources.fluentcore.arm.Manager; import com.azure.resourcemanager.resources.fluentcore.arm.ResourceId; -import com.azure.resourcemanager.resources.fluentcore.arm.implementation.AzureConfigurableImpl; import com.microsoft.azure.toolkit.lib.Azure; import com.microsoft.azure.toolkit.lib.AzureConfiguration; import com.microsoft.azure.toolkit.lib.AzureService; @@ -27,6 +26,7 @@ import java.util.List; import java.util.Optional; import java.util.function.Function; +import java.util.function.Supplier; import java.util.stream.Collectors; public abstract class AbstractAzureResourceModule extends SubscriptionScoped> @@ -63,16 +63,21 @@ public T get(@Nonnull final String resourceGroup, @Nonnull final String name) { @Nonnull protected abstract T get(@Nonnull final String subscriptionId, @Nonnull final String resourceGroup, @Nonnull final String name); - protected static > R getResourceManager(String subscriptionId, AzureConfigurableImpl configurable) { + protected static , T extends Manager> T getResourceManager( + final String subscriptionId, Supplier> configurableSupplier, AuthenticationMethod authenticationMethod) { + final Account account = Azure.az(AzureAccount.class).account(); final AzureConfiguration config = Azure.az().config(); final String userAgent = config.getUserAgent(); final HttpLogDetailLevel logLevel = Optional.ofNullable(config.getLogLevel()).map(HttpLogDetailLevel::valueOf).orElse(HttpLogDetailLevel.NONE); - return configurable.withLogLevel(logLevel).withPolicy(getUserAgentPolicy(userAgent)); + final AzureProfile azureProfile = new AzureProfile(null, subscriptionId, account.getEnvironment()); + final TokenCredential tokenCredential = account.getTokenCredential(subscriptionId); + final R configurable = configurableSupplier.get().withPolicy(getUserAgentPolicy(userAgent)).withLogLevel(logLevel); + return authenticationMethod.apply(configurable, tokenCredential, azureProfile); } - protected static AzureProfile getAzureProfile(final String subscriptionId) { - final Account account = Azure.az(AzureAccount.class).account(); - return new AzureProfile(null, subscriptionId, account.getEnvironment()); + @FunctionalInterface + protected interface AuthenticationMethod, T extends Manager> { + T apply(R configurable, TokenCredential tokenCredential, AzureProfile azureProfile); } protected static HttpPipelinePolicy getUserAgentPolicy(String userAgent) { diff --git a/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/ComputeManagerFactory.java b/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/ComputeManagerFactory.java deleted file mode 100644 index d59dc04d5b..0000000000 --- a/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/ComputeManagerFactory.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - */ - -package com.microsoft.azure.toolkit.lib.compute; - -import com.azure.core.http.policy.HttpLogDetailLevel; -import com.azure.core.http.policy.HttpPipelinePolicy; -import com.azure.core.management.profile.AzureProfile; -import com.azure.resourcemanager.compute.ComputeManager; -import com.microsoft.azure.toolkit.lib.Azure; -import com.microsoft.azure.toolkit.lib.AzureConfiguration; -import com.microsoft.azure.toolkit.lib.auth.Account; -import com.microsoft.azure.toolkit.lib.auth.AzureAccount; -import com.microsoft.azure.toolkit.lib.common.cache.Cacheable; - -import java.util.Optional; - -public class ComputeManagerFactory { - private ComputeManagerFactory() { - } - - @Cacheable(cacheName = "ComputeManager", key = "$subscriptionId") - public static ComputeManager create(String subscriptionId) { - final Account account = Azure.az(AzureAccount.class).account(); - final AzureConfiguration config = Azure.az().config(); - final String userAgent = config.getUserAgent(); - final HttpLogDetailLevel logLevel = Optional.ofNullable(config.getLogLevel()).map(HttpLogDetailLevel::valueOf).orElse(HttpLogDetailLevel.NONE); - final AzureProfile azureProfile = new AzureProfile(null, subscriptionId, account.getEnvironment()); - return ComputeManager.configure() - .withLogLevel(logLevel) - .withPolicy(getUserAgentPolicy(userAgent)) - .authenticate(account.getTokenCredential(subscriptionId), azureProfile); - } - - private static HttpPipelinePolicy getUserAgentPolicy(String userAgent) { - return (httpPipelineCallContext, httpPipelineNextPolicy) -> { - final String previousUserAgent = httpPipelineCallContext.getHttpRequest().getHeaders().getValue("User-Agent"); - httpPipelineCallContext.getHttpRequest().setHeader("User-Agent", String.format("%s %s", userAgent, previousUserAgent)); - return httpPipelineNextPolicy.process(); - }; - } -} From e209b381de0cf04f0a5de06b249e0ffb371e4692 Mon Sep 17 00:00:00 2001 From: Mingliang Wang Date: Fri, 10 Sep 2021 13:50:27 +0800 Subject: [PATCH 041/126] AzureTask.Monitor --- .../toolkit/lib/common/action/Action.java | 21 ++++++++++++------ .../lib/common/messager/AzureHtmlMessage.java | 4 ++-- .../toolkit/lib/common/task/AzureTask.java | 22 +++++++++++++++++++ 3 files changed, 38 insertions(+), 9 deletions(-) diff --git a/azure-toolkit-libs/azure-toolkit-common-lib/src/main/java/com/microsoft/azure/toolkit/lib/common/action/Action.java b/azure-toolkit-libs/azure-toolkit-common-lib/src/main/java/com/microsoft/azure/toolkit/lib/common/action/Action.java index 9b012fb119..c640a32e4d 100644 --- a/azure-toolkit-libs/azure-toolkit-common-lib/src/main/java/com/microsoft/azure/toolkit/lib/common/action/Action.java +++ b/azure-toolkit-libs/azure-toolkit-common-lib/src/main/java/com/microsoft/azure/toolkit/lib/common/action/Action.java @@ -71,20 +71,27 @@ public IView.Label view(D source) { } @SuppressWarnings("unchecked") - public void handle(D source, Object e) { + public BiConsumer handler(D source, Object e) { for (int i = this.handlers.size() - 1; i >= 0; i--) { final AbstractMap.SimpleEntry, BiConsumer> p = this.handlers.get(i); final BiPredicate condition = (BiPredicate) p.getKey(); final BiConsumer handler = (BiConsumer) p.getValue(); if (condition.test(source, e)) { - final AzureString title = Optional.ofNullable(this.view).map(b -> b.title).map(t -> t.apply(source)) - .orElse(AzureString.fromString(IAzureOperation.UNKNOWN_NAME)); - final AzureTask task = new AzureTask<>(title, () -> handle(source, e, handler)); - task.setType(AzureOperation.Type.ACTION.name()); - AzureTaskManager.getInstance().runInBackground(task); - return; + return handler; } } + return null; + } + + public void handle(D source, Object e) { + final BiConsumer handler = this.handler(source, e); + if (Objects.nonNull(handler)) { + final AzureString title = Optional.ofNullable(this.view).map(b -> b.title).map(t -> t.apply(source)) + .orElse(AzureString.fromString(IAzureOperation.UNKNOWN_NAME)); + final AzureTask task = new AzureTask<>(title, () -> handle(source, e, handler)); + task.setType(AzureOperation.Type.ACTION.name()); + AzureTaskManager.getInstance().runInBackground(task); + } } protected void handle(D source, Object e, BiConsumer handler) { diff --git a/azure-toolkit-libs/azure-toolkit-common-lib/src/main/java/com/microsoft/azure/toolkit/lib/common/messager/AzureHtmlMessage.java b/azure-toolkit-libs/azure-toolkit-common-lib/src/main/java/com/microsoft/azure/toolkit/lib/common/messager/AzureHtmlMessage.java index 1baf361ccf..5e55a1abbd 100644 --- a/azure-toolkit-libs/azure-toolkit-common-lib/src/main/java/com/microsoft/azure/toolkit/lib/common/messager/AzureHtmlMessage.java +++ b/azure-toolkit-libs/azure-toolkit-common-lib/src/main/java/com/microsoft/azure/toolkit/lib/common/messager/AzureHtmlMessage.java @@ -46,7 +46,7 @@ public String getContent() { protected String getCause(@Nonnull Throwable throwable) { final String color = getErrorColor(); return Optional.ofNullable(super.getCause(throwable)) - .map(cause -> String.format("%s", color, cause)) + .map(cause -> String.format("%s", color, cause)) .orElse(null); } @@ -69,7 +69,7 @@ public String decorateValue(@Nonnull Object p, @Nullable Supplier dft) { if (Objects.isNull(result)) { final String color = getValueColor(); final String font = "'JetBrains Mono', Consolas, 'Liberation Mono', Menlo, Courier, monospace"; - result = String.format("%s", color, font, p.toString()); + result = String.format("%s", color, font, p); } return Objects.isNull(result) && Objects.nonNull(dft) ? dft.get() : result; } diff --git a/azure-toolkit-libs/azure-toolkit-common-lib/src/main/java/com/microsoft/azure/toolkit/lib/common/task/AzureTask.java b/azure-toolkit-libs/azure-toolkit-common-lib/src/main/java/com/microsoft/azure/toolkit/lib/common/task/AzureTask.java index 6706918db8..beac934feb 100644 --- a/azure-toolkit-libs/azure-toolkit-common-lib/src/main/java/com/microsoft/azure/toolkit/lib/common/task/AzureTask.java +++ b/azure-toolkit-libs/azure-toolkit-common-lib/src/main/java/com/microsoft/azure/toolkit/lib/common/task/AzureTask.java @@ -38,6 +38,7 @@ public class AzureTask implements IAzureOperation { @Nonnull @Builder.Default private String type = "ASYNC"; + private Monitor monitor; public AzureTask() { this((Supplier) null); @@ -126,6 +127,7 @@ public AzureTask(@Nullable Object project, @Nullable AzureString title, boolean this.project = project; this.title = title; this.cancellable = cancellable; + this.monitor = new DefaultMonitor(); this.supplier = supplier; this.modality = modality; } @@ -152,4 +154,24 @@ public T execute() { public enum Modality { DEFAULT, ANY, NONE } + + public interface Monitor { + void cancel(); + + boolean isCancelled(); + } + + public static class DefaultMonitor implements Monitor { + private boolean cancelled = false; + + @Override + public void cancel() { + this.cancelled = true; + } + + @Override + public boolean isCancelled() { + return this.cancelled; + } + } } From 2880d3798fc7b5b880f3a5a155e57fe5b1417922 Mon Sep 17 00:00:00 2001 From: Hanxiao Liu Date: Sun, 12 Sep 2021 22:09:58 +0800 Subject: [PATCH 042/126] Add library for azure ip service --- .../lib/compute/ip/AzurePublicIpAddress.java | 51 ++++++++++++++++++ .../lib/compute/ip/DraftPublicIpAddress.java | 54 +++++++++++++++++++ .../lib/compute/ip/PublicIpAddress.java | 41 ++++++++++++++ 3 files changed, 146 insertions(+) create mode 100644 azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/ip/AzurePublicIpAddress.java create mode 100644 azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/ip/DraftPublicIpAddress.java create mode 100644 azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/ip/PublicIpAddress.java diff --git a/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/ip/AzurePublicIpAddress.java b/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/ip/AzurePublicIpAddress.java new file mode 100644 index 0000000000..3d1a0a0a72 --- /dev/null +++ b/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/ip/AzurePublicIpAddress.java @@ -0,0 +1,51 @@ +/* + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + */ + +package com.microsoft.azure.toolkit.lib.compute.ip; + +import com.azure.resourcemanager.compute.ComputeManager; +import com.azure.resourcemanager.network.models.PublicIpAddresses; +import com.microsoft.azure.toolkit.lib.common.model.Subscription; +import com.microsoft.azure.toolkit.lib.compute.AbstractAzureResourceModule; + +import javax.annotation.Nonnull; +import java.util.List; +import java.util.stream.Collectors; + +public class AzurePublicIpAddress extends AbstractAzureResourceModule { + + public AzurePublicIpAddress() { + super(AzurePublicIpAddress::new); + } + + private AzurePublicIpAddress(@Nonnull final List subscriptions) { + super(AzurePublicIpAddress::new, subscriptions); + } + + @Override + public List list(@Nonnull String subscriptionId) { + return getPublicIpAddressManager(subscriptionId).list().stream().map(ip -> new PublicIpAddress(ip, this)).collect(Collectors.toList()); + } + + @Nonnull + @Override + public PublicIpAddress get(@Nonnull final String subscriptionId, @Nonnull final String resourceGroup, @Nonnull final String name) { + final PublicIpAddresses virtualMachinesManager = getPublicIpAddressManager(subscriptionId); + return new PublicIpAddress(virtualMachinesManager.getByResourceGroup(resourceGroup, name), this); + } + + public PublicIpAddress create(@Nonnull final DraftPublicIpAddress draftPublicIpAddress) { + return draftPublicIpAddress.create(this); + } + + public PublicIpAddresses getPublicIpAddressManager(String subscriptionId) { + return getResourceManager(subscriptionId, ComputeManager::configure, ComputeManager.Configurable::authenticate).networkManager().publicIpAddresses(); + } + + @Override + public String name() { + return "PublicIpAddress"; + } +} diff --git a/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/ip/DraftPublicIpAddress.java b/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/ip/DraftPublicIpAddress.java new file mode 100644 index 0000000000..9b04e5ab60 --- /dev/null +++ b/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/ip/DraftPublicIpAddress.java @@ -0,0 +1,54 @@ +/* + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + */ + +package com.microsoft.azure.toolkit.lib.compute.ip; + +import com.microsoft.azure.toolkit.lib.common.model.Region; +import com.microsoft.azure.toolkit.lib.compute.AzureResourceDraft; +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.Setter; +import org.jetbrains.annotations.Nullable; + +import javax.annotation.Nonnull; +import java.util.Optional; + +@Getter +@Setter +@EqualsAndHashCode(callSuper = true) +public class DraftPublicIpAddress extends PublicIpAddress implements AzureResourceDraft { + private Region region; + private String leafDomainLabel; + + public DraftPublicIpAddress(@Nonnull final String subscriptionId, @Nonnull final String resourceGroup, @Nonnull final String name) { + super(getResourceId(subscriptionId, resourceGroup, name), null); + } + + PublicIpAddress create(AzurePublicIpAddress module) { + this.module = module; + module.getPublicIpAddressManager(subscriptionId).define(name) + .withRegion(region.getName()) + .withExistingResourceGroup(resourceGroup) + .withLeafDomainLabel(leafDomainLabel) + .create(); + refreshStatus(); + return this; + } + + @Override + protected String loadStatus() { + return Optional.ofNullable(module).map(ignore -> super.loadStatus()).orElse(Status.DRAFT); + } + + @Nullable + @Override + protected com.azure.resourcemanager.network.models.PublicIpAddress loadRemote() { + return Optional.ofNullable(module).map(ignore -> super.loadRemote()).orElse(null); + } + + private static String getResourceId(@Nonnull final String subscriptionId, @Nonnull final String resourceGroup, @Nonnull final String name) { + return String.format("/subscriptions/%s/resourceGroups/%s/providers/Microsoft.Network/publicIPAddresses/%s", subscriptionId, resourceGroup, name); + } +} diff --git a/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/ip/PublicIpAddress.java b/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/ip/PublicIpAddress.java new file mode 100644 index 0000000000..2df1e50460 --- /dev/null +++ b/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/ip/PublicIpAddress.java @@ -0,0 +1,41 @@ +/* + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + */ + +package com.microsoft.azure.toolkit.lib.compute.ip; + +import com.microsoft.azure.toolkit.lib.common.entity.IAzureBaseResource; +import com.microsoft.azure.toolkit.lib.common.entity.IAzureModule; +import com.microsoft.azure.toolkit.lib.compute.AbstractAzureResource; +import lombok.EqualsAndHashCode; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +@EqualsAndHashCode(callSuper = true) +public class PublicIpAddress extends AbstractAzureResource { + + protected AzurePublicIpAddress module; + + public PublicIpAddress(@Nonnull final String id, final AzurePublicIpAddress azureClient) { + super(id); + this.module = azureClient; + } + + public PublicIpAddress(@Nonnull final com.azure.resourcemanager.network.models.PublicIpAddress resource, final AzurePublicIpAddress module) { + super(resource); + this.module = module; + } + + @Override + public IAzureModule, ? extends IAzureBaseResource> module() { + return module; + } + + @Nullable + @Override + protected com.azure.resourcemanager.network.models.PublicIpAddress loadRemote() { + return module.getPublicIpAddressManager(getSubscriptionId()).getByResourceGroup(resourceGroup(), name()); + } +} From da3435283769ef446e9590d4cea7c7884b85fb20 Mon Sep 17 00:00:00 2001 From: Hanxiao Liu Date: Sun, 12 Sep 2021 22:10:27 +0800 Subject: [PATCH 043/126] Add library for azure virtual network service --- .../lib/compute/network/AzureNetwork.java | 50 +++++++++++++ .../lib/compute/network/DraftNetwork.java | 74 +++++++++++++++++++ .../toolkit/lib/compute/network/Network.java | 48 ++++++++++++ .../lib/compute/network/model/Subnet.java | 25 +++++++ 4 files changed, 197 insertions(+) create mode 100644 azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/network/AzureNetwork.java create mode 100644 azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/network/DraftNetwork.java create mode 100644 azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/network/Network.java create mode 100644 azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/network/model/Subnet.java diff --git a/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/network/AzureNetwork.java b/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/network/AzureNetwork.java new file mode 100644 index 0000000000..f6ec9053a7 --- /dev/null +++ b/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/network/AzureNetwork.java @@ -0,0 +1,50 @@ +/* + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + */ + +package com.microsoft.azure.toolkit.lib.compute.network; + +import com.azure.resourcemanager.compute.ComputeManager; +import com.azure.resourcemanager.network.models.Networks; +import com.microsoft.azure.toolkit.lib.common.model.Subscription; +import com.microsoft.azure.toolkit.lib.compute.AbstractAzureResourceModule; + +import javax.annotation.Nonnull; +import java.util.List; +import java.util.stream.Collectors; + +public class AzureNetwork extends AbstractAzureResourceModule { + public AzureNetwork() { + super(AzureNetwork::new); + } + + private AzureNetwork(@Nonnull final List subscriptions) { + super(AzureNetwork::new, subscriptions); + } + + @Override + public List list(@Nonnull String subscriptionId) { + return getNetworkManager(subscriptionId).list().stream().map(network -> new Network(network, this)).collect(Collectors.toList()); + } + + @Nonnull + @Override + public Network get(@Nonnull String subscriptionId, @Nonnull String resourceGroup, @Nonnull String name) { + final Networks networks = getNetworkManager(subscriptionId); + return new Network(networks.getByResourceGroup(resourceGroup, name), this); + } + + public Network create(@Nonnull final DraftNetwork draftNetwork) { + return draftNetwork.create(this); + } + + public Networks getNetworkManager(@Nonnull final String subscriptionId) { + return getResourceManager(subscriptionId, ComputeManager::configure, ComputeManager.Configurable::authenticate).networkManager().networks(); + } + + @Override + public String name() { + return "Network"; + } +} diff --git a/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/network/DraftNetwork.java b/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/network/DraftNetwork.java new file mode 100644 index 0000000000..4c2b357638 --- /dev/null +++ b/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/network/DraftNetwork.java @@ -0,0 +1,74 @@ +/* + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + */ + +package com.microsoft.azure.toolkit.lib.compute.network; + +import com.azure.resourcemanager.network.models.Network.DefinitionStages.WithCreateAndSubnet; +import com.microsoft.azure.toolkit.lib.common.model.Region; +import com.microsoft.azure.toolkit.lib.compute.AzureResourceDraft; +import com.microsoft.azure.toolkit.lib.compute.network.model.Subnet; +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.Setter; +import org.apache.commons.lang3.StringUtils; +import org.jetbrains.annotations.Nullable; + +import javax.annotation.Nonnull; +import java.util.Collections; +import java.util.List; +import java.util.Optional; + +@Getter +@Setter +@EqualsAndHashCode(callSuper = true) +public class DraftNetwork extends Network implements AzureResourceDraft { + + private String subscriptionId; + private String resourceGroup; + private String name; + private Region region; + private String addressSpace; + + private String subnet; + private String subnetAddressSpace; + + public DraftNetwork(@Nonnull final String subscriptionId, @Nonnull final String resourceGroup, @Nonnull final String name) { + super(getResourceId(subscriptionId, resourceGroup, name), null); + } + + Network create(final AzureNetwork module) { + this.module = module; + WithCreateAndSubnet withCreateAndSubnet = module.getNetworkManager(subscriptionId).define(name) + .withRegion(region.getName()) + .withExistingResourceGroup(resourceGroup) + .withAddressSpace(addressSpace); + if (StringUtils.isNotEmpty(subnet)) { + withCreateAndSubnet = withCreateAndSubnet.withSubnet(subnet, subnetAddressSpace); + } + this.remote = withCreateAndSubnet.create(); + refreshStatus(); + return this; + } + + @Override + public List subnets() { + return Optional.ofNullable(module).map(ignore -> super.subnets()).orElseGet(() -> Collections.singletonList(new Subnet(subnet, subnetAddressSpace))); + } + + @Override + protected String loadStatus() { + return Optional.ofNullable(module).map(ignore -> super.loadStatus()).orElse(Status.DRAFT); + } + + @Nullable + @Override + protected com.azure.resourcemanager.network.models.Network loadRemote() { + return Optional.ofNullable(module).map(ignore -> super.loadRemote()).orElse(null); + } + + private static String getResourceId(@Nonnull final String subscriptionId, @Nonnull final String resourceGroup, @Nonnull final String name) { + return String.format("/subscriptions/%s/resourceGroups/%s/providers/Microsoft.Network/virtualNetworks/%s", subscriptionId, resourceGroup, name); + } +} diff --git a/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/network/Network.java b/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/network/Network.java new file mode 100644 index 0000000000..0e75635492 --- /dev/null +++ b/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/network/Network.java @@ -0,0 +1,48 @@ +/* + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + */ + +package com.microsoft.azure.toolkit.lib.compute.network; + +import com.microsoft.azure.toolkit.lib.common.entity.IAzureBaseResource; +import com.microsoft.azure.toolkit.lib.common.entity.IAzureModule; +import com.microsoft.azure.toolkit.lib.compute.AbstractAzureResource; +import com.microsoft.azure.toolkit.lib.compute.network.model.Subnet; +import lombok.EqualsAndHashCode; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.util.List; +import java.util.stream.Collectors; + +@EqualsAndHashCode(callSuper = true) +public class Network extends AbstractAzureResource { + protected AzureNetwork module; + + public Network(@Nonnull String id, @Nullable final AzureNetwork module) { + super(id); + this.module = module; + } + + public Network(@Nonnull final com.azure.resourcemanager.network.models.Network resource, @Nonnull final AzureNetwork module) { + super(resource); + this.module = module; + } + + public List subnets() { + return remote.subnets().values().stream().map(Subnet::new).collect(Collectors.toList()); + } + + @Override + public IAzureModule, + ? extends IAzureBaseResource> module() { + return module; + } + + @Nullable + @Override + protected com.azure.resourcemanager.network.models.Network loadRemote() { + return module.getNetworkManager(getSubscriptionId()).getByResourceGroup(getResourceGroup(), getName()); + } +} diff --git a/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/network/model/Subnet.java b/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/network/model/Subnet.java new file mode 100644 index 0000000000..574a977486 --- /dev/null +++ b/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/network/model/Subnet.java @@ -0,0 +1,25 @@ +/* + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + */ +package com.microsoft.azure.toolkit.lib.compute.network.model; + +import lombok.EqualsAndHashCode; +import lombok.Getter; + +@Getter +@EqualsAndHashCode +public class Subnet { + private final String name; + private final String addressSpace; + + public Subnet(String name, String addressSpace) { + this.name = name; + this.addressSpace = addressSpace; + } + + public Subnet(com.azure.resourcemanager.network.models.Subnet resource) { + this.name = resource.name(); + this.addressSpace = resource.addressPrefix(); + } +} From 571376ade5e992c6f836ba27ed338134db6473bf Mon Sep 17 00:00:00 2001 From: Hanxiao Liu Date: Sun, 12 Sep 2021 22:10:44 +0800 Subject: [PATCH 044/126] Add library for azure security group service --- .../security/AzureNetworkSecurityGroup.java | 52 +++++++++++++++++ .../security/DraftNetworkSecurityGroup.java | 56 +++++++++++++++++++ .../security/NetworkSecurityGroup.java | 42 ++++++++++++++ 3 files changed, 150 insertions(+) create mode 100644 azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/security/AzureNetworkSecurityGroup.java create mode 100644 azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/security/DraftNetworkSecurityGroup.java create mode 100644 azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/security/NetworkSecurityGroup.java diff --git a/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/security/AzureNetworkSecurityGroup.java b/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/security/AzureNetworkSecurityGroup.java new file mode 100644 index 0000000000..876b3fd0bc --- /dev/null +++ b/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/security/AzureNetworkSecurityGroup.java @@ -0,0 +1,52 @@ +/* + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + */ + +package com.microsoft.azure.toolkit.lib.compute.security; + +import com.azure.resourcemanager.compute.ComputeManager; +import com.azure.resourcemanager.network.models.NetworkSecurityGroups; +import com.microsoft.azure.toolkit.lib.common.model.Subscription; +import com.microsoft.azure.toolkit.lib.compute.AbstractAzureResourceModule; +import org.jetbrains.annotations.NotNull; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.util.List; +import java.util.stream.Collectors; + +public class AzureNetworkSecurityGroup extends AbstractAzureResourceModule { + public AzureNetworkSecurityGroup() { + super(AzureNetworkSecurityGroup::new); + } + + private AzureNetworkSecurityGroup(@Nullable List subscriptions) { + super(AzureNetworkSecurityGroup::new, subscriptions); + } + + @Override + public List list(@Nonnull String subscriptionId) { + return getSecurityGroupManager(subscriptionId).list().stream().map(group -> new NetworkSecurityGroup(group, this)).collect(Collectors.toList()); + } + + @NotNull + @Override + public NetworkSecurityGroup get(@Nonnull String subscriptionId, @Nonnull String resourceGroup, @Nonnull String name) { + final NetworkSecurityGroups securityGroupManager = getSecurityGroupManager(subscriptionId); + return new NetworkSecurityGroup(securityGroupManager.getByResourceGroup(resourceGroup, name), this); + } + + public NetworkSecurityGroup create(@Nonnull final DraftNetworkSecurityGroup draftNetworkSecurityGroup) { + return draftNetworkSecurityGroup.create(this); + } + + public NetworkSecurityGroups getSecurityGroupManager(final String subscriptionId) { + return getResourceManager(subscriptionId, ComputeManager::configure, ComputeManager.Configurable::authenticate).networkManager().networkSecurityGroups(); + } + + @Override + public String name() { + return "NetworkSecurityGroup"; + } +} diff --git a/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/security/DraftNetworkSecurityGroup.java b/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/security/DraftNetworkSecurityGroup.java new file mode 100644 index 0000000000..85f83098dc --- /dev/null +++ b/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/security/DraftNetworkSecurityGroup.java @@ -0,0 +1,56 @@ +/* + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + */ + +package com.microsoft.azure.toolkit.lib.compute.security; + +import com.azure.resourcemanager.network.models.NetworkSecurityGroup.DefinitionStages.WithCreate; +import com.microsoft.azure.toolkit.lib.common.entity.IAzureBaseResource; +import com.microsoft.azure.toolkit.lib.common.model.Region; +import com.microsoft.azure.toolkit.lib.compute.AzureResourceDraft; +import lombok.Getter; +import lombok.Setter; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.util.Optional; + +@Getter +@Setter +public class DraftNetworkSecurityGroup extends NetworkSecurityGroup implements AzureResourceDraft { + private String subscriptionId; + private String resourceGroup; + private String name; + private Region region; + + public DraftNetworkSecurityGroup(@Nonnull final String subscriptionId, @Nonnull final String resourceGroup, @Nonnull final String name) { + super(getResourceId(subscriptionId, resourceGroup, name), null); + } + + NetworkSecurityGroup create(final AzureNetworkSecurityGroup module) { + this.module = module; + WithCreate withCreate = module.getSecurityGroupManager(subscriptionId) + .define(name) + .withRegion(region.getName()) + .withExistingResourceGroup(resourceGroup); + this.remote = withCreate.create(); + refreshStatus(); + return this; + } + + @Override + protected String loadStatus() { + return Optional.ofNullable(module).map(ignore -> super.loadStatus()).orElse(IAzureBaseResource.Status.DRAFT); + } + + @Nullable + @Override + protected com.azure.resourcemanager.network.models.NetworkSecurityGroup loadRemote() { + return Optional.ofNullable(module).map(ignore -> super.loadRemote()).orElse(null); + } + + private static String getResourceId(@Nonnull final String subscriptionId, @Nonnull final String resourceGroup, @Nonnull final String name) { + return String.format("/subscriptions/%s/resourceGroups/%s/providers/Microsoft.Network/virtualNetworks/%s", subscriptionId, resourceGroup, name); + } +} diff --git a/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/security/NetworkSecurityGroup.java b/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/security/NetworkSecurityGroup.java new file mode 100644 index 0000000000..dbcda3b2f1 --- /dev/null +++ b/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/security/NetworkSecurityGroup.java @@ -0,0 +1,42 @@ +/* + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + */ + +package com.microsoft.azure.toolkit.lib.compute.security; + +import com.microsoft.azure.toolkit.lib.common.entity.IAzureBaseResource; +import com.microsoft.azure.toolkit.lib.common.entity.IAzureModule; +import com.microsoft.azure.toolkit.lib.compute.AbstractAzureResource; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + + +public class NetworkSecurityGroup extends AbstractAzureResource { + + protected AzureNetworkSecurityGroup module; + + public NetworkSecurityGroup(@Nonnull final String id, @Nullable final AzureNetworkSecurityGroup module) { + super(id); + this.module = module; + } + + public NetworkSecurityGroup(@Nonnull final com.azure.resourcemanager.network.models.NetworkSecurityGroup resource, + @Nonnull final AzureNetworkSecurityGroup module) { + super(resource); + this.module = module; + } + + @Override + public IAzureModule, + ? extends IAzureBaseResource> module() { + return module; + } + + @Nullable + @Override + protected com.azure.resourcemanager.network.models.NetworkSecurityGroup loadRemote() { + return module.getSecurityGroupManager(getSubscriptionId()).getByResourceGroup(getResourceGroup(), getName()); + } +} From caa89bb539f71b0048e7f1cccf5dd4304fa4396b Mon Sep 17 00:00:00 2001 From: andxu Date: Tue, 14 Sep 2021 13:19:39 +0800 Subject: [PATCH 045/126] add access tier during creating storage account --- .../toolkit/lib/storage/model/AccessTier.java | 20 +++++++++++++++++++ .../azure/toolkit/lib/storage/model/Kind.java | 3 ++- .../storage/model/StorageAccountConfig.java | 1 + .../storage/service/AzureStorageAccount.java | 8 ++++---- 4 files changed, 27 insertions(+), 5 deletions(-) create mode 100644 azure-toolkit-libs/azure-toolkit-storage-lib/src/main/java/com/microsoft/azure/toolkit/lib/storage/model/AccessTier.java diff --git a/azure-toolkit-libs/azure-toolkit-storage-lib/src/main/java/com/microsoft/azure/toolkit/lib/storage/model/AccessTier.java b/azure-toolkit-libs/azure-toolkit-storage-lib/src/main/java/com/microsoft/azure/toolkit/lib/storage/model/AccessTier.java new file mode 100644 index 0000000000..bf7e891667 --- /dev/null +++ b/azure-toolkit-libs/azure-toolkit-storage-lib/src/main/java/com/microsoft/azure/toolkit/lib/storage/model/AccessTier.java @@ -0,0 +1,20 @@ +/* + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + */ + +package com.microsoft.azure.toolkit.lib.storage.model; + +public enum AccessTier { + HOT("Hot"), + COOL("Cool"); + private final String value; + + AccessTier(String value) { + this.value = value; + } + + public String toString() { + return this.value; + } +} diff --git a/azure-toolkit-libs/azure-toolkit-storage-lib/src/main/java/com/microsoft/azure/toolkit/lib/storage/model/Kind.java b/azure-toolkit-libs/azure-toolkit-storage-lib/src/main/java/com/microsoft/azure/toolkit/lib/storage/model/Kind.java index 5f7c2ad015..c3ea408d87 100644 --- a/azure-toolkit-libs/azure-toolkit-storage-lib/src/main/java/com/microsoft/azure/toolkit/lib/storage/model/Kind.java +++ b/azure-toolkit-libs/azure-toolkit-storage-lib/src/main/java/com/microsoft/azure/toolkit/lib/storage/model/Kind.java @@ -25,7 +25,8 @@ public class Kind implements ExpandableParameter { public static final Kind FILE_STORAGE = new Kind(Performance.PREMIUM, "FileStorage", "File Storage"); public static final Kind PAGE_BLOB_STORAGE = new Kind(Performance.PREMIUM, "StorageV2", "Page Blobs Storage"); - private static final List values = new ImmutableList.Builder().add(STORAGE, STORAGE_V2, BLOCK_BLOB_STORAGE, FILE_STORAGE, PAGE_BLOB_STORAGE).build(); + private static final List values = new ImmutableList.Builder().add(STORAGE, STORAGE_V2, + BLOCK_BLOB_STORAGE, FILE_STORAGE, PAGE_BLOB_STORAGE).build(); private final Performance performance; private final String name; diff --git a/azure-toolkit-libs/azure-toolkit-storage-lib/src/main/java/com/microsoft/azure/toolkit/lib/storage/model/StorageAccountConfig.java b/azure-toolkit-libs/azure-toolkit-storage-lib/src/main/java/com/microsoft/azure/toolkit/lib/storage/model/StorageAccountConfig.java index 31524a64da..453c3228be 100644 --- a/azure-toolkit-libs/azure-toolkit-storage-lib/src/main/java/com/microsoft/azure/toolkit/lib/storage/model/StorageAccountConfig.java +++ b/azure-toolkit-libs/azure-toolkit-storage-lib/src/main/java/com/microsoft/azure/toolkit/lib/storage/model/StorageAccountConfig.java @@ -28,6 +28,7 @@ public class StorageAccountConfig implements IStorageAccountEntity { private Performance performance; private Kind kind; private Redundancy redundancy; + private AccessTier accessTier; @Override public String getSubscriptionId() { diff --git a/azure-toolkit-libs/azure-toolkit-storage-lib/src/main/java/com/microsoft/azure/toolkit/lib/storage/service/AzureStorageAccount.java b/azure-toolkit-libs/azure-toolkit-storage-lib/src/main/java/com/microsoft/azure/toolkit/lib/storage/service/AzureStorageAccount.java index 5d254e537d..05ec2dd47b 100644 --- a/azure-toolkit-libs/azure-toolkit-storage-lib/src/main/java/com/microsoft/azure/toolkit/lib/storage/service/AzureStorageAccount.java +++ b/azure-toolkit-libs/azure-toolkit-storage-lib/src/main/java/com/microsoft/azure/toolkit/lib/storage/service/AzureStorageAccount.java @@ -7,10 +7,7 @@ import com.azure.resourcemanager.resources.fluentcore.arm.ResourceId; import com.azure.resourcemanager.storage.StorageManager; -import com.azure.resourcemanager.storage.models.CheckNameAvailabilityResult; -import com.azure.resourcemanager.storage.models.Reason; -import com.azure.resourcemanager.storage.models.SkuName; -import com.azure.resourcemanager.storage.models.StorageAccountSkuType; +import com.azure.resourcemanager.storage.models.*; import com.microsoft.azure.toolkit.lib.AzureService; import com.microsoft.azure.toolkit.lib.SubscriptionScoped; import com.microsoft.azure.toolkit.lib.common.cache.CacheEvict; @@ -129,6 +126,9 @@ public StorageAccount commit() { withCreate = withCreate.withFileStorageAccountKind(); } else if (Objects.equals(Kind.BLOCK_BLOB_STORAGE, config.getKind())) { withCreate = withCreate.withBlockBlobStorageAccountKind(); + } else if (Objects.equals(Kind.BLOB_STORAGE, config.getKind())) { + withCreate = withCreate.withBlobStorageAccountKind().withAccessTier( + Optional.ofNullable(config.getAccessTier()).map(t -> AccessTier.fromString(t.toString())).orElse(null)); } else { withCreate = withCreate.withGeneralPurposeAccountKindV2(); } From 55ed98d3484c7e1a0c3e009970c8264b9155783b Mon Sep 17 00:00:00 2001 From: Hanxiao Liu Date: Tue, 14 Sep 2021 21:39:58 +0800 Subject: [PATCH 046/126] Support create network security group with customized rules --- .../security/AzureNetworkSecurityGroup.java | 6 ++- .../security/DraftNetworkSecurityGroup.java | 46 +++++++++++++++--- .../security/NetworkSecurityGroup.java | 5 +- .../compute/security/model/SecurityRule.java | 47 +++++++++++++++++++ 4 files changed, 95 insertions(+), 9 deletions(-) create mode 100644 azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/security/model/SecurityRule.java diff --git a/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/security/AzureNetworkSecurityGroup.java b/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/security/AzureNetworkSecurityGroup.java index 876b3fd0bc..019c576980 100644 --- a/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/security/AzureNetworkSecurityGroup.java +++ b/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/security/AzureNetworkSecurityGroup.java @@ -7,6 +7,7 @@ import com.azure.resourcemanager.compute.ComputeManager; import com.azure.resourcemanager.network.models.NetworkSecurityGroups; +import com.microsoft.azure.toolkit.lib.common.event.AzureOperationEvent; import com.microsoft.azure.toolkit.lib.common.model.Subscription; import com.microsoft.azure.toolkit.lib.compute.AbstractAzureResourceModule; import org.jetbrains.annotations.NotNull; @@ -16,7 +17,8 @@ import java.util.List; import java.util.stream.Collectors; -public class AzureNetworkSecurityGroup extends AbstractAzureResourceModule { +public class AzureNetworkSecurityGroup extends AbstractAzureResourceModule + implements AzureOperationEvent.Source { public AzureNetworkSecurityGroup() { super(AzureNetworkSecurityGroup::new); } @@ -41,7 +43,7 @@ public NetworkSecurityGroup create(@Nonnull final DraftNetworkSecurityGroup draf return draftNetworkSecurityGroup.create(this); } - public NetworkSecurityGroups getSecurityGroupManager(final String subscriptionId) { + NetworkSecurityGroups getSecurityGroupManager(final String subscriptionId) { return getResourceManager(subscriptionId, ComputeManager::configure, ComputeManager.Configurable::authenticate).networkManager().networkSecurityGroups(); } diff --git a/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/security/DraftNetworkSecurityGroup.java b/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/security/DraftNetworkSecurityGroup.java index 85f83098dc..bb00ab32cc 100644 --- a/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/security/DraftNetworkSecurityGroup.java +++ b/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/security/DraftNetworkSecurityGroup.java @@ -6,23 +6,32 @@ package com.microsoft.azure.toolkit.lib.compute.security; import com.azure.resourcemanager.network.models.NetworkSecurityGroup.DefinitionStages.WithCreate; +import com.azure.resourcemanager.network.models.NetworkSecurityRule; +import com.azure.resourcemanager.network.models.NetworkSecurityRule.DefinitionStages.WithDestinationAddressOrSecurityGroup; +import com.azure.resourcemanager.network.models.NetworkSecurityRule.DefinitionStages.WithSourceAddressOrSecurityGroup; +import com.azure.resourcemanager.network.models.NetworkSecurityRule.DefinitionStages.WithSourcePort; +import com.azure.resourcemanager.network.models.SecurityRuleProtocol; import com.microsoft.azure.toolkit.lib.common.entity.IAzureBaseResource; import com.microsoft.azure.toolkit.lib.common.model.Region; import com.microsoft.azure.toolkit.lib.compute.AzureResourceDraft; +import com.microsoft.azure.toolkit.lib.compute.security.model.SecurityRule; +import io.jsonwebtoken.lang.Collections; import lombok.Getter; import lombok.Setter; import javax.annotation.Nonnull; import javax.annotation.Nullable; +import java.util.List; import java.util.Optional; @Getter @Setter public class DraftNetworkSecurityGroup extends NetworkSecurityGroup implements AzureResourceDraft { - private String subscriptionId; - private String resourceGroup; - private String name; + private static final int BASE_PRIORITY = 300; + private static final int PRIORITY_STEP = 20; + private Region region; + private List securityRuleList; public DraftNetworkSecurityGroup(@Nonnull final String subscriptionId, @Nonnull final String resourceGroup, @Nonnull final String name) { super(getResourceId(subscriptionId, resourceGroup, name), null); @@ -34,23 +43,48 @@ NetworkSecurityGroup create(final AzureNetworkSecurityGroup module) { .define(name) .withRegion(region.getName()) .withExistingResourceGroup(resourceGroup); + if (!Collections.isEmpty(securityRuleList)) { + applySecurityRule(withCreate, securityRuleList); + } this.remote = withCreate.create(); refreshStatus(); + module.refresh(); return this; } + private static void applySecurityRule(WithCreate withCreate, List securityRuleList) { + for (int priority = BASE_PRIORITY, count = 0; count < securityRuleList.size(); count++, priority += PRIORITY_STEP) { + applySecurityRule(withCreate, securityRuleList.get(count), priority); + } + } + + private static void applySecurityRule(final WithCreate withCreate, final SecurityRule securityRule, final int priority) { + final WithSourceAddressOrSecurityGroup withSource = withCreate.defineRule(securityRule.getName()).allowInbound(); + final WithSourcePort withSourcePort = securityRule.getFromAddresses() != null ? + withSource.fromAddresses(securityRule.getFromAddresses()) : withSource.fromAnyAddress(); + final WithDestinationAddressOrSecurityGroup withDestination = securityRule.getFromPort() != null ? + withSourcePort.fromPort(securityRule.getFromPort()) : withSourcePort.fromAnyPort(); + final NetworkSecurityRule.DefinitionStages.WithDestinationPort withDestPort = securityRule.getToAddresses() != null ? + withDestination.toAddresses(securityRule.getToAddresses()) : withDestination.toAnyAddress(); + final NetworkSecurityRule.DefinitionStages.WithProtocol withProtocol = securityRule.getToPort() != null ? + withDestPort.toPort(securityRule.getToPort()) : withDestPort.toAnyPort(); + final NetworkSecurityRule.DefinitionStages.WithAttach withAttach = securityRule.getProtocol() == SecurityRule.Protocol.ALL ? + withProtocol.withAnyProtocol() : withProtocol.withProtocol(SecurityRuleProtocol.fromString(securityRule.getProtocol().name())); + withAttach.withPriority(priority).attach(); + } + @Override protected String loadStatus() { - return Optional.ofNullable(module).map(ignore -> super.loadStatus()).orElse(IAzureBaseResource.Status.DRAFT); + return Optional.ofNullable(remote).map(ignore -> super.loadStatus()).orElse(IAzureBaseResource.Status.DRAFT); } @Nullable @Override protected com.azure.resourcemanager.network.models.NetworkSecurityGroup loadRemote() { - return Optional.ofNullable(module).map(ignore -> super.loadRemote()).orElse(null); + return Optional.ofNullable(remote).map(ignore -> super.loadRemote()).orElse(null); } private static String getResourceId(@Nonnull final String subscriptionId, @Nonnull final String resourceGroup, @Nonnull final String name) { - return String.format("/subscriptions/%s/resourceGroups/%s/providers/Microsoft.Network/virtualNetworks/%s", subscriptionId, resourceGroup, name); + return String.format("/subscriptions/%s/resourceGroups/%s/providers/Microsoft.Network/networkSecurityGroups/%s", subscriptionId, resourceGroup, name); } } diff --git a/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/security/NetworkSecurityGroup.java b/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/security/NetworkSecurityGroup.java index dbcda3b2f1..9ba51ed284 100644 --- a/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/security/NetworkSecurityGroup.java +++ b/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/security/NetworkSecurityGroup.java @@ -7,13 +7,16 @@ import com.microsoft.azure.toolkit.lib.common.entity.IAzureBaseResource; import com.microsoft.azure.toolkit.lib.common.entity.IAzureModule; +import com.microsoft.azure.toolkit.lib.common.event.AzureOperationEvent; import com.microsoft.azure.toolkit.lib.compute.AbstractAzureResource; +import com.microsoft.azure.toolkit.lib.compute.vm.VirtualMachine; import javax.annotation.Nonnull; import javax.annotation.Nullable; -public class NetworkSecurityGroup extends AbstractAzureResource { +public class NetworkSecurityGroup extends AbstractAzureResource + implements AzureOperationEvent.Source { protected AzureNetworkSecurityGroup module; diff --git a/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/security/model/SecurityRule.java b/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/security/model/SecurityRule.java new file mode 100644 index 0000000000..e6db84cc69 --- /dev/null +++ b/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/security/model/SecurityRule.java @@ -0,0 +1,47 @@ +/* + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + */ + +package com.microsoft.azure.toolkit.lib.compute.security.model; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.Setter; + +@Getter +@Setter +@Builder() +@EqualsAndHashCode() +public class SecurityRule { + public static final SecurityRule SSH_RULE = SecurityRule.builder().name("SSH") + .toPort(22).protocol(Protocol.TCP).build(); + public static final SecurityRule HTTP_RULE = SecurityRule.builder().name("HTTP") + .toPort(80).protocol(Protocol.TCP).build(); + public static final SecurityRule HTTPS_RULE = SecurityRule.builder().name("HTTPS") + .toPort(443).protocol(Protocol.TCP).build(); + public static final SecurityRule RDP_RULE = SecurityRule.builder().name("RDP") + .toPort(3389).protocol(Protocol.TCP).build(); + + private String name; + private String[] fromAddresses; + private Integer fromPort; + private String[] toAddresses; + private Integer toPort; + private Protocol protocol; + + @AllArgsConstructor + public enum Protocol { + TCP("Tcp"), + UDP("Udp"), + ICMP("Icmp"), + ESP("Esp"), + ASTERISK("*"), + AH("Ah"), + ALL("all"); + + private String value; + } +} From 0ed3ce2a26f0ae3e2569978b035b5f6ac3cb20be Mon Sep 17 00:00:00 2001 From: Hanxiao Liu Date: Tue, 14 Sep 2021 21:41:07 +0800 Subject: [PATCH 047/126] Resolve comments and fix issues for vm creation --- .../toolkit/lib/compute/ip/AzurePublicIpAddress.java | 5 +++-- .../toolkit/lib/compute/ip/DraftPublicIpAddress.java | 7 ++++--- .../azure/toolkit/lib/compute/ip/PublicIpAddress.java | 5 ++++- .../toolkit/lib/compute/network/AzureNetwork.java | 5 +++-- .../toolkit/lib/compute/network/DraftNetwork.java | 10 ++++------ .../azure/toolkit/lib/compute/network/Network.java | 5 ++++- 6 files changed, 22 insertions(+), 15 deletions(-) diff --git a/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/ip/AzurePublicIpAddress.java b/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/ip/AzurePublicIpAddress.java index 3d1a0a0a72..c5fabd769d 100644 --- a/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/ip/AzurePublicIpAddress.java +++ b/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/ip/AzurePublicIpAddress.java @@ -7,6 +7,7 @@ import com.azure.resourcemanager.compute.ComputeManager; import com.azure.resourcemanager.network.models.PublicIpAddresses; +import com.microsoft.azure.toolkit.lib.common.event.AzureOperationEvent; import com.microsoft.azure.toolkit.lib.common.model.Subscription; import com.microsoft.azure.toolkit.lib.compute.AbstractAzureResourceModule; @@ -14,7 +15,7 @@ import java.util.List; import java.util.stream.Collectors; -public class AzurePublicIpAddress extends AbstractAzureResourceModule { +public class AzurePublicIpAddress extends AbstractAzureResourceModule implements AzureOperationEvent.Source { public AzurePublicIpAddress() { super(AzurePublicIpAddress::new); @@ -40,7 +41,7 @@ public PublicIpAddress create(@Nonnull final DraftPublicIpAddress draftPublicIpA return draftPublicIpAddress.create(this); } - public PublicIpAddresses getPublicIpAddressManager(String subscriptionId) { + PublicIpAddresses getPublicIpAddressManager(String subscriptionId) { return getResourceManager(subscriptionId, ComputeManager::configure, ComputeManager.Configurable::authenticate).networkManager().publicIpAddresses(); } diff --git a/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/ip/DraftPublicIpAddress.java b/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/ip/DraftPublicIpAddress.java index 9b04e5ab60..6db3d446aa 100644 --- a/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/ip/DraftPublicIpAddress.java +++ b/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/ip/DraftPublicIpAddress.java @@ -28,24 +28,25 @@ public DraftPublicIpAddress(@Nonnull final String subscriptionId, @Nonnull final PublicIpAddress create(AzurePublicIpAddress module) { this.module = module; - module.getPublicIpAddressManager(subscriptionId).define(name) + this.remote = module.getPublicIpAddressManager(subscriptionId).define(name) .withRegion(region.getName()) .withExistingResourceGroup(resourceGroup) .withLeafDomainLabel(leafDomainLabel) .create(); refreshStatus(); + module.refresh(); return this; } @Override protected String loadStatus() { - return Optional.ofNullable(module).map(ignore -> super.loadStatus()).orElse(Status.DRAFT); + return Optional.ofNullable(remote).map(ignore -> super.loadStatus()).orElse(Status.DRAFT); } @Nullable @Override protected com.azure.resourcemanager.network.models.PublicIpAddress loadRemote() { - return Optional.ofNullable(module).map(ignore -> super.loadRemote()).orElse(null); + return Optional.ofNullable(remote).map(ignore -> super.loadRemote()).orElse(null); } private static String getResourceId(@Nonnull final String subscriptionId, @Nonnull final String resourceGroup, @Nonnull final String name) { diff --git a/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/ip/PublicIpAddress.java b/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/ip/PublicIpAddress.java index 2df1e50460..3b5e669bf5 100644 --- a/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/ip/PublicIpAddress.java +++ b/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/ip/PublicIpAddress.java @@ -7,14 +7,17 @@ import com.microsoft.azure.toolkit.lib.common.entity.IAzureBaseResource; import com.microsoft.azure.toolkit.lib.common.entity.IAzureModule; +import com.microsoft.azure.toolkit.lib.common.event.AzureOperationEvent; import com.microsoft.azure.toolkit.lib.compute.AbstractAzureResource; +import com.microsoft.azure.toolkit.lib.compute.vm.VirtualMachine; import lombok.EqualsAndHashCode; import javax.annotation.Nonnull; import javax.annotation.Nullable; @EqualsAndHashCode(callSuper = true) -public class PublicIpAddress extends AbstractAzureResource { +public class PublicIpAddress extends AbstractAzureResource + implements AzureOperationEvent.Source { protected AzurePublicIpAddress module; diff --git a/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/network/AzureNetwork.java b/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/network/AzureNetwork.java index f6ec9053a7..ec2a01c13f 100644 --- a/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/network/AzureNetwork.java +++ b/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/network/AzureNetwork.java @@ -7,6 +7,7 @@ import com.azure.resourcemanager.compute.ComputeManager; import com.azure.resourcemanager.network.models.Networks; +import com.microsoft.azure.toolkit.lib.common.event.AzureOperationEvent; import com.microsoft.azure.toolkit.lib.common.model.Subscription; import com.microsoft.azure.toolkit.lib.compute.AbstractAzureResourceModule; @@ -14,7 +15,7 @@ import java.util.List; import java.util.stream.Collectors; -public class AzureNetwork extends AbstractAzureResourceModule { +public class AzureNetwork extends AbstractAzureResourceModule implements AzureOperationEvent.Source { public AzureNetwork() { super(AzureNetwork::new); } @@ -39,7 +40,7 @@ public Network create(@Nonnull final DraftNetwork draftNetwork) { return draftNetwork.create(this); } - public Networks getNetworkManager(@Nonnull final String subscriptionId) { + Networks getNetworkManager(@Nonnull final String subscriptionId) { return getResourceManager(subscriptionId, ComputeManager::configure, ComputeManager.Configurable::authenticate).networkManager().networks(); } diff --git a/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/network/DraftNetwork.java b/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/network/DraftNetwork.java index 4c2b357638..a301e97ed9 100644 --- a/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/network/DraftNetwork.java +++ b/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/network/DraftNetwork.java @@ -25,9 +25,6 @@ @EqualsAndHashCode(callSuper = true) public class DraftNetwork extends Network implements AzureResourceDraft { - private String subscriptionId; - private String resourceGroup; - private String name; private Region region; private String addressSpace; @@ -49,23 +46,24 @@ Network create(final AzureNetwork module) { } this.remote = withCreateAndSubnet.create(); refreshStatus(); + module.refresh(); return this; } @Override public List subnets() { - return Optional.ofNullable(module).map(ignore -> super.subnets()).orElseGet(() -> Collections.singletonList(new Subnet(subnet, subnetAddressSpace))); + return Optional.ofNullable(remote).map(ignore -> super.subnets()).orElseGet(() -> Collections.singletonList(new Subnet(subnet, subnetAddressSpace))); } @Override protected String loadStatus() { - return Optional.ofNullable(module).map(ignore -> super.loadStatus()).orElse(Status.DRAFT); + return Optional.ofNullable(remote).map(ignore -> super.loadStatus()).orElse(Status.DRAFT); } @Nullable @Override protected com.azure.resourcemanager.network.models.Network loadRemote() { - return Optional.ofNullable(module).map(ignore -> super.loadRemote()).orElse(null); + return Optional.ofNullable(remote).map(ignore -> super.loadRemote()).orElse(null); } private static String getResourceId(@Nonnull final String subscriptionId, @Nonnull final String resourceGroup, @Nonnull final String name) { diff --git a/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/network/Network.java b/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/network/Network.java index 0e75635492..81c102c9b9 100644 --- a/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/network/Network.java +++ b/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/network/Network.java @@ -7,8 +7,10 @@ import com.microsoft.azure.toolkit.lib.common.entity.IAzureBaseResource; import com.microsoft.azure.toolkit.lib.common.entity.IAzureModule; +import com.microsoft.azure.toolkit.lib.common.event.AzureOperationEvent; import com.microsoft.azure.toolkit.lib.compute.AbstractAzureResource; import com.microsoft.azure.toolkit.lib.compute.network.model.Subnet; +import com.microsoft.azure.toolkit.lib.compute.vm.VirtualMachine; import lombok.EqualsAndHashCode; import javax.annotation.Nonnull; @@ -17,7 +19,8 @@ import java.util.stream.Collectors; @EqualsAndHashCode(callSuper = true) -public class Network extends AbstractAzureResource { +public class Network extends AbstractAzureResource + implements AzureOperationEvent.Source{ protected AzureNetwork module; public Network(@Nonnull String id, @Nullable final AzureNetwork module) { From 33e62afc8273fb75c6925c639bca5de0f1b3dc30 Mon Sep 17 00:00:00 2001 From: Hanxiao Liu Date: Tue, 14 Sep 2021 21:48:14 +0800 Subject: [PATCH 048/126] Resolve checkstyle issues --- .../azure/toolkit/lib/compute/ip/PublicIpAddress.java | 1 - .../microsoft/azure/toolkit/lib/compute/network/Network.java | 3 +-- .../toolkit/lib/compute/security/NetworkSecurityGroup.java | 1 - 3 files changed, 1 insertion(+), 4 deletions(-) diff --git a/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/ip/PublicIpAddress.java b/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/ip/PublicIpAddress.java index 3b5e669bf5..cd52d8973f 100644 --- a/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/ip/PublicIpAddress.java +++ b/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/ip/PublicIpAddress.java @@ -9,7 +9,6 @@ import com.microsoft.azure.toolkit.lib.common.entity.IAzureModule; import com.microsoft.azure.toolkit.lib.common.event.AzureOperationEvent; import com.microsoft.azure.toolkit.lib.compute.AbstractAzureResource; -import com.microsoft.azure.toolkit.lib.compute.vm.VirtualMachine; import lombok.EqualsAndHashCode; import javax.annotation.Nonnull; diff --git a/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/network/Network.java b/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/network/Network.java index 81c102c9b9..d70dc6cf4b 100644 --- a/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/network/Network.java +++ b/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/network/Network.java @@ -10,7 +10,6 @@ import com.microsoft.azure.toolkit.lib.common.event.AzureOperationEvent; import com.microsoft.azure.toolkit.lib.compute.AbstractAzureResource; import com.microsoft.azure.toolkit.lib.compute.network.model.Subnet; -import com.microsoft.azure.toolkit.lib.compute.vm.VirtualMachine; import lombok.EqualsAndHashCode; import javax.annotation.Nonnull; @@ -20,7 +19,7 @@ @EqualsAndHashCode(callSuper = true) public class Network extends AbstractAzureResource - implements AzureOperationEvent.Source{ + implements AzureOperationEvent.Source { protected AzureNetwork module; public Network(@Nonnull String id, @Nullable final AzureNetwork module) { diff --git a/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/security/NetworkSecurityGroup.java b/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/security/NetworkSecurityGroup.java index 9ba51ed284..b1b3571b05 100644 --- a/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/security/NetworkSecurityGroup.java +++ b/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/security/NetworkSecurityGroup.java @@ -9,7 +9,6 @@ import com.microsoft.azure.toolkit.lib.common.entity.IAzureModule; import com.microsoft.azure.toolkit.lib.common.event.AzureOperationEvent; import com.microsoft.azure.toolkit.lib.compute.AbstractAzureResource; -import com.microsoft.azure.toolkit.lib.compute.vm.VirtualMachine; import javax.annotation.Nonnull; import javax.annotation.Nullable; From ca329ec93fa4964cffdd02f7dd9715bca5036c51 Mon Sep 17 00:00:00 2001 From: Hanxiao Liu Date: Tue, 14 Sep 2021 21:54:37 +0800 Subject: [PATCH 049/126] Add library for Azure virtual machine service --- .../azure-toolkit-compute-lib/pom.xml | 8 ++ .../toolkit/lib/compute/vm/AzureImage.java | 62 +++++++++ .../lib/compute/vm/AzureImageOffer.java | 37 +++++ .../lib/compute/vm/AzureImagePublisher.java | 33 +++++ .../toolkit/lib/compute/vm/AzureImageSku.java | 37 +++++ .../lib/compute/vm/AzureVirtualMachine.java | 116 ++++++++++++++++ .../compute/vm/AzureVirtualMachineSize.java | 24 ++++ .../lib/compute/vm/DraftVirtualMachine.java | 128 ++++++++++++++++++ .../lib/compute/vm/VirtualMachine.java | 89 ++++++++++++ .../compute/vm/model/AuthenticationType.java | 10 ++ .../lib/compute/vm/model/AzureSpotConfig.java | 27 ++++ .../lib/compute/vm/model/OperatingSystem.java | 20 +++ .../vm/task/CreateVirtualMachineTask.java | 75 ++++++++++ ...m.microsoft.azure.toolkit.lib.AzureService | 4 + azure-toolkit-libs/pom.xml | 5 + 15 files changed, 675 insertions(+) create mode 100644 azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/vm/AzureImage.java create mode 100644 azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/vm/AzureImageOffer.java create mode 100644 azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/vm/AzureImagePublisher.java create mode 100644 azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/vm/AzureImageSku.java create mode 100644 azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/vm/AzureVirtualMachine.java create mode 100644 azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/vm/AzureVirtualMachineSize.java create mode 100644 azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/vm/DraftVirtualMachine.java create mode 100644 azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/vm/VirtualMachine.java create mode 100644 azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/vm/model/AuthenticationType.java create mode 100644 azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/vm/model/AzureSpotConfig.java create mode 100644 azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/vm/model/OperatingSystem.java create mode 100644 azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/vm/task/CreateVirtualMachineTask.java create mode 100644 azure-toolkit-libs/azure-toolkit-compute-lib/src/main/resources/META-INF/services/com.microsoft.azure.toolkit.lib.AzureService diff --git a/azure-toolkit-libs/azure-toolkit-compute-lib/pom.xml b/azure-toolkit-libs/azure-toolkit-compute-lib/pom.xml index d3bda02402..321729b10d 100644 --- a/azure-toolkit-libs/azure-toolkit-compute-lib/pom.xml +++ b/azure-toolkit-libs/azure-toolkit-compute-lib/pom.xml @@ -108,6 +108,14 @@ com.microsoft.azure azure-toolkit-common-lib + + com.microsoft.azure + azure-toolkit-storage-lib + + + com.microsoft.azure + azure-toolkit-resource-lib + \ No newline at end of file diff --git a/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/vm/AzureImage.java b/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/vm/AzureImage.java new file mode 100644 index 0000000000..6586d34823 --- /dev/null +++ b/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/vm/AzureImage.java @@ -0,0 +1,62 @@ +/* + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + */ + +package com.microsoft.azure.toolkit.lib.compute.vm; + +import com.azure.resourcemanager.compute.models.ImageReference; +import com.azure.resourcemanager.compute.models.KnownLinuxVirtualMachineImage; +import com.azure.resourcemanager.compute.models.KnownWindowsVirtualMachineImage; +import com.azure.resourcemanager.compute.models.VirtualMachineImage; +import com.microsoft.azure.toolkit.lib.compute.vm.model.OperatingSystem; +import lombok.AccessLevel; +import lombok.EqualsAndHashCode; +import lombok.Getter; + +import javax.annotation.Nonnull; + +@EqualsAndHashCode +public class AzureImage { + @Nonnull + @Getter(value = AccessLevel.PACKAGE) + private final ImageReference imageReference; + @Nonnull + @Getter + private final OperatingSystem operatingSystem; + + AzureImage(@Nonnull VirtualMachineImage virtualMachineImage) { + this.operatingSystem = OperatingSystem.fromString(virtualMachineImage.osDiskImage().operatingSystem().name()); + this.imageReference = virtualMachineImage.imageReference(); + } + + public AzureImage(@Nonnull KnownWindowsVirtualMachineImage windowsVirtualMachineImage) { + this.operatingSystem = OperatingSystem.Windows; + this.imageReference = windowsVirtualMachineImage.imageReference(); + } + + AzureImage(@Nonnull KnownLinuxVirtualMachineImage linuxVirtualMachineImage) { + this.operatingSystem = OperatingSystem.Linux; + this.imageReference = linuxVirtualMachineImage.imageReference(); + } + + public String id() { + return imageReference.id(); + } + + public String publisherName() { + return imageReference.publisher(); + } + + public String offer() { + return imageReference.offer(); + } + + public String sku() { + return imageReference.sku(); + } + + public String version() { + return imageReference.version(); + } +} diff --git a/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/vm/AzureImageOffer.java b/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/vm/AzureImageOffer.java new file mode 100644 index 0000000000..d3dfb45fe2 --- /dev/null +++ b/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/vm/AzureImageOffer.java @@ -0,0 +1,37 @@ +/* + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + */ + +package com.microsoft.azure.toolkit.lib.compute.vm; + +import com.azure.resourcemanager.compute.models.VirtualMachineOffer; +import com.microsoft.azure.toolkit.lib.common.model.Region; +import lombok.Getter; + +import javax.annotation.Nonnull; +import java.util.List; +import java.util.stream.Collectors; + +public class AzureImageOffer { + @Getter + private final AzureImagePublisher publisher; + private final VirtualMachineOffer virtualMachineOffer; + + AzureImageOffer(@Nonnull AzureImagePublisher publisher, @Nonnull VirtualMachineOffer virtualMachineOffer) { + this.publisher = publisher; + this.virtualMachineOffer = virtualMachineOffer; + } + + public String name() { + return virtualMachineOffer.name(); + } + + public Region region() { + return Region.fromName(virtualMachineOffer.region().name()); + } + + public List skus() { + return virtualMachineOffer.skus().list().stream().map(sku -> new AzureImageSku(this, sku)).collect(Collectors.toList()); + } +} diff --git a/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/vm/AzureImagePublisher.java b/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/vm/AzureImagePublisher.java new file mode 100644 index 0000000000..07f7f5a26c --- /dev/null +++ b/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/vm/AzureImagePublisher.java @@ -0,0 +1,33 @@ +/* + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + */ + +package com.microsoft.azure.toolkit.lib.compute.vm; + +import com.azure.resourcemanager.compute.models.VirtualMachinePublisher; +import com.microsoft.azure.toolkit.lib.common.model.Region; + +import javax.annotation.Nonnull; +import java.util.List; +import java.util.stream.Collectors; + +public class AzureImagePublisher { + private final VirtualMachinePublisher virtualMachinePublisher; + + AzureImagePublisher(@Nonnull VirtualMachinePublisher virtualMachinePublisher) { + this.virtualMachinePublisher = virtualMachinePublisher; + } + + public String name() { + return virtualMachinePublisher.name(); + } + + public Region region() { + return Region.fromName(virtualMachinePublisher.region().name()); + } + + public List offers() { + return virtualMachinePublisher.offers().list().stream().map(offer -> new AzureImageOffer(this, offer)).collect(Collectors.toList()); + } +} diff --git a/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/vm/AzureImageSku.java b/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/vm/AzureImageSku.java new file mode 100644 index 0000000000..43566a8ff0 --- /dev/null +++ b/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/vm/AzureImageSku.java @@ -0,0 +1,37 @@ +/* + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + */ + +package com.microsoft.azure.toolkit.lib.compute.vm; + +import com.azure.resourcemanager.compute.models.VirtualMachineSku; +import com.microsoft.azure.toolkit.lib.common.model.Region; +import lombok.Getter; + +import javax.annotation.Nonnull; +import java.util.List; +import java.util.stream.Collectors; + +public class AzureImageSku { + @Getter + private final AzureImageOffer publisher; + private final VirtualMachineSku virtualMachineSku; + + AzureImageSku(@Nonnull AzureImageOffer imageOffer, @Nonnull VirtualMachineSku virtualMachineSku) { + this.publisher = imageOffer; + this.virtualMachineSku = virtualMachineSku; + } + + public String name() { + return virtualMachineSku.name(); + } + + public Region region() { + return Region.fromName(virtualMachineSku.region().name()); + } + + public List images() { + return virtualMachineSku.images().list().stream().map(AzureImage::new).collect(Collectors.toList()); + } +} diff --git a/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/vm/AzureVirtualMachine.java b/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/vm/AzureVirtualMachine.java new file mode 100644 index 0000000000..f433092dfe --- /dev/null +++ b/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/vm/AzureVirtualMachine.java @@ -0,0 +1,116 @@ +/* + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + */ + +package com.microsoft.azure.toolkit.lib.compute.vm; + +import com.azure.resourcemanager.compute.ComputeManager; +import com.azure.resourcemanager.compute.models.AvailabilitySet; +import com.azure.resourcemanager.compute.models.ComputeResourceType; +import com.azure.resourcemanager.compute.models.KnownLinuxVirtualMachineImage; +import com.azure.resourcemanager.compute.models.KnownWindowsVirtualMachineImage; +import com.azure.resourcemanager.compute.models.VirtualMachines; +import com.microsoft.azure.toolkit.lib.common.cache.CacheEvict; +import com.microsoft.azure.toolkit.lib.common.cache.CacheManager; +import com.microsoft.azure.toolkit.lib.common.cache.Cacheable; +import com.microsoft.azure.toolkit.lib.common.event.AzureOperationEvent; +import com.microsoft.azure.toolkit.lib.common.model.Region; +import com.microsoft.azure.toolkit.lib.common.model.Subscription; +import com.microsoft.azure.toolkit.lib.common.operation.AzureOperation; +import com.microsoft.azure.toolkit.lib.compute.AbstractAzureResourceModule; +import lombok.extern.slf4j.Slf4j; + +import javax.annotation.Nonnull; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.concurrent.ExecutionException; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +@Slf4j +public class AzureVirtualMachine extends AbstractAzureResourceModule implements AzureOperationEvent.Source { + + private static final List linuxImages = + Arrays.stream(KnownLinuxVirtualMachineImage.values()).map(AzureImage::new).collect(Collectors.toList()); + private static final List windowsImages = + Arrays.stream(KnownWindowsVirtualMachineImage.values()).map(AzureImage::new).collect(Collectors.toList()); + private static final List images = + Collections.unmodifiableList(Stream.of(linuxImages, windowsImages).flatMap(List::stream).collect(Collectors.toList())); + + public AzureVirtualMachine() { // for SPI + super(AzureVirtualMachine::new); + } + + private AzureVirtualMachine(@Nonnull final List subscriptions) { + super(AzureVirtualMachine::new, subscriptions); + } + + @Cacheable(cacheName = "compute/{}/vm", key = "$subscriptionId") + public List list(@Nonnull final String subscriptionId) { + final VirtualMachines virtualMachines = getVirtualMachinesManager(subscriptionId); + return virtualMachines.list().stream() + .map(vm -> new VirtualMachine(vm, this)).collect(Collectors.toList()); + } + + @Nonnull + public VirtualMachine get(@Nonnull final String subscriptionId, @Nonnull final String resourceGroup, @Nonnull final String name) { + final VirtualMachines virtualMachinesManager = getVirtualMachinesManager(subscriptionId); + return new VirtualMachine(virtualMachinesManager.getByResourceGroup(resourceGroup, name), this); + } + + public List availabilitySets() { + return availabilitySets(getDefaultSubscription().getId()); + } + + public List availabilitySets(@Nonnull final String subscriptionId) { + return getVirtualMachinesManager(subscriptionId).manager().availabilitySets().list().stream().map(AvailabilitySet::name).collect(Collectors.toList()); + } + + public List publishers(final Region region) { + return publishers(getDefaultSubscription().getId(), region); + } + + public List publishers(final String subscriptionId, final Region region) { + return getVirtualMachinesManager(subscriptionId).manager().virtualMachineImages() + .publishers().listByRegion(region.getName()).stream().map(AzureImagePublisher::new).collect(Collectors.toList()); + } + + public List listPricing(final Region region) { + return listPricing(getDefaultSubscription().getId(), region); + } + + public List listPricing(final String subscriptionId, final Region region) { + return getVirtualMachinesManager(subscriptionId).manager().computeSkus() + .listByRegionAndResourceType(com.azure.core.management.Region.fromName(region.getName()), ComputeResourceType.VIRTUALMACHINES).stream() + .map(AzureVirtualMachineSize::new).collect(Collectors.toList()); + } + + public List getKnownImages() { + return images; + } + + @Nonnull + public VirtualMachine create(@Nonnull final DraftVirtualMachine config) { + return config.create(this); + } + + VirtualMachines getVirtualMachinesManager(String subscriptionId) { + return getResourceManager(subscriptionId, ComputeManager::configure, ComputeManager.Configurable::authenticate).virtualMachines(); + } + + @AzureOperation(name = "common|service.refresh", params = "this.name()", type = AzureOperation.Type.SERVICE) + public void refresh() { + try { + CacheManager.evictCache("compute/{}/vm", CacheEvict.ALL); + } catch (ExecutionException e) { + log.warn("failed to evict cache", e); + } + } + + @Override + public String name() { + return "Virtual Machine"; + } +} diff --git a/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/vm/AzureVirtualMachineSize.java b/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/vm/AzureVirtualMachineSize.java new file mode 100644 index 0000000000..85e2345dfd --- /dev/null +++ b/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/vm/AzureVirtualMachineSize.java @@ -0,0 +1,24 @@ +/* + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + */ + +package com.microsoft.azure.toolkit.lib.compute.vm; + +import com.azure.resourcemanager.compute.models.ComputeSku; +import lombok.EqualsAndHashCode; +import lombok.Getter; + +@Getter +@EqualsAndHashCode +public class AzureVirtualMachineSize { + private final String name; + + public AzureVirtualMachineSize(final ComputeSku size) { + this.name = size.name().toString(); + } + + public AzureVirtualMachineSize(final String name) { + this.name = name; + } +} diff --git a/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/vm/DraftVirtualMachine.java b/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/vm/DraftVirtualMachine.java new file mode 100644 index 0000000000..f629c30ab0 --- /dev/null +++ b/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/vm/DraftVirtualMachine.java @@ -0,0 +1,128 @@ +/* + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + */ + +package com.microsoft.azure.toolkit.lib.compute.vm; + +import com.azure.resourcemanager.compute.models.AvailabilitySet; +import com.azure.resourcemanager.compute.models.VirtualMachine.DefinitionStages.WithCreate; +import com.azure.resourcemanager.compute.models.VirtualMachine.DefinitionStages.WithLinuxCreateManagedOrUnmanaged; +import com.azure.resourcemanager.compute.models.VirtualMachine.DefinitionStages.WithLinuxRootPasswordOrPublicKeyManagedOrUnmanaged; +import com.azure.resourcemanager.compute.models.VirtualMachine.DefinitionStages.WithProximityPlacementGroup; +import com.azure.resourcemanager.compute.models.VirtualMachine.DefinitionStages.WithPublicIPAddress; +import com.microsoft.azure.toolkit.lib.common.model.Region; +import com.microsoft.azure.toolkit.lib.compute.AzureResourceDraft; +import com.microsoft.azure.toolkit.lib.compute.ip.PublicIpAddress; +import com.microsoft.azure.toolkit.lib.compute.network.Network; +import com.microsoft.azure.toolkit.lib.compute.network.model.Subnet; +import com.microsoft.azure.toolkit.lib.compute.security.NetworkSecurityGroup; +import com.microsoft.azure.toolkit.lib.compute.vm.model.AuthenticationType; +import com.microsoft.azure.toolkit.lib.compute.vm.model.AzureSpotConfig; +import com.microsoft.azure.toolkit.lib.compute.vm.model.OperatingSystem; +import com.microsoft.azure.toolkit.lib.storage.service.StorageAccount; +import lombok.Getter; +import lombok.Setter; +import org.apache.commons.lang3.StringUtils; +import org.jetbrains.annotations.Nullable; + +import javax.annotation.Nonnull; +import java.util.Optional; + +@Getter +@Setter +public class DraftVirtualMachine extends VirtualMachine implements AzureResourceDraft { + private Region region; + private AzureImage image; + private Network network; + private Subnet subnet; + private PublicIpAddress ipAddress; + private NetworkSecurityGroup securityGroup; + private String userName; + private AuthenticationType authenticationType; + private String password; + private String sshKey; + private AzureVirtualMachineSize size; + private String availabilitySet; + private StorageAccount storageAccount; + private AzureSpotConfig azureSpotConfig; + + public DraftVirtualMachine(@Nonnull final String subscriptionId, @Nonnull final String resourceGroup, @Nonnull final String name) { + super(getResourceId(subscriptionId, resourceGroup, name), null); + } + + @Override + protected String loadStatus() { + return Optional.ofNullable(remote).map(ignore -> super.loadStatus()).orElse(Status.DRAFT); + } + + @Nullable + @Override + protected com.azure.resourcemanager.compute.models.VirtualMachine loadRemote() { + return Optional.ofNullable(remote).map(ignore -> super.loadRemote()).orElse(null); + } + + VirtualMachine create(final AzureVirtualMachine module) { + this.module = module; + final WithPublicIPAddress withPublicIPAddress = module.getVirtualMachinesManager(subscriptionId).define(this.getName()) + .withRegion(this.getRegion().getName()) + .withExistingResourceGroup(this.getResourceGroup()) + .withExistingPrimaryNetwork(this.getNetworkClient()) + .withSubnet(subnet.getName()) + .withPrimaryPrivateIPAddressDynamic(); + final WithProximityPlacementGroup withProximityPlacementGroup = ipAddress != null ? + withPublicIPAddress.withExistingPrimaryPublicIPAddress(getPublicIpAddressClient()) : withPublicIPAddress.withoutPrimaryPublicIPAddress(); + final WithCreate withCreate = configureImage(withProximityPlacementGroup); + if (StringUtils.isNotEmpty(availabilitySet)) { + withCreate.withExistingAvailabilitySet(getAvailabilitySetClient()); + } + if (storageAccount != null) { + // todo: implement storage account + } + if (azureSpotConfig != null) { + // todo: implement azure spot related configs + } + this.remote = withCreate.create(); + this.remote.getPrimaryNetworkInterface().update().withExistingNetworkSecurityGroup(getSecurityGroupClient()).apply(); + refreshStatus(); + module.refresh(); + return this; + } + + private WithCreate configureImage(final WithProximityPlacementGroup withCreate) { + if (getImage().getOperatingSystem() == OperatingSystem.Windows) { + return withCreate.withSpecificWindowsImageVersion(image.getImageReference()) + .withAdminUsername(userName).withAdminPassword(password).withSize(size.getName()); + } else { + final WithLinuxRootPasswordOrPublicKeyManagedOrUnmanaged withLinuxImage = + withCreate.withSpecificLinuxImageVersion(image.getImageReference()).withRootUsername(userName); + final WithLinuxCreateManagedOrUnmanaged withLinuxAuthentication = authenticationType == AuthenticationType.Password ? + withLinuxImage.withRootPassword(password) : withLinuxImage.withSsh(sshKey); + return withLinuxAuthentication.withSize(size.getName()); + } + } + + private com.azure.resourcemanager.network.models.NetworkSecurityGroup getSecurityGroupClient() { + return Optional.ofNullable(module).map(parent -> parent.getVirtualMachinesManager(subscriptionId).manager()) + .map(manager -> manager.networkManager().networkSecurityGroups().getByResourceGroup(resourceGroup, securityGroup.name())).orElse(null); + } + + private AvailabilitySet getAvailabilitySetClient() { + return Optional.ofNullable(module).map(parent -> parent.getVirtualMachinesManager(subscriptionId).manager()) + .map(manager -> manager.availabilitySets().getByResourceGroup(resourceGroup, availabilitySet)).orElse(null); + } + + private com.azure.resourcemanager.network.models.PublicIpAddress getPublicIpAddressClient() { + return Optional.ofNullable(module).map(parent -> parent.getVirtualMachinesManager(subscriptionId).manager()) + .map(manager -> manager.networkManager().publicIpAddresses().getById(ipAddress.getId())).orElse(null); + } + + private com.azure.resourcemanager.network.models.Network getNetworkClient() { + return Optional.ofNullable(module).map(parent -> parent.getVirtualMachinesManager(subscriptionId).manager()) + .map(manager -> manager.networkManager().networks().getById(network.getId())).orElse(null); + } + + private static String getResourceId(@Nonnull final String subscriptionId, @Nonnull final String resourceGroup, @Nonnull final String name) { + return String.format("/subscriptions/%s/resourceGroups/%s/providers/Microsoft.Compute/virtualMachines/%s", subscriptionId, resourceGroup, name); + } +} diff --git a/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/vm/VirtualMachine.java b/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/vm/VirtualMachine.java new file mode 100644 index 0000000000..60fd481f88 --- /dev/null +++ b/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/vm/VirtualMachine.java @@ -0,0 +1,89 @@ +/* + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + */ + +package com.microsoft.azure.toolkit.lib.compute.vm; + +import com.azure.resourcemanager.compute.models.PowerState; +import com.microsoft.azure.toolkit.lib.common.entity.IAzureBaseResource; +import com.microsoft.azure.toolkit.lib.common.entity.IAzureModule; +import com.microsoft.azure.toolkit.lib.common.entity.Removable; +import com.microsoft.azure.toolkit.lib.common.event.AzureOperationEvent; +import com.microsoft.azure.toolkit.lib.compute.AbstractAzureResource; +import org.apache.commons.lang3.StringUtils; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.util.Objects; + +public class VirtualMachine extends AbstractAzureResource + implements AzureOperationEvent.Source, Removable { + + protected AzureVirtualMachine module; + + public VirtualMachine(@Nonnull String id, @Nullable AzureVirtualMachine module) { + super(id); + this.module = module; + } + + public VirtualMachine(@Nonnull com.azure.resourcemanager.compute.models.VirtualMachine resource, @Nonnull AzureVirtualMachine module) { + super(resource); + this.module = module; + } + + @Nonnull + @Override + public IAzureModule, + ? extends IAzureBaseResource> module() { + return module; + } + + @Override + protected String loadStatus() { + final String powerState = remote().powerState().toString(); + if (StringUtils.equalsIgnoreCase(powerState, PowerState.RUNNING.toString())) { + return Status.RUNNING; + } else if (StringUtils.equalsAnyIgnoreCase(powerState, PowerState.DEALLOCATING.toString(), PowerState.STOPPING.toString(), + PowerState.STARTING.toString())) { + return Status.PENDING; + } else if (StringUtils.equalsAnyIgnoreCase(powerState, PowerState.STOPPED.toString(), PowerState.DEALLOCATED.toString())) { + return Status.STOPPED; + } else { + return Status.UNKNOWN; + } + } + + @Nullable + @Override + protected com.azure.resourcemanager.compute.models.VirtualMachine loadRemote() { + return module.getVirtualMachinesManager(subscriptionId).getByResourceGroup(resourceGroup, name); + } + + public void start() { + this.status(Status.PENDING); + remote().start(); + this.refreshStatus(); + } + + public void stop() { + this.status(Status.PENDING); + remote().powerOff(); + this.refreshStatus(); + } + + public void restart() { + this.status(Status.PENDING); + remote().restart(); + this.refreshStatus(); + } + + @Override + public void remove() { + if (this.exists()) { + this.status(Status.PENDING); + this.remote().manager().virtualMachines().deleteById(id()); + this.module.refresh(); + } + } +} diff --git a/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/vm/model/AuthenticationType.java b/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/vm/model/AuthenticationType.java new file mode 100644 index 0000000000..af3833a4b7 --- /dev/null +++ b/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/vm/model/AuthenticationType.java @@ -0,0 +1,10 @@ +/* + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + */ +package com.microsoft.azure.toolkit.lib.compute.vm.model; + +public enum AuthenticationType { + Password, + SSH +} diff --git a/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/vm/model/AzureSpotConfig.java b/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/vm/model/AzureSpotConfig.java new file mode 100644 index 0000000000..743c3a12f5 --- /dev/null +++ b/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/vm/model/AzureSpotConfig.java @@ -0,0 +1,27 @@ +/* + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + */ + +package com.microsoft.azure.toolkit.lib.compute.vm.model; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +@Getter +@AllArgsConstructor +public class AzureSpotConfig { + private final double maximumPrice; + private final EvictionType type; + private final EvictionPolicy policy; + + public enum EvictionType { + CapacityOnly, + PriceOrCapacity; + } + + public enum EvictionPolicy { + StopAndDeallocate, + Delete; + } +} diff --git a/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/vm/model/OperatingSystem.java b/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/vm/model/OperatingSystem.java new file mode 100644 index 0000000000..f9309e1dd1 --- /dev/null +++ b/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/vm/model/OperatingSystem.java @@ -0,0 +1,20 @@ +/* + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + */ + +package com.microsoft.azure.toolkit.lib.compute.vm.model; + +import org.apache.commons.lang3.StringUtils; + +import java.util.Arrays; + +public enum OperatingSystem { + Windows, + Linux; + + public static OperatingSystem fromString(String value) { + return Arrays.stream(values()).filter(operatingSystem -> StringUtils.equalsIgnoreCase(operatingSystem.name(), value)) + .findFirst().orElse(null); + } +} diff --git a/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/vm/task/CreateVirtualMachineTask.java b/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/vm/task/CreateVirtualMachineTask.java new file mode 100644 index 0000000000..a639e96821 --- /dev/null +++ b/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/vm/task/CreateVirtualMachineTask.java @@ -0,0 +1,75 @@ +/* + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + */ + +package com.microsoft.azure.toolkit.lib.compute.vm.task; + +import com.microsoft.azure.toolkit.lib.Azure; +import com.microsoft.azure.toolkit.lib.common.bundle.AzureString; +import com.microsoft.azure.toolkit.lib.common.entity.IAzureBaseResource; +import com.microsoft.azure.toolkit.lib.common.task.AzureTask; +import com.microsoft.azure.toolkit.lib.compute.ip.AzurePublicIpAddress; +import com.microsoft.azure.toolkit.lib.compute.ip.DraftPublicIpAddress; +import com.microsoft.azure.toolkit.lib.compute.ip.PublicIpAddress; +import com.microsoft.azure.toolkit.lib.compute.network.AzureNetwork; +import com.microsoft.azure.toolkit.lib.compute.network.DraftNetwork; +import com.microsoft.azure.toolkit.lib.compute.network.Network; +import com.microsoft.azure.toolkit.lib.compute.security.AzureNetworkSecurityGroup; +import com.microsoft.azure.toolkit.lib.compute.security.DraftNetworkSecurityGroup; +import com.microsoft.azure.toolkit.lib.compute.security.NetworkSecurityGroup; +import com.microsoft.azure.toolkit.lib.compute.vm.AzureVirtualMachine; +import com.microsoft.azure.toolkit.lib.compute.vm.DraftVirtualMachine; +import com.microsoft.azure.toolkit.lib.compute.vm.VirtualMachine; +import com.microsoft.azure.toolkit.lib.resource.task.CreateResourceGroupTask; +import org.apache.commons.lang3.StringUtils; + +import java.util.ArrayList; +import java.util.List; + +public class CreateVirtualMachineTask extends AzureTask { + private final DraftVirtualMachine draftVirtualMachine; + private final List> subTasks; + private VirtualMachine result; + + public CreateVirtualMachineTask(final DraftVirtualMachine draftVirtualMachine) { + this.draftVirtualMachine = draftVirtualMachine; + this.subTasks = this.initTasks(); + } + + private List> initTasks() { + final List> tasks = new ArrayList<>(); + tasks.add(new CreateResourceGroupTask(draftVirtualMachine.subscriptionId(), draftVirtualMachine.resourceGroup(), draftVirtualMachine.getRegion())); + // Create Virtual Network + final Network network = draftVirtualMachine.getNetwork(); + if (network instanceof DraftNetwork && StringUtils.equalsIgnoreCase(network.status(), IAzureBaseResource.Status.DRAFT)) { + final AzureString title = AzureString.format("Create new virtual network({0})", network.getName()); + tasks.add(new AzureTask<>(title, () -> Azure.az(AzureNetwork.class).create((DraftNetwork) network))); + } + // Create Public IP + final PublicIpAddress publicIpAddress = draftVirtualMachine.getIpAddress(); + if (publicIpAddress instanceof DraftPublicIpAddress && StringUtils.equalsIgnoreCase(publicIpAddress.status(), IAzureBaseResource.Status.DRAFT)) { + final AzureString title = AzureString.format("Create new public ip address({0})", publicIpAddress.getName()); + tasks.add(new AzureTask<>(title, () -> Azure.az(AzurePublicIpAddress.class).create((DraftPublicIpAddress) publicIpAddress))); + } + // Create Security Group + final NetworkSecurityGroup securityGroup = draftVirtualMachine.getSecurityGroup(); + if (securityGroup instanceof DraftNetworkSecurityGroup && StringUtils.equalsIgnoreCase(securityGroup.status(), IAzureBaseResource.Status.DRAFT)) { + final AzureString title = AzureString.format("Create security group ({0})", securityGroup.getName()); + tasks.add(new AzureTask(title, () -> + Azure.az(AzureNetworkSecurityGroup.class).create((DraftNetworkSecurityGroup) securityGroup))); + } + // Create VM + final AzureString title = AzureString.format("Create virtual machine ({0})", draftVirtualMachine.getName()); + tasks.add(new AzureTask<>(title, () -> { + CreateVirtualMachineTask.this.result = Azure.az(AzureVirtualMachine.class).create(draftVirtualMachine); + return CreateVirtualMachineTask.this.result; + })); + return tasks; + } + + public VirtualMachine execute() { + this.subTasks.forEach(t -> t.getSupplier().get()); + return this.result; + } +} diff --git a/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/resources/META-INF/services/com.microsoft.azure.toolkit.lib.AzureService b/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/resources/META-INF/services/com.microsoft.azure.toolkit.lib.AzureService new file mode 100644 index 0000000000..1c2471e130 --- /dev/null +++ b/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/resources/META-INF/services/com.microsoft.azure.toolkit.lib.AzureService @@ -0,0 +1,4 @@ +com.microsoft.azure.toolkit.lib.compute.vm.AzureVirtualMachine +com.microsoft.azure.toolkit.lib.compute.network.AzureNetwork +com.microsoft.azure.toolkit.lib.compute.ip.AzurePublicIpAddress +com.microsoft.azure.toolkit.lib.compute.security.AzureNetworkSecurityGroup diff --git a/azure-toolkit-libs/pom.xml b/azure-toolkit-libs/pom.xml index bc972d626e..159686b021 100644 --- a/azure-toolkit-libs/pom.xml +++ b/azure-toolkit-libs/pom.xml @@ -213,6 +213,11 @@ azure-toolkit-redis-lib ${azure.toolkit-lib.version} + + com.microsoft.azure + azure-toolkit-compute-lib + ${azure.toolkit-lib.version} + com.microsoft.azure From 87b05301d2bf1dfe2e0fdae1dbeb7e947a2490fa Mon Sep 17 00:00:00 2001 From: Hanxiao Liu Date: Tue, 14 Sep 2021 21:55:13 +0800 Subject: [PATCH 050/126] Resolve refresh issue in abstract azure resource --- .../toolkit/lib/compute/AbstractAzureResource.java | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/AbstractAzureResource.java b/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/AbstractAzureResource.java index a0672ca261..46ad6d0124 100644 --- a/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/AbstractAzureResource.java +++ b/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/AbstractAzureResource.java @@ -95,16 +95,14 @@ protected final T remote() { @Override public final String status() { - if (Objects.nonNull(this.status)) { - return this.status; - } else { - this.refreshStatus(); - return Status.LOADING; + if (Objects.isNull(this.status)) { + this.status(loadStatus()); } + return this.status; } public final void refreshStatus() { - AzureTaskManager.getInstance().runOnPooledThread(() -> this.status(this.loadStatus())); + AzureTaskManager.getInstance().runOnPooledThread(() -> this.status(this.refresh().loadStatus())); } protected final void status(@Nonnull String status) { From 7c22a88cf2c36d5a6849ea450f966085e65d47bb Mon Sep 17 00:00:00 2001 From: Hanxiao Liu Date: Wed, 15 Sep 2021 12:59:32 +0800 Subject: [PATCH 051/126] Resolve checkstyle issues --- .../lib/compute/vm/VirtualMachine.java | 1 - .../lib/compute/vm/model/AzureSpotConfig.java | 54 +++++++++---------- 2 files changed, 27 insertions(+), 28 deletions(-) diff --git a/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/vm/VirtualMachine.java b/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/vm/VirtualMachine.java index 60fd481f88..e31b3dfbfb 100644 --- a/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/vm/VirtualMachine.java +++ b/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/vm/VirtualMachine.java @@ -15,7 +15,6 @@ import javax.annotation.Nonnull; import javax.annotation.Nullable; -import java.util.Objects; public class VirtualMachine extends AbstractAzureResource implements AzureOperationEvent.Source, Removable { diff --git a/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/vm/model/AzureSpotConfig.java b/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/vm/model/AzureSpotConfig.java index 743c3a12f5..6f341c024c 100644 --- a/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/vm/model/AzureSpotConfig.java +++ b/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/vm/model/AzureSpotConfig.java @@ -1,27 +1,27 @@ -/* - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - */ - -package com.microsoft.azure.toolkit.lib.compute.vm.model; - -import lombok.AllArgsConstructor; -import lombok.Getter; - -@Getter -@AllArgsConstructor -public class AzureSpotConfig { - private final double maximumPrice; - private final EvictionType type; - private final EvictionPolicy policy; - - public enum EvictionType { - CapacityOnly, - PriceOrCapacity; - } - - public enum EvictionPolicy { - StopAndDeallocate, - Delete; - } -} +/* + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + */ + +package com.microsoft.azure.toolkit.lib.compute.vm.model; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +@Getter +@AllArgsConstructor +public class AzureSpotConfig { + private final double maximumPrice; + private final EvictionType type; + private final EvictionPolicy policy; + + public enum EvictionType { + CapacityOnly, + PriceOrCapacity; + } + + public enum EvictionPolicy { + StopAndDeallocate, + Delete; + } +} From be58eb811e7a7cce8359d45d46c86be4999c40d8 Mon Sep 17 00:00:00 2001 From: andxu Date: Wed, 15 Sep 2021 21:09:06 +0800 Subject: [PATCH 052/126] list regions for redis/storage account/mysql/sql server --- .../azure/toolkit/lib/auth/AzureAccount.java | 20 +++++++++++++++++++ .../azure/toolkit/lib/AzureService.java | 1 - .../azure/toolkit/lib/mysql/AzureMySql.java | 20 ++++++------------- .../azure/toolkit/redis/AzureRedis.java | 11 ++++++++-- .../toolkit/lib/sqlserver/AzureSqlServer.java | 10 ++++++++-- .../storage/service/AzureStorageAccount.java | 13 +++++++++++- 6 files changed, 55 insertions(+), 20 deletions(-) diff --git a/azure-toolkit-libs/azure-toolkit-auth-lib/src/main/java/com/microsoft/azure/toolkit/lib/auth/AzureAccount.java b/azure-toolkit-libs/azure-toolkit-auth-lib/src/main/java/com/microsoft/azure/toolkit/lib/auth/AzureAccount.java index 4c5e1a4512..6ead7e4171 100644 --- a/azure-toolkit-libs/azure-toolkit-auth-lib/src/main/java/com/microsoft/azure/toolkit/lib/auth/AzureAccount.java +++ b/azure-toolkit-libs/azure-toolkit-auth-lib/src/main/java/com/microsoft/azure/toolkit/lib/auth/AzureAccount.java @@ -16,6 +16,7 @@ import com.azure.resourcemanager.resources.ResourceManager; import com.azure.resourcemanager.resources.fluentcore.policy.ProviderRegistrationPolicy; import com.azure.resourcemanager.resources.models.Location; +import com.azure.resourcemanager.resources.models.ProviderResourceType; import com.azure.resourcemanager.resources.models.Providers; import com.azure.resourcemanager.resources.models.RegionType; import com.azure.resourcemanager.resources.models.Subscription; @@ -53,6 +54,8 @@ import java.util.function.Supplier; import java.util.stream.Collectors; +import static com.microsoft.azure.toolkit.lib.Azure.az; + public class AzureAccount implements IAzureAccount { @Setter(AccessLevel.PACKAGE) @@ -237,6 +240,23 @@ public List listRegions(String subscriptionId) { .map(Location::region).distinct().map(AzureAccount::toRegion).collect(Collectors.toList()); } + public List listSupportedRegions(String subscriptionId, String provider, String resourceType) { + List regionList = az(AzureAccount.class).listRegions(subscriptionId); + final ResourceManager resourceManager = getResourceManager(subscriptionId); + final ProviderResourceType redisResourceType = + resourceManager.providers().getByName(provider).resourceTypes() + .stream().filter(type -> StringUtils.equalsIgnoreCase(type.resourceType(), resourceType)).findFirst().orElse(null); + if (redisResourceType == null) { + return regionList; + } + final List validRegions = redisResourceType.locations().stream().map(Region::fromName).collect(Collectors.toList()); + + return regionList.stream() + .filter(validRegions::contains) + .distinct() + .collect(Collectors.toList()); + } + /** * see doc for: az account list-locations -o table */ diff --git a/azure-toolkit-libs/azure-toolkit-common-lib/src/main/java/com/microsoft/azure/toolkit/lib/AzureService.java b/azure-toolkit-libs/azure-toolkit-common-lib/src/main/java/com/microsoft/azure/toolkit/lib/AzureService.java index c1173bd389..77da47f2a6 100644 --- a/azure-toolkit-libs/azure-toolkit-common-lib/src/main/java/com/microsoft/azure/toolkit/lib/AzureService.java +++ b/azure-toolkit-libs/azure-toolkit-common-lib/src/main/java/com/microsoft/azure/toolkit/lib/AzureService.java @@ -17,4 +17,3 @@ default List getSubscriptions() { return Azure.az(IAzureAccount.class).account().getSelectedSubscriptions(); } } - diff --git a/azure-toolkit-libs/azure-toolkit-mysql-lib/src/main/java/com/microsoft/azure/toolkit/lib/mysql/AzureMySql.java b/azure-toolkit-libs/azure-toolkit-mysql-lib/src/main/java/com/microsoft/azure/toolkit/lib/mysql/AzureMySql.java index f0107aa9b9..bce125e647 100644 --- a/azure-toolkit-libs/azure-toolkit-mysql-lib/src/main/java/com/microsoft/azure/toolkit/lib/mysql/AzureMySql.java +++ b/azure-toolkit-libs/azure-toolkit-mysql-lib/src/main/java/com/microsoft/azure/toolkit/lib/mysql/AzureMySql.java @@ -13,6 +13,7 @@ import com.azure.resourcemanager.mysql.models.ServerVersion; import com.azure.resourcemanager.mysql.models.Sku; import com.azure.resourcemanager.resources.fluentcore.arm.ResourceId; +import com.microsoft.azure.toolkit.lib.Azure; import com.microsoft.azure.toolkit.lib.AzureService; import com.microsoft.azure.toolkit.lib.SubscriptionScoped; import com.microsoft.azure.toolkit.lib.auth.AzureAccount; @@ -27,19 +28,10 @@ import org.apache.commons.lang3.StringUtils; import javax.annotation.Nonnull; -import java.util.Arrays; import java.util.List; import java.util.stream.Collectors; -import static com.microsoft.azure.toolkit.lib.Azure.az; - public class AzureMySql extends SubscriptionScoped implements AzureService { - private static final List MYSQL_SUPPORTED_REGIONS = Arrays.asList( - "australiacentral", "australiacentral2", "australiaeast", "australiasoutheast", "brazilsouth", "canadacentral", "canadaeast", "centralindia", - "centralus", "eastasia", "eastus2", "eastus", "francecentral", "francesouth", "germanywestcentral", "japaneast", "japanwest", "koreacentral", - "koreasouth", "northcentralus", "northeurope", "southafricanorth", "southafricawest", "southcentralus", "southindia", "southeastasia", - "norwayeast", "switzerlandnorth", "uaenorth", "uksouth", "ukwest", "westcentralus", "westeurope", "westindia", "westus", "westus2", - "centraluseuap", "eastus2euap"); private static final String NAME_AVAILABILITY_CHECK_TYPE = "Microsoft.DBforMySQL/servers"; public AzureMySql() { @@ -85,11 +77,11 @@ public boolean checkNameAvailability(String name) { } public List listSupportedRegions() { - List locationList = az(AzureAccount.class).listRegions(getDefaultSubscription().getId()); - return locationList.stream() - .filter(e -> MYSQL_SUPPORTED_REGIONS.contains(e.getName())) - .distinct() - .collect(Collectors.toList()); + return listSupportedRegions(getDefaultSubscription().getId()); + } + + public List listSupportedRegions(String subscriptionId) { + return Azure.az(AzureAccount.class).listSupportedRegions(subscriptionId, "Microsoft.DBforMySQL", "servers"); } public List listSupportedVersions() { diff --git a/azure-toolkit-libs/azure-toolkit-redis-lib/src/main/java/com/microsoft/azure/toolkit/redis/AzureRedis.java b/azure-toolkit-libs/azure-toolkit-redis-lib/src/main/java/com/microsoft/azure/toolkit/redis/AzureRedis.java index 3d3061fbf4..7282f12965 100644 --- a/azure-toolkit-libs/azure-toolkit-redis-lib/src/main/java/com/microsoft/azure/toolkit/redis/AzureRedis.java +++ b/azure-toolkit-libs/azure-toolkit-redis-lib/src/main/java/com/microsoft/azure/toolkit/redis/AzureRedis.java @@ -11,10 +11,13 @@ import com.azure.resourcemanager.redis.fluent.RedisClient; import com.azure.resourcemanager.redis.models.CheckNameAvailabilityParameters; import com.azure.resourcemanager.resources.fluentcore.arm.ResourceId; +import com.microsoft.azure.toolkit.lib.Azure; import com.microsoft.azure.toolkit.lib.AzureService; import com.microsoft.azure.toolkit.lib.SubscriptionScoped; +import com.microsoft.azure.toolkit.lib.auth.AzureAccount; import com.microsoft.azure.toolkit.lib.common.entity.CheckNameAvailabilityResultEntity; import com.microsoft.azure.toolkit.lib.common.event.AzureOperationEvent; +import com.microsoft.azure.toolkit.lib.common.model.Region; import com.microsoft.azure.toolkit.lib.common.model.Subscription; import com.microsoft.azure.toolkit.lib.common.operation.AzureOperation; import com.microsoft.azure.toolkit.lib.common.task.ICommittable; @@ -67,14 +70,18 @@ public CheckNameAvailabilityResultEntity checkNameAvailability(String subscripti } } + public List listSupportedRegions(String subscriptionId) { + return Azure.az(AzureAccount.class).listSupportedRegions(subscriptionId, "Microsoft.Cache", "Redis"); + } + public RedisCache create(RedisConfig config) { return new Creator(config).commit(); } @AllArgsConstructor(access = AccessLevel.PRIVATE) - private class Creator implements ICommittable, AzureOperationEvent.Source { + private static class Creator implements ICommittable, AzureOperationEvent.Source { - private RedisConfig config; + private final RedisConfig config; @Override @AzureOperation(name = "redis.create", params = {"this.config.getName()"}, type = AzureOperation.Type.SERVICE) diff --git a/azure-toolkit-libs/azure-toolkit-sqlserver-lib/src/main/java/com/microsoft/azure/toolkit/lib/sqlserver/AzureSqlServer.java b/azure-toolkit-libs/azure-toolkit-sqlserver-lib/src/main/java/com/microsoft/azure/toolkit/lib/sqlserver/AzureSqlServer.java index 545a4623b3..2520404565 100644 --- a/azure-toolkit-libs/azure-toolkit-sqlserver-lib/src/main/java/com/microsoft/azure/toolkit/lib/sqlserver/AzureSqlServer.java +++ b/azure-toolkit-libs/azure-toolkit-sqlserver-lib/src/main/java/com/microsoft/azure/toolkit/lib/sqlserver/AzureSqlServer.java @@ -4,17 +4,19 @@ */ package com.microsoft.azure.toolkit.lib.sqlserver; -import com.azure.core.management.Region; import com.azure.resourcemanager.resources.fluentcore.arm.ResourceId; import com.azure.resourcemanager.sql.SqlServerManager; import com.azure.resourcemanager.sql.models.CapabilityStatus; import com.azure.resourcemanager.sql.models.CheckNameAvailabilityResult; +import com.microsoft.azure.toolkit.lib.Azure; import com.microsoft.azure.toolkit.lib.AzureService; import com.microsoft.azure.toolkit.lib.SubscriptionScoped; +import com.microsoft.azure.toolkit.lib.auth.AzureAccount; import com.microsoft.azure.toolkit.lib.common.entity.CheckNameAvailabilityResultEntity; import com.microsoft.azure.toolkit.lib.common.entity.IAzureResourceEntity; import com.microsoft.azure.toolkit.lib.common.event.AzureOperationEvent; import com.microsoft.azure.toolkit.lib.common.exception.AzureToolkitRuntimeException; +import com.microsoft.azure.toolkit.lib.common.model.Region; import com.microsoft.azure.toolkit.lib.common.model.Subscription; import com.microsoft.azure.toolkit.lib.common.operation.AzureOperation; import com.microsoft.azure.toolkit.lib.common.task.ICommittable; @@ -69,10 +71,14 @@ public CheckNameAvailabilityResultEntity checkNameAvailability(String subscripti public boolean checkRegionCapability(String subscriptionId, String region) { SqlServerManager manager = SqlServerManagerFactory.create(subscriptionId); - com.azure.resourcemanager.sql.models.RegionCapabilities capabilities = manager.sqlServers().getCapabilitiesByRegion(Region.fromName(region)); + com.azure.resourcemanager.sql.models.RegionCapabilities capabilities = manager.sqlServers().getCapabilitiesByRegion(com.azure.core.management.Region.fromName(region)); return Objects.nonNull(capabilities.status()) && CapabilityStatus.AVAILABLE == capabilities.status(); } + public List listSupportedRegions(String subscriptionId) { + return Azure.az(AzureAccount.class).listSupportedRegions(subscriptionId, "Microsoft.SQL", "servers"); + } + private String getSubscriptionFromResourceEntity(@Nonnull IAzureResourceEntity resourceEntity) { if (StringUtils.isNotEmpty(resourceEntity.getId())) { return ResourceId.fromString(resourceEntity.getId()).subscriptionId(); diff --git a/azure-toolkit-libs/azure-toolkit-storage-lib/src/main/java/com/microsoft/azure/toolkit/lib/storage/service/AzureStorageAccount.java b/azure-toolkit-libs/azure-toolkit-storage-lib/src/main/java/com/microsoft/azure/toolkit/lib/storage/service/AzureStorageAccount.java index 05ec2dd47b..0c7e987f7c 100644 --- a/azure-toolkit-libs/azure-toolkit-storage-lib/src/main/java/com/microsoft/azure/toolkit/lib/storage/service/AzureStorageAccount.java +++ b/azure-toolkit-libs/azure-toolkit-storage-lib/src/main/java/com/microsoft/azure/toolkit/lib/storage/service/AzureStorageAccount.java @@ -7,14 +7,21 @@ import com.azure.resourcemanager.resources.fluentcore.arm.ResourceId; import com.azure.resourcemanager.storage.StorageManager; -import com.azure.resourcemanager.storage.models.*; +import com.azure.resourcemanager.storage.models.AccessTier; +import com.azure.resourcemanager.storage.models.CheckNameAvailabilityResult; +import com.azure.resourcemanager.storage.models.Reason; +import com.azure.resourcemanager.storage.models.SkuName; +import com.azure.resourcemanager.storage.models.StorageAccountSkuType; +import com.microsoft.azure.toolkit.lib.Azure; import com.microsoft.azure.toolkit.lib.AzureService; import com.microsoft.azure.toolkit.lib.SubscriptionScoped; +import com.microsoft.azure.toolkit.lib.auth.AzureAccount; import com.microsoft.azure.toolkit.lib.common.cache.CacheEvict; import com.microsoft.azure.toolkit.lib.common.cache.CacheManager; import com.microsoft.azure.toolkit.lib.common.cache.Cacheable; import com.microsoft.azure.toolkit.lib.common.entity.CheckNameAvailabilityResultEntity; import com.microsoft.azure.toolkit.lib.common.event.AzureOperationEvent; +import com.microsoft.azure.toolkit.lib.common.model.Region; import com.microsoft.azure.toolkit.lib.common.model.Subscription; import com.microsoft.azure.toolkit.lib.common.operation.AzureOperation; import com.microsoft.azure.toolkit.lib.common.task.ICommittable; @@ -78,6 +85,10 @@ public CheckNameAvailabilityResultEntity checkNameAvailability(String subscripti Optional.ofNullable(result.reason()).map(Reason::toString).orElse(null), result.message()); } + public List listSupportedRegions(String subscriptionId) { + return Azure.az(AzureAccount.class).listSupportedRegions(subscriptionId, "Microsoft.Storage", "storageAccounts"); + } + public List listSupportedPerformances() { return Performance.values(); } From 58dc5b0536f3c07af6ced3cd9936efacc9565283 Mon Sep 17 00:00:00 2001 From: Mingliang Wang Date: Sat, 11 Sep 2021 22:29:35 +0800 Subject: [PATCH 053/126] remove IView.Dynamic --- .../azure/toolkit/lib/common/view/IView.java | 28 +++---------------- 1 file changed, 4 insertions(+), 24 deletions(-) diff --git a/azure-toolkit-libs/azure-toolkit-common-lib/src/main/java/com/microsoft/azure/toolkit/lib/common/view/IView.java b/azure-toolkit-libs/azure-toolkit-common-lib/src/main/java/com/microsoft/azure/toolkit/lib/common/view/IView.java index eb52946bf1..97ffb5bc04 100644 --- a/azure-toolkit-libs/azure-toolkit-common-lib/src/main/java/com/microsoft/azure/toolkit/lib/common/view/IView.java +++ b/azure-toolkit-libs/azure-toolkit-common-lib/src/main/java/com/microsoft/azure/toolkit/lib/common/view/IView.java @@ -11,35 +11,12 @@ import javax.annotation.Nonnull; import javax.annotation.Nullable; -import java.util.Optional; public interface IView { void dispose(); - interface Dynamic extends IView { - - default void updateView() { - Optional.ofNullable(this.getUpdater()).ifPresent(Updater::updateView); - } - - default void updateChildren() { - Optional.ofNullable(this.getUpdater()).ifPresent(Updater::updateChildren); - } - - void setUpdater(Updater updater); - - @Nullable - Updater getUpdater(); - - interface Updater { - default void updateView() { - } - - default void updateChildren() { - } - } - } + void refresh(); interface Label extends IView { String getLabel(); @@ -52,6 +29,9 @@ default boolean isEnabled() { return true; } + default void refresh() { + } + @Getter @RequiredArgsConstructor @AllArgsConstructor From f3130d9a09d709f638ded385e1e3abf0cbb5d183 Mon Sep 17 00:00:00 2001 From: Mingliang Wang Date: Thu, 16 Sep 2021 10:39:21 +0800 Subject: [PATCH 054/126] get connection string/account from remote --- .../storage/service/AzureStorageAccount.java | 2 ++ .../lib/storage/service/StorageAccount.java | 19 +++++++++++++++++++ 2 files changed, 21 insertions(+) diff --git a/azure-toolkit-libs/azure-toolkit-storage-lib/src/main/java/com/microsoft/azure/toolkit/lib/storage/service/AzureStorageAccount.java b/azure-toolkit-libs/azure-toolkit-storage-lib/src/main/java/com/microsoft/azure/toolkit/lib/storage/service/AzureStorageAccount.java index 05ec2dd47b..a2323fa9ca 100644 --- a/azure-toolkit-libs/azure-toolkit-storage-lib/src/main/java/com/microsoft/azure/toolkit/lib/storage/service/AzureStorageAccount.java +++ b/azure-toolkit-libs/azure-toolkit-storage-lib/src/main/java/com/microsoft/azure/toolkit/lib/storage/service/AzureStorageAccount.java @@ -8,6 +8,7 @@ import com.azure.resourcemanager.resources.fluentcore.arm.ResourceId; import com.azure.resourcemanager.storage.StorageManager; import com.azure.resourcemanager.storage.models.*; +import com.microsoft.azure.toolkit.lib.Azure; import com.microsoft.azure.toolkit.lib.AzureService; import com.microsoft.azure.toolkit.lib.SubscriptionScoped; import com.microsoft.azure.toolkit.lib.common.cache.CacheEvict; @@ -133,6 +134,7 @@ public StorageAccount commit() { withCreate = withCreate.withGeneralPurposeAccountKindV2(); } com.azure.resourcemanager.storage.models.StorageAccount account = withCreate.create(); + Azure.az(AzureStorageAccount.class).refresh(); return new StorageAccount(account); } diff --git a/azure-toolkit-libs/azure-toolkit-storage-lib/src/main/java/com/microsoft/azure/toolkit/lib/storage/service/StorageAccount.java b/azure-toolkit-libs/azure-toolkit-storage-lib/src/main/java/com/microsoft/azure/toolkit/lib/storage/service/StorageAccount.java index 7294a22007..a1a5ed3e87 100644 --- a/azure-toolkit-libs/azure-toolkit-storage-lib/src/main/java/com/microsoft/azure/toolkit/lib/storage/service/StorageAccount.java +++ b/azure-toolkit-libs/azure-toolkit-storage-lib/src/main/java/com/microsoft/azure/toolkit/lib/storage/service/StorageAccount.java @@ -7,16 +7,21 @@ import com.azure.core.management.exception.ManagementException; import com.azure.resourcemanager.storage.StorageManager; +import com.azure.resourcemanager.storage.models.StorageAccountKey; import com.microsoft.azure.toolkit.lib.Azure; +import com.microsoft.azure.toolkit.lib.auth.AzureCloud; import com.microsoft.azure.toolkit.lib.common.entity.AbstractAzureResource; import com.microsoft.azure.toolkit.lib.common.entity.IAzureResource; import com.microsoft.azure.toolkit.lib.common.entity.Removable; import com.microsoft.azure.toolkit.lib.common.event.AzureOperationEvent; import com.microsoft.azure.toolkit.lib.common.operation.AzureOperation; import com.microsoft.azure.toolkit.lib.storage.model.StorageAccountEntity; +import org.apache.commons.lang3.StringUtils; import org.apache.http.HttpStatus; import javax.annotation.Nonnull; +import java.util.List; +import java.util.Objects; public class StorageAccount extends AbstractAzureResource implements Removable, AzureOperationEvent.Source, IAzureResource { @@ -51,6 +56,20 @@ public void delete() { } } + @AzureOperation(name = "storage|account.get_connection_string", params = {"this.entity().getName()"}, type = AzureOperation.Type.SERVICE) + public String getConnectionString() { + // refer https://github.com/Azure/azure-cli/blob/ac3b190d4d/src/azure-cli/azure/cli/command_modules/storage/operations/account.py#L232 + final String suffix = Azure.az(AzureCloud.class).get().getStorageEndpointSuffix(); + return String.format("DefaultEndpointsProtocol=https;EndpointSuffix=%s;AccountName=%s;AccountKey=%s", + suffix, this.name(), getKey()); + } + + @AzureOperation(name = "storage|account.get_key", params = {"this.entity().getName()"}, type = AzureOperation.Type.SERVICE) + public String getKey() { + final List keys = Objects.requireNonNull(this.remote()).getKeys(); + return StringUtils.equalsIgnoreCase(keys.get(0).keyName(), "primary") ? keys.get(0).value() : keys.get(1).value(); + } + @Override public void remove() { this.delete(); From 3b6e7a7e5e225ab3385d1a6d725bc2e65d2b7ae1 Mon Sep 17 00:00:00 2001 From: andxu Date: Fri, 17 Sep 2021 11:34:53 +0800 Subject: [PATCH 055/126] Remove unsupported JBoss 7.2 --- .../microsoft/azure/toolkit/lib/appservice/model/Runtime.java | 3 +-- .../azure/toolkit/lib/appservice/model/WebContainer.java | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/model/Runtime.java b/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/model/Runtime.java index 029a253e27..4e6086003f 100644 --- a/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/model/Runtime.java +++ b/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/model/Runtime.java @@ -45,7 +45,6 @@ public class Runtime { public static final Runtime LINUX_JAVA8_TOMCAT85 = new Runtime(OperatingSystem.LINUX, WebContainer.TOMCAT_85, JavaVersion.JAVA_8); public static final Runtime LINUX_JAVA8_JBOSS7 = new Runtime(OperatingSystem.LINUX, WebContainer.JBOSS_7, JavaVersion.JAVA_8); public static final Runtime LINUX_JAVA11_JBOSS7 = new Runtime(OperatingSystem.LINUX, WebContainer.JBOSS_7, JavaVersion.JAVA_11); - public static final Runtime LINUX_JAVA8_JBOSS72 = new Runtime(OperatingSystem.LINUX, WebContainer.JBOSS_72, JavaVersion.JAVA_8); public static final Runtime LINUX_JAVA11_TOMCAT9 = new Runtime(OperatingSystem.LINUX, WebContainer.TOMCAT_9, JavaVersion.JAVA_11); public static final Runtime LINUX_JAVA11_TOMCAT85 = new Runtime(OperatingSystem.LINUX, WebContainer.TOMCAT_85, JavaVersion.JAVA_11); // Function @@ -58,7 +57,7 @@ public class Runtime { public static final List WEBAPP_RUNTIME = Collections.unmodifiableList(Arrays.asList(WINDOWS_JAVA8, WINDOWS_JAVA11, WINDOWS_JAVA8_TOMCAT9, WINDOWS_JAVA8_TOMCAT85, WINDOWS_JAVA11_TOMCAT9, WINDOWS_JAVA11_TOMCAT85, LINUX_JAVA8, LINUX_JAVA11, LINUX_JAVA8_TOMCAT9, LINUX_JAVA8_TOMCAT85, - LINUX_JAVA8_JBOSS72, LINUX_JAVA11_JBOSS7, LINUX_JAVA8_JBOSS7, LINUX_JAVA11_TOMCAT9, LINUX_JAVA11_TOMCAT85)); + LINUX_JAVA11_JBOSS7, LINUX_JAVA8_JBOSS7, LINUX_JAVA11_TOMCAT9, LINUX_JAVA11_TOMCAT85)); public static final List FUNCTION_APP_RUNTIME = Collections.unmodifiableList(Arrays.asList(FUNCTION_LINUX_JAVA8, FUNCTION_LINUX_JAVA11, FUNCTION_WINDOWS_JAVA8, FUNCTION_WINDOWS_JAVA11)); private static final List values = diff --git a/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/model/WebContainer.java b/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/model/WebContainer.java index fa64371ad1..b4352ea250 100644 --- a/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/model/WebContainer.java +++ b/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/model/WebContainer.java @@ -35,7 +35,6 @@ public class WebContainer implements ExpandableParameter { public static final WebContainer TOMCAT_85 = new WebContainer("tomcat 8.5"); public static final WebContainer TOMCAT_9 = new WebContainer("tomcat 9.0"); public static final WebContainer JBOSS_7 = new WebContainer("JBOSSEAP 7"); - public static final WebContainer JBOSS_72 = new WebContainer("JBOSSEAP 7.2"); public static final WebContainer TOMCAT_7_0_50 = new WebContainer("tomcat 7.0.50"); public static final WebContainer TOMCAT_7_0_62 = new WebContainer("tomcat 7.0.62"); @@ -56,7 +55,7 @@ public class WebContainer implements ExpandableParameter { private static final Set values = Collections.unmodifiableSet(Sets.newHashSet(TOMCAT_7, TOMCAT_7_0_50, TOMCAT_7_0_62, TOMCAT_8, TOMCAT_8_0_23, TOMCAT_85, TOMCAT_8_5_6, TOMCAT_8_5_20, TOMCAT_8_5_31, TOMCAT_8_5_34, TOMCAT_8_5_37, TOMCAT_9, TOMCAT_9_0_0, TOMCAT_9_0_8, - TOMCAT_9_0_12, TOMCAT_9_0_14, JETTY_9_1_NEWEST, JETTY_9_1_V20131115, JETTY_9_3_NEWEST, JETTY_9_3_V20161014, JAVA_SE, JBOSS_72, JBOSS_7)); + TOMCAT_9_0_12, TOMCAT_9_0_14, JETTY_9_1_NEWEST, JETTY_9_1_V20131115, JETTY_9_3_NEWEST, JETTY_9_3_V20161014, JAVA_SE, JBOSS_7)); private String value; From 165e40ebf5468b23f16114d34e828c961153f17c Mon Sep 17 00:00:00 2001 From: andxu Date: Fri, 17 Sep 2021 13:17:01 +0800 Subject: [PATCH 056/126] Fix test case --- .../microsoft/azure/maven/webapp/parser/ConfigParserTest.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/azure-webapp-maven-plugin/src/test/java/com/microsoft/azure/maven/webapp/parser/ConfigParserTest.java b/azure-webapp-maven-plugin/src/test/java/com/microsoft/azure/maven/webapp/parser/ConfigParserTest.java index 3f9ce1fa03..784fab635d 100644 --- a/azure-webapp-maven-plugin/src/test/java/com/microsoft/azure/maven/webapp/parser/ConfigParserTest.java +++ b/azure-webapp-maven-plugin/src/test/java/com/microsoft/azure/maven/webapp/parser/ConfigParserTest.java @@ -106,8 +106,8 @@ public void getWindowsRuntime() { public void getLinuxRuntime() { doReturn("linux").when(runtimeSetting).getOs(); doReturn("Java 8").when(runtimeSetting).getJavaVersion(); - doReturn("JBosseap 7.2").when(runtimeSetting).getWebContainer(); - assertEquals(parser.getRuntime(), Runtime.LINUX_JAVA8_JBOSS72); + doReturn("JBosseap 7").when(runtimeSetting).getWebContainer(); + assertEquals(parser.getRuntime(), Runtime.LINUX_JAVA8_JBOSS7); doReturn("linux").when(runtimeSetting).getOs(); doReturn("Java 11").when(runtimeSetting).getJavaVersion(); From f808cf3acaca3070e646a7a543e0a18d174f4e6a Mon Sep 17 00:00:00 2001 From: andxu Date: Sat, 18 Sep 2021 09:03:59 +0800 Subject: [PATCH 057/126] Resolve review comments --- .../azure/toolkit/lib/auth/AzureAccount.java | 56 --------------- .../azure/toolkit/lib/AzureService.java | 68 +++++++++++++++++++ .../azure/toolkit/lib/account/IAccount.java | 6 ++ .../toolkit/lib/account/IAzureAccount.java | 5 ++ .../azure/toolkit/lib/mysql/AzureMySql.java | 14 ++-- .../azure/toolkit/redis/AzureRedis.java | 9 +-- .../toolkit/lib/resource/AzureGroup.java | 31 --------- .../toolkit/lib/sqlserver/AzureSqlServer.java | 10 +-- .../storage/service/AzureStorageAccount.java | 10 +-- 9 files changed, 92 insertions(+), 117 deletions(-) diff --git a/azure-toolkit-libs/azure-toolkit-auth-lib/src/main/java/com/microsoft/azure/toolkit/lib/auth/AzureAccount.java b/azure-toolkit-libs/azure-toolkit-auth-lib/src/main/java/com/microsoft/azure/toolkit/lib/auth/AzureAccount.java index 6ead7e4171..eefa75186d 100644 --- a/azure-toolkit-libs/azure-toolkit-auth-lib/src/main/java/com/microsoft/azure/toolkit/lib/auth/AzureAccount.java +++ b/azure-toolkit-libs/azure-toolkit-auth-lib/src/main/java/com/microsoft/azure/toolkit/lib/auth/AzureAccount.java @@ -6,23 +6,15 @@ package com.microsoft.azure.toolkit.lib.auth; import com.azure.core.credential.TokenCredential; -import com.azure.core.http.policy.HttpLogDetailLevel; -import com.azure.core.http.policy.HttpPipelinePolicy; import com.azure.core.management.AzureEnvironment; -import com.azure.core.management.profile.AzureProfile; import com.azure.identity.SharedTokenCacheCredential; import com.azure.identity.SharedTokenCacheCredentialBuilder; import com.azure.identity.TokenCachePersistenceOptions; -import com.azure.resourcemanager.resources.ResourceManager; -import com.azure.resourcemanager.resources.fluentcore.policy.ProviderRegistrationPolicy; import com.azure.resourcemanager.resources.models.Location; -import com.azure.resourcemanager.resources.models.ProviderResourceType; -import com.azure.resourcemanager.resources.models.Providers; import com.azure.resourcemanager.resources.models.RegionType; import com.azure.resourcemanager.resources.models.Subscription; import com.google.common.base.Preconditions; import com.microsoft.azure.toolkit.lib.Azure; -import com.microsoft.azure.toolkit.lib.AzureConfiguration; import com.microsoft.azure.toolkit.lib.account.IAzureAccount; import com.microsoft.azure.toolkit.lib.auth.core.azurecli.AzureCliAccount; import com.microsoft.azure.toolkit.lib.auth.core.devicecode.DeviceCodeAccount; @@ -54,8 +46,6 @@ import java.util.function.Supplier; import java.util.stream.Collectors; -import static com.microsoft.azure.toolkit.lib.Azure.az; - public class AzureAccount implements IAzureAccount { @Setter(AccessLevel.PACKAGE) @@ -240,23 +230,6 @@ public List listRegions(String subscriptionId) { .map(Location::region).distinct().map(AzureAccount::toRegion).collect(Collectors.toList()); } - public List listSupportedRegions(String subscriptionId, String provider, String resourceType) { - List regionList = az(AzureAccount.class).listRegions(subscriptionId); - final ResourceManager resourceManager = getResourceManager(subscriptionId); - final ProviderResourceType redisResourceType = - resourceManager.providers().getByName(provider).resourceTypes() - .stream().filter(type -> StringUtils.equalsIgnoreCase(type.resourceType(), resourceType)).findFirst().orElse(null); - if (redisResourceType == null) { - return regionList; - } - final List validRegions = redisResourceType.locations().stream().map(Region::fromName).collect(Collectors.toList()); - - return regionList.stream() - .filter(validRegions::contains) - .distinct() - .collect(Collectors.toList()); - } - /** * see doc for: az account list-locations -o table */ @@ -300,33 +273,4 @@ private Subscription getSubscription(String subscriptionId) { return getResourceManager(subscriptionId).subscriptions().getById(subscriptionId); } - @Cacheable(cacheName = "resource/{}/manager", key = "$subscriptionId") - private ResourceManager getResourceManager(String subscriptionId) { - // make sure it is signed in. - account(); - final AzureConfiguration config = Azure.az().config(); - final String userAgent = config.getUserAgent(); - final HttpLogDetailLevel logDetailLevel = config.getLogLevel() == null ? - HttpLogDetailLevel.NONE : HttpLogDetailLevel.valueOf(config.getLogLevel()); - final AzureProfile azureProfile = new AzureProfile(account.getEnvironment()); - - final Providers providers = ResourceManager.configure() - .withPolicy(getUserAgentPolicy(userAgent)) - .authenticate(account.getTokenCredential(subscriptionId), azureProfile) - .withSubscription(subscriptionId).providers(); - return ResourceManager.configure() - .withLogLevel(logDetailLevel) - .withPolicy(getUserAgentPolicy(userAgent)) // set user agent with policy - .withPolicy(new ProviderRegistrationPolicy(providers)) // add policy to auto register resource providers - .authenticate(account.getTokenCredential(subscriptionId), azureProfile) - .withSubscription(subscriptionId); - } - - private HttpPipelinePolicy getUserAgentPolicy(String userAgent) { - return (httpPipelineCallContext, httpPipelineNextPolicy) -> { - final String previousUserAgent = httpPipelineCallContext.getHttpRequest().getHeaders().getValue("User-Agent"); - httpPipelineCallContext.getHttpRequest().setHeader("User-Agent", String.format("%s %s", userAgent, previousUserAgent)); - return httpPipelineNextPolicy.process(); - }; - } } diff --git a/azure-toolkit-libs/azure-toolkit-common-lib/src/main/java/com/microsoft/azure/toolkit/lib/AzureService.java b/azure-toolkit-libs/azure-toolkit-common-lib/src/main/java/com/microsoft/azure/toolkit/lib/AzureService.java index 77da47f2a6..c2960bbc73 100644 --- a/azure-toolkit-libs/azure-toolkit-common-lib/src/main/java/com/microsoft/azure/toolkit/lib/AzureService.java +++ b/azure-toolkit-libs/azure-toolkit-common-lib/src/main/java/com/microsoft/azure/toolkit/lib/AzureService.java @@ -5,15 +5,83 @@ package com.microsoft.azure.toolkit.lib; +import com.azure.core.http.policy.HttpLogDetailLevel; +import com.azure.core.http.policy.HttpPipelinePolicy; +import com.azure.core.management.profile.AzureProfile; +import com.azure.resourcemanager.resources.ResourceManager; +import com.azure.resourcemanager.resources.fluentcore.policy.ProviderRegistrationPolicy; +import com.azure.resourcemanager.resources.models.ProviderResourceType; +import com.azure.resourcemanager.resources.models.Providers; +import com.microsoft.azure.toolkit.lib.account.IAccount; import com.microsoft.azure.toolkit.lib.account.IAzureAccount; +import com.microsoft.azure.toolkit.lib.common.cache.Cacheable; import com.microsoft.azure.toolkit.lib.common.entity.IAzureBaseResource; import com.microsoft.azure.toolkit.lib.common.entity.IAzureModule; +import com.microsoft.azure.toolkit.lib.common.exception.AzureToolkitRuntimeException; +import com.microsoft.azure.toolkit.lib.common.model.Region; import com.microsoft.azure.toolkit.lib.common.model.Subscription; +import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.lang3.StringUtils; +import java.util.ArrayList; import java.util.List; +import java.util.stream.Collectors; + +import static com.microsoft.azure.toolkit.lib.Azure.az; public interface AzureService extends IAzureModule { default List getSubscriptions() { return Azure.az(IAzureAccount.class).account().getSelectedSubscriptions(); } + + @SuppressWarnings("checkstyle:Indentation") + default List listSupportedRegions(String subscriptionId) { + String[] names = StringUtils.split(name(), "/"); + if (names.length != 2) { + throw new AzureToolkitRuntimeException(String.format("It is illegal to list regions for service '%s'.", name())); + } + final String provider = names[0]; + final String resourceType = names[1]; + List allRegionList = az(IAzureAccount.class).listRegions(subscriptionId); + List result = new ArrayList<>(); + final ResourceManager resourceManager = getResourceManager(subscriptionId); + resourceManager.providers().getByName(provider).resourceTypes() + .stream().filter(type -> StringUtils.equalsIgnoreCase(type.resourceType(), resourceType)) + .findAny().map(ProviderResourceType::locations) + .ifPresent(list -> { + final List regionListByResource = list.stream().map(Region::fromName).collect(Collectors.toList()); + result.addAll(CollectionUtils.intersection(regionListByResource, allRegionList)); + }); + return result.isEmpty() ? allRegionList : result; + } + + @Cacheable(cacheName = "resource/{}/manager", key = "$subscriptionId") + default ResourceManager getResourceManager(String subscriptionId) { + // make sure it is signed in. + final IAccount account = az(IAzureAccount.class).account(); + final AzureConfiguration config = Azure.az().config(); + final String userAgent = config.getUserAgent(); + final HttpLogDetailLevel logDetailLevel = config.getLogLevel() == null ? + HttpLogDetailLevel.NONE : HttpLogDetailLevel.valueOf(config.getLogLevel()); + final AzureProfile azureProfile = new AzureProfile(account.getEnvironment()); + + final Providers providers = ResourceManager.configure() + .withPolicy(getUserAgentPolicy(userAgent)) + .authenticate(account.getTokenCredential(subscriptionId), azureProfile) + .withSubscription(subscriptionId).providers(); + return ResourceManager.configure() + .withLogLevel(logDetailLevel) + .withPolicy(getUserAgentPolicy(userAgent)) // set user agent with policy + .withPolicy(new ProviderRegistrationPolicy(providers)) // add policy to auto register resource providers + .authenticate(account.getTokenCredential(subscriptionId), azureProfile) + .withSubscription(subscriptionId); + } + + static HttpPipelinePolicy getUserAgentPolicy(String userAgent) { + return (httpPipelineCallContext, httpPipelineNextPolicy) -> { + final String previousUserAgent = httpPipelineCallContext.getHttpRequest().getHeaders().getValue("User-Agent"); + httpPipelineCallContext.getHttpRequest().setHeader("User-Agent", String.format("%s %s", userAgent, previousUserAgent)); + return httpPipelineNextPolicy.process(); + }; + } } diff --git a/azure-toolkit-libs/azure-toolkit-common-lib/src/main/java/com/microsoft/azure/toolkit/lib/account/IAccount.java b/azure-toolkit-libs/azure-toolkit-common-lib/src/main/java/com/microsoft/azure/toolkit/lib/account/IAccount.java index 2fa82565a9..7af0ecf00b 100644 --- a/azure-toolkit-libs/azure-toolkit-common-lib/src/main/java/com/microsoft/azure/toolkit/lib/account/IAccount.java +++ b/azure-toolkit-libs/azure-toolkit-common-lib/src/main/java/com/microsoft/azure/toolkit/lib/account/IAccount.java @@ -5,6 +5,8 @@ package com.microsoft.azure.toolkit.lib.account; +import com.azure.core.credential.TokenCredential; +import com.azure.core.management.AzureEnvironment; import com.microsoft.azure.toolkit.lib.common.model.Subscription; import java.util.List; @@ -18,4 +20,8 @@ public interface IAccount { Subscription getSubscription(String subscriptionId); String portalUrl(); + + AzureEnvironment getEnvironment(); + + TokenCredential getTokenCredential(String subscriptionId); } diff --git a/azure-toolkit-libs/azure-toolkit-common-lib/src/main/java/com/microsoft/azure/toolkit/lib/account/IAzureAccount.java b/azure-toolkit-libs/azure-toolkit-common-lib/src/main/java/com/microsoft/azure/toolkit/lib/account/IAzureAccount.java index bf5049426a..79f69be988 100644 --- a/azure-toolkit-libs/azure-toolkit-common-lib/src/main/java/com/microsoft/azure/toolkit/lib/account/IAzureAccount.java +++ b/azure-toolkit-libs/azure-toolkit-common-lib/src/main/java/com/microsoft/azure/toolkit/lib/account/IAzureAccount.java @@ -6,7 +6,12 @@ package com.microsoft.azure.toolkit.lib.account; import com.microsoft.azure.toolkit.lib.AzureService; +import com.microsoft.azure.toolkit.lib.common.model.Region; + +import java.util.List; public interface IAzureAccount extends AzureService { IAccount account(); + + List listRegions(String subscriptionId); } diff --git a/azure-toolkit-libs/azure-toolkit-mysql-lib/src/main/java/com/microsoft/azure/toolkit/lib/mysql/AzureMySql.java b/azure-toolkit-libs/azure-toolkit-mysql-lib/src/main/java/com/microsoft/azure/toolkit/lib/mysql/AzureMySql.java index bce125e647..3c12d04569 100644 --- a/azure-toolkit-libs/azure-toolkit-mysql-lib/src/main/java/com/microsoft/azure/toolkit/lib/mysql/AzureMySql.java +++ b/azure-toolkit-libs/azure-toolkit-mysql-lib/src/main/java/com/microsoft/azure/toolkit/lib/mysql/AzureMySql.java @@ -13,10 +13,8 @@ import com.azure.resourcemanager.mysql.models.ServerVersion; import com.azure.resourcemanager.mysql.models.Sku; import com.azure.resourcemanager.resources.fluentcore.arm.ResourceId; -import com.microsoft.azure.toolkit.lib.Azure; import com.microsoft.azure.toolkit.lib.AzureService; import com.microsoft.azure.toolkit.lib.SubscriptionScoped; -import com.microsoft.azure.toolkit.lib.auth.AzureAccount; import com.microsoft.azure.toolkit.lib.common.event.AzureOperationEvent; import com.microsoft.azure.toolkit.lib.common.exception.AzureToolkitRuntimeException; import com.microsoft.azure.toolkit.lib.common.model.Region; @@ -32,7 +30,7 @@ import java.util.stream.Collectors; public class AzureMySql extends SubscriptionScoped implements AzureService { - private static final String NAME_AVAILABILITY_CHECK_TYPE = "Microsoft.DBforMySQL/servers"; + private static final String MYSQL_PROVIDER_AND_RESOURCE = "Microsoft.DBforMySQL/servers"; public AzureMySql() { super(AzureMySql::new); @@ -72,7 +70,7 @@ private static int getTierPriority(PerformanceTierProperties tier) { public boolean checkNameAvailability(String name) { MySqlManager mySqlManager = MySqlManagerFactory.create(getDefaultSubscription().getId()); - NameAvailabilityRequest request = new NameAvailabilityRequest().withName(name).withType(NAME_AVAILABILITY_CHECK_TYPE); + NameAvailabilityRequest request = new NameAvailabilityRequest().withName(name).withType(MYSQL_PROVIDER_AND_RESOURCE); return mySqlManager.checkNameAvailabilities().execute(request).nameAvailable(); } @@ -80,10 +78,6 @@ public List listSupportedRegions() { return listSupportedRegions(getDefaultSubscription().getId()); } - public List listSupportedRegions(String subscriptionId) { - return Azure.az(AzureAccount.class).listSupportedRegions(subscriptionId, "Microsoft.DBforMySQL", "servers"); - } - public List listSupportedVersions() { return ServerVersion.values().stream().map(ExpandableStringEnum::toString).collect(Collectors.toList()); } @@ -164,4 +158,8 @@ public AzureOperationEvent.Source getEventSource() { return new AzureOperationEvent.Source() {}; } } + + public String name() { + return MYSQL_PROVIDER_AND_RESOURCE; + } } diff --git a/azure-toolkit-libs/azure-toolkit-redis-lib/src/main/java/com/microsoft/azure/toolkit/redis/AzureRedis.java b/azure-toolkit-libs/azure-toolkit-redis-lib/src/main/java/com/microsoft/azure/toolkit/redis/AzureRedis.java index 7282f12965..bf126fce1a 100644 --- a/azure-toolkit-libs/azure-toolkit-redis-lib/src/main/java/com/microsoft/azure/toolkit/redis/AzureRedis.java +++ b/azure-toolkit-libs/azure-toolkit-redis-lib/src/main/java/com/microsoft/azure/toolkit/redis/AzureRedis.java @@ -11,13 +11,10 @@ import com.azure.resourcemanager.redis.fluent.RedisClient; import com.azure.resourcemanager.redis.models.CheckNameAvailabilityParameters; import com.azure.resourcemanager.resources.fluentcore.arm.ResourceId; -import com.microsoft.azure.toolkit.lib.Azure; import com.microsoft.azure.toolkit.lib.AzureService; import com.microsoft.azure.toolkit.lib.SubscriptionScoped; -import com.microsoft.azure.toolkit.lib.auth.AzureAccount; import com.microsoft.azure.toolkit.lib.common.entity.CheckNameAvailabilityResultEntity; import com.microsoft.azure.toolkit.lib.common.event.AzureOperationEvent; -import com.microsoft.azure.toolkit.lib.common.model.Region; import com.microsoft.azure.toolkit.lib.common.model.Subscription; import com.microsoft.azure.toolkit.lib.common.operation.AzureOperation; import com.microsoft.azure.toolkit.lib.common.task.ICommittable; @@ -70,10 +67,6 @@ public CheckNameAvailabilityResultEntity checkNameAvailability(String subscripti } } - public List listSupportedRegions(String subscriptionId) { - return Azure.az(AzureAccount.class).listSupportedRegions(subscriptionId, "Microsoft.Cache", "Redis"); - } - public RedisCache create(RedisConfig config) { return new Creator(config).commit(); } @@ -112,6 +105,6 @@ public AzureOperationEvent.Source getEventSource() { @Override public String name() { - return "Redis Caches"; + return "Microsoft.Cache/redis"; } } diff --git a/azure-toolkit-libs/azure-toolkit-resource-lib/src/main/java/com/microsoft/azure/toolkit/lib/resource/AzureGroup.java b/azure-toolkit-libs/azure-toolkit-resource-lib/src/main/java/com/microsoft/azure/toolkit/lib/resource/AzureGroup.java index d8b5ceb6d1..f65d6999ee 100644 --- a/azure-toolkit-libs/azure-toolkit-resource-lib/src/main/java/com/microsoft/azure/toolkit/lib/resource/AzureGroup.java +++ b/azure-toolkit-libs/azure-toolkit-resource-lib/src/main/java/com/microsoft/azure/toolkit/lib/resource/AzureGroup.java @@ -5,17 +5,9 @@ package com.microsoft.azure.toolkit.lib.resource; -import com.azure.core.http.policy.HttpLogDetailLevel; -import com.azure.core.http.policy.HttpPipelinePolicy; -import com.azure.core.management.profile.AzureProfile; -import com.azure.resourcemanager.resources.ResourceManager; import com.azure.resourcemanager.resources.fluentcore.arm.ResourceId; -import com.microsoft.azure.toolkit.lib.Azure; -import com.microsoft.azure.toolkit.lib.AzureConfiguration; import com.microsoft.azure.toolkit.lib.AzureService; import com.microsoft.azure.toolkit.lib.SubscriptionScoped; -import com.microsoft.azure.toolkit.lib.auth.Account; -import com.microsoft.azure.toolkit.lib.auth.AzureAccount; import com.microsoft.azure.toolkit.lib.common.cache.Cacheable; import com.microsoft.azure.toolkit.lib.common.cache.Preload; import com.microsoft.azure.toolkit.lib.common.exception.AzureToolkitRuntimeException; @@ -96,27 +88,4 @@ private static ResourceGroup fromResource(@Nonnull com.azure.resourcemanager.res String id = resource.id(); return ResourceGroup.builder().subscriptionId(subscriptionId).id(id).name(name).region(region).build(); } - - @Cacheable(cacheName = "resource/{}/manager", key = "$subscriptionId") - private ResourceManager getResourceManager(String subscriptionId) { - final Account account = Azure.az(AzureAccount.class).account(); - final AzureConfiguration config = Azure.az().config(); - final String userAgent = config.getUserAgent(); - final HttpLogDetailLevel logDetailLevel = config.getLogLevel() == null ? - HttpLogDetailLevel.NONE : HttpLogDetailLevel.valueOf(config.getLogLevel()); - final AzureProfile azureProfile = new AzureProfile(account.getEnvironment()); - return ResourceManager.configure() - .withLogLevel(logDetailLevel) - .withPolicy(getUserAgentPolicy(userAgent)) // set user agent with policy - .authenticate(account.getTokenCredential(subscriptionId), azureProfile) - .withSubscription(subscriptionId); - } - - private HttpPipelinePolicy getUserAgentPolicy(String userAgent) { - return (httpPipelineCallContext, httpPipelineNextPolicy) -> { - final String previousUserAgent = httpPipelineCallContext.getHttpRequest().getHeaders().getValue("User-Agent"); - httpPipelineCallContext.getHttpRequest().setHeader("User-Agent", String.format("%s %s", userAgent, previousUserAgent)); - return httpPipelineNextPolicy.process(); - }; - } } diff --git a/azure-toolkit-libs/azure-toolkit-sqlserver-lib/src/main/java/com/microsoft/azure/toolkit/lib/sqlserver/AzureSqlServer.java b/azure-toolkit-libs/azure-toolkit-sqlserver-lib/src/main/java/com/microsoft/azure/toolkit/lib/sqlserver/AzureSqlServer.java index 2520404565..73321cd859 100644 --- a/azure-toolkit-libs/azure-toolkit-sqlserver-lib/src/main/java/com/microsoft/azure/toolkit/lib/sqlserver/AzureSqlServer.java +++ b/azure-toolkit-libs/azure-toolkit-sqlserver-lib/src/main/java/com/microsoft/azure/toolkit/lib/sqlserver/AzureSqlServer.java @@ -8,15 +8,12 @@ import com.azure.resourcemanager.sql.SqlServerManager; import com.azure.resourcemanager.sql.models.CapabilityStatus; import com.azure.resourcemanager.sql.models.CheckNameAvailabilityResult; -import com.microsoft.azure.toolkit.lib.Azure; import com.microsoft.azure.toolkit.lib.AzureService; import com.microsoft.azure.toolkit.lib.SubscriptionScoped; -import com.microsoft.azure.toolkit.lib.auth.AzureAccount; import com.microsoft.azure.toolkit.lib.common.entity.CheckNameAvailabilityResultEntity; import com.microsoft.azure.toolkit.lib.common.entity.IAzureResourceEntity; import com.microsoft.azure.toolkit.lib.common.event.AzureOperationEvent; import com.microsoft.azure.toolkit.lib.common.exception.AzureToolkitRuntimeException; -import com.microsoft.azure.toolkit.lib.common.model.Region; import com.microsoft.azure.toolkit.lib.common.model.Subscription; import com.microsoft.azure.toolkit.lib.common.operation.AzureOperation; import com.microsoft.azure.toolkit.lib.common.task.ICommittable; @@ -75,10 +72,6 @@ public boolean checkRegionCapability(String subscriptionId, String region) { return Objects.nonNull(capabilities.status()) && CapabilityStatus.AVAILABLE == capabilities.status(); } - public List listSupportedRegions(String subscriptionId) { - return Azure.az(AzureAccount.class).listSupportedRegions(subscriptionId, "Microsoft.SQL", "servers"); - } - private String getSubscriptionFromResourceEntity(@Nonnull IAzureResourceEntity resourceEntity) { if (StringUtils.isNotEmpty(resourceEntity.getId())) { return ResourceId.fromString(resourceEntity.getId()).subscriptionId(); @@ -122,4 +115,7 @@ public AzureOperationEvent.Source getEventSource() { } } + public String name() { + return "Microsoft.SQL/servers"; + } } diff --git a/azure-toolkit-libs/azure-toolkit-storage-lib/src/main/java/com/microsoft/azure/toolkit/lib/storage/service/AzureStorageAccount.java b/azure-toolkit-libs/azure-toolkit-storage-lib/src/main/java/com/microsoft/azure/toolkit/lib/storage/service/AzureStorageAccount.java index 0c7e987f7c..4469d5b97c 100644 --- a/azure-toolkit-libs/azure-toolkit-storage-lib/src/main/java/com/microsoft/azure/toolkit/lib/storage/service/AzureStorageAccount.java +++ b/azure-toolkit-libs/azure-toolkit-storage-lib/src/main/java/com/microsoft/azure/toolkit/lib/storage/service/AzureStorageAccount.java @@ -12,16 +12,13 @@ import com.azure.resourcemanager.storage.models.Reason; import com.azure.resourcemanager.storage.models.SkuName; import com.azure.resourcemanager.storage.models.StorageAccountSkuType; -import com.microsoft.azure.toolkit.lib.Azure; import com.microsoft.azure.toolkit.lib.AzureService; import com.microsoft.azure.toolkit.lib.SubscriptionScoped; -import com.microsoft.azure.toolkit.lib.auth.AzureAccount; import com.microsoft.azure.toolkit.lib.common.cache.CacheEvict; import com.microsoft.azure.toolkit.lib.common.cache.CacheManager; import com.microsoft.azure.toolkit.lib.common.cache.Cacheable; import com.microsoft.azure.toolkit.lib.common.entity.CheckNameAvailabilityResultEntity; import com.microsoft.azure.toolkit.lib.common.event.AzureOperationEvent; -import com.microsoft.azure.toolkit.lib.common.model.Region; import com.microsoft.azure.toolkit.lib.common.model.Subscription; import com.microsoft.azure.toolkit.lib.common.operation.AzureOperation; import com.microsoft.azure.toolkit.lib.common.task.ICommittable; @@ -85,10 +82,6 @@ public CheckNameAvailabilityResultEntity checkNameAvailability(String subscripti Optional.ofNullable(result.reason()).map(Reason::toString).orElse(null), result.message()); } - public List listSupportedRegions(String subscriptionId) { - return Azure.az(AzureAccount.class).listSupportedRegions(subscriptionId, "Microsoft.Storage", "storageAccounts"); - } - public List listSupportedPerformances() { return Performance.values(); } @@ -154,4 +147,7 @@ public AzureOperationEvent.Source getEventSource() { } } + public String name() { + return "Microsoft.Storage/storageAccounts"; + } } From defac12ca0bccf2e269c11b0c89f3a60491a3537 Mon Sep 17 00:00:00 2001 From: Mingliang Wang Date: Sun, 19 Sep 2021 23:31:10 +0800 Subject: [PATCH 058/126] fix to comments --- .../lib/storage/service/StorageAccount.java | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/azure-toolkit-libs/azure-toolkit-storage-lib/src/main/java/com/microsoft/azure/toolkit/lib/storage/service/StorageAccount.java b/azure-toolkit-libs/azure-toolkit-storage-lib/src/main/java/com/microsoft/azure/toolkit/lib/storage/service/StorageAccount.java index a1a5ed3e87..ed720e2de5 100644 --- a/azure-toolkit-libs/azure-toolkit-storage-lib/src/main/java/com/microsoft/azure/toolkit/lib/storage/service/StorageAccount.java +++ b/azure-toolkit-libs/azure-toolkit-storage-lib/src/main/java/com/microsoft/azure/toolkit/lib/storage/service/StorageAccount.java @@ -5,9 +5,10 @@ package com.microsoft.azure.toolkit.lib.storage.service; +import com.azure.core.management.AzureEnvironment; import com.azure.core.management.exception.ManagementException; +import com.azure.resourcemanager.resources.fluentcore.utils.ResourceManagerUtils; import com.azure.resourcemanager.storage.StorageManager; -import com.azure.resourcemanager.storage.models.StorageAccountKey; import com.microsoft.azure.toolkit.lib.Azure; import com.microsoft.azure.toolkit.lib.auth.AzureCloud; import com.microsoft.azure.toolkit.lib.common.entity.AbstractAzureResource; @@ -16,11 +17,9 @@ import com.microsoft.azure.toolkit.lib.common.event.AzureOperationEvent; import com.microsoft.azure.toolkit.lib.common.operation.AzureOperation; import com.microsoft.azure.toolkit.lib.storage.model.StorageAccountEntity; -import org.apache.commons.lang3.StringUtils; import org.apache.http.HttpStatus; import javax.annotation.Nonnull; -import java.util.List; import java.util.Objects; public class StorageAccount extends AbstractAzureResource @@ -58,16 +57,14 @@ public void delete() { @AzureOperation(name = "storage|account.get_connection_string", params = {"this.entity().getName()"}, type = AzureOperation.Type.SERVICE) public String getConnectionString() { - // refer https://github.com/Azure/azure-cli/blob/ac3b190d4d/src/azure-cli/azure/cli/command_modules/storage/operations/account.py#L232 - final String suffix = Azure.az(AzureCloud.class).get().getStorageEndpointSuffix(); - return String.format("DefaultEndpointsProtocol=https;EndpointSuffix=%s;AccountName=%s;AccountKey=%s", - suffix, this.name(), getKey()); + // see https://github.com/Azure/azure-cli/blob/ac3b190d4d/src/azure-cli/azure/cli/command_modules/storage/operations/account.py#L232 + final AzureEnvironment environment = Azure.az(AzureCloud.class).get(); + return ResourceManagerUtils.getStorageConnectionString(this.name(), getKey(), environment); } @AzureOperation(name = "storage|account.get_key", params = {"this.entity().getName()"}, type = AzureOperation.Type.SERVICE) public String getKey() { - final List keys = Objects.requireNonNull(this.remote()).getKeys(); - return StringUtils.equalsIgnoreCase(keys.get(0).keyName(), "primary") ? keys.get(0).value() : keys.get(1).value(); + return Objects.requireNonNull(this.remote()).getKeys().get(0).keyName(); } @Override From 51a1efb05f9df7ab5e146d38748c980ae78f8fa4 Mon Sep 17 00:00:00 2001 From: Hanxiao Liu Date: Wed, 15 Sep 2021 16:11:54 +0800 Subject: [PATCH 059/126] Migrate to use web app create/deploy task in web app maven plugin --- .../lib/appservice/task/DeployWebAppTask.java | 20 +- .../maven/webapp/AbstractWebAppMojo.java | 10 +- .../azure/maven/webapp/ConfigMojo.java | 3 +- .../azure/maven/webapp/DeployMojo.java | 265 +++--------------- .../configuration/DeploymentSlotConfig.java | 21 ++ .../maven/webapp/parser/ConfigParser.java | 202 +++++++------ 6 files changed, 194 insertions(+), 327 deletions(-) create mode 100644 azure-webapp-maven-plugin/src/main/java/com/microsoft/azure/maven/webapp/configuration/DeploymentSlotConfig.java diff --git a/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/task/DeployWebAppTask.java b/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/task/DeployWebAppTask.java index 9de0cceb9e..c2d9136196 100644 --- a/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/task/DeployWebAppTask.java +++ b/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/task/DeployWebAppTask.java @@ -6,7 +6,7 @@ package com.microsoft.azure.toolkit.lib.appservice.task; import com.microsoft.azure.toolkit.lib.appservice.model.WebAppArtifact; -import com.microsoft.azure.toolkit.lib.appservice.service.IWebApp; +import com.microsoft.azure.toolkit.lib.appservice.service.IWebAppBase; 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; @@ -18,7 +18,7 @@ import java.util.concurrent.TimeUnit; import java.util.stream.Collectors; -public class DeployWebAppTask extends AzureTask { +public class DeployWebAppTask extends AzureTask> { private static final String SKIP_DEPLOYMENT_FOR_DOCKER_APP_SERVICE = "Skip deployment for docker webapp, " + "you can navigate to %s to access your docker webapp."; private static final String DEPLOY_START = "Trying to deploy artifact to %s..."; @@ -28,15 +28,15 @@ public class DeployWebAppTask extends AzureTask { private static final String STOP_APP_DONE = "Successfully stopped Web App."; private static final String START_APP_DONE = "Successfully started Web App."; private static final String RUNNING = "Running"; - private IWebApp webApp; - private List artifacts; - private boolean isStopAppDuringDeployment; + private final IWebAppBase webApp; + private final List artifacts; + private final boolean isStopAppDuringDeployment; - public DeployWebAppTask(IWebApp webApp, List artifacts) { + public DeployWebAppTask(IWebAppBase webApp, List artifacts) { this(webApp, artifacts, false); } - public DeployWebAppTask(IWebApp webApp, List artifacts, boolean isStopAppDuringDeployment) { + public DeployWebAppTask(IWebAppBase webApp, List artifacts, boolean isStopAppDuringDeployment) { this.webApp = webApp; this.artifacts = artifacts; this.isStopAppDuringDeployment = isStopAppDuringDeployment; @@ -44,7 +44,7 @@ public DeployWebAppTask(IWebApp webApp, List artifacts, boolean @Override @AzureOperation(name = "webapp.deploy", params = {"this.webApp.entity().getName()"}, type = AzureOperation.Type.SERVICE) - public IWebApp execute() { + public IWebAppBase execute() { if (webApp.getRuntime().isDocker()) { AzureMessager.getMessager().info(AzureString.format(SKIP_DEPLOYMENT_FOR_DOCKER_APP_SERVICE, "https://" + webApp.hostName())); return webApp; @@ -73,7 +73,7 @@ private void deployArtifacts() { artifactsOneDeploy.forEach(resource -> webApp.deploy(resource.getDeployType(), resource.getFile(), resource.getPath())); } - private static void stopAppService(IWebApp target) { + private static void stopAppService(IWebAppBase target) { AzureMessager.getMessager().info(STOP_APP); target.stop(); // workaround for the resources release problem. @@ -86,7 +86,7 @@ private static void stopAppService(IWebApp target) { AzureMessager.getMessager().info(STOP_APP_DONE); } - private static void startAppService(IWebApp target) { + private static void startAppService(IWebAppBase target) { if (!StringUtils.equalsIgnoreCase(target.state(), RUNNING)) { AzureMessager.getMessager().info(START_APP); target.start(); diff --git a/azure-webapp-maven-plugin/src/main/java/com/microsoft/azure/maven/webapp/AbstractWebAppMojo.java b/azure-webapp-maven-plugin/src/main/java/com/microsoft/azure/maven/webapp/AbstractWebAppMojo.java index be08a72270..539ddd161c 100644 --- a/azure-webapp-maven-plugin/src/main/java/com/microsoft/azure/maven/webapp/AbstractWebAppMojo.java +++ b/azure-webapp-maven-plugin/src/main/java/com/microsoft/azure/maven/webapp/AbstractWebAppMojo.java @@ -136,7 +136,7 @@ public abstract class AbstractWebAppMojo extends AbstractAppServiceMojo { private boolean isRuntimeInjected = false; @JsonIgnore - private WebAppConfig config; + protected ConfigParser configParser; //endregion @@ -238,11 +238,11 @@ protected void validateConfiguration(Consumer validationMessa } } - protected synchronized WebAppConfig getWebAppConfig() throws AzureExecutionException { - if (config == null) { - config = new ConfigParser(this).parse(); + public ConfigParser getConfigParser() { + if (configParser == null) { + configParser = new ConfigParser(this); } - return config; + return configParser; } @Override diff --git a/azure-webapp-maven-plugin/src/main/java/com/microsoft/azure/maven/webapp/ConfigMojo.java b/azure-webapp-maven-plugin/src/main/java/com/microsoft/azure/maven/webapp/ConfigMojo.java index 5e914db580..6a49a97a54 100644 --- a/azure-webapp-maven-plugin/src/main/java/com/microsoft/azure/maven/webapp/ConfigMojo.java +++ b/azure-webapp-maven-plugin/src/main/java/com/microsoft/azure/maven/webapp/ConfigMojo.java @@ -14,7 +14,6 @@ import com.microsoft.azure.maven.webapp.configuration.SchemaVersion; import com.microsoft.azure.maven.webapp.handlers.WebAppPomHandler; import com.microsoft.azure.maven.webapp.models.WebAppOption; -import com.microsoft.azure.maven.webapp.parser.ConfigParser; import com.microsoft.azure.toolkit.lib.Azure; import com.microsoft.azure.toolkit.lib.appservice.AzureAppService; import com.microsoft.azure.toolkit.lib.appservice.model.JavaVersion; @@ -466,7 +465,7 @@ private boolean isJarProject() { private WebAppConfiguration getWebAppConfiguration() { validateConfiguration(message -> AzureMessager.getMessager().warning(message.getMessage()), false); - return new ConfigParser(this).getWebAppConfiguration(); + return getConfigParser().getWebAppConfiguration(); } private WebAppConfiguration chooseExistingWebappForConfiguration() diff --git a/azure-webapp-maven-plugin/src/main/java/com/microsoft/azure/maven/webapp/DeployMojo.java b/azure-webapp-maven-plugin/src/main/java/com/microsoft/azure/maven/webapp/DeployMojo.java index 92b852ced2..ac66934b5e 100644 --- a/azure-webapp-maven-plugin/src/main/java/com/microsoft/azure/maven/webapp/DeployMojo.java +++ b/azure-webapp-maven-plugin/src/main/java/com/microsoft/azure/maven/webapp/DeployMojo.java @@ -6,67 +6,37 @@ package com.microsoft.azure.maven.webapp; import com.microsoft.azure.maven.model.DeploymentResource; -import com.microsoft.azure.maven.webapp.utils.DeployUtils; +import com.microsoft.azure.maven.webapp.configuration.DeploymentSlotConfig; +import com.microsoft.azure.maven.webapp.utils.FTPUtils; import com.microsoft.azure.maven.webapp.utils.Utils; -import com.microsoft.azure.maven.webapp.utils.WebAppUtils; -import com.microsoft.azure.toolkit.lib.appservice.model.DeployType; +import com.microsoft.azure.toolkit.lib.appservice.model.PublishingProfile; import com.microsoft.azure.toolkit.lib.appservice.model.WebAppArtifact; -import com.microsoft.azure.toolkit.lib.appservice.model.WebContainer; import com.microsoft.azure.toolkit.lib.appservice.service.IAppService; -import com.microsoft.azure.toolkit.lib.appservice.service.IAppServicePlan; import com.microsoft.azure.toolkit.lib.appservice.service.IWebApp; import com.microsoft.azure.toolkit.lib.appservice.service.IWebAppBase; import com.microsoft.azure.toolkit.lib.appservice.service.IWebAppDeploymentSlot; +import com.microsoft.azure.toolkit.lib.appservice.task.CreateOrUpdateWebAppTask; +import com.microsoft.azure.toolkit.lib.appservice.task.DeployWebAppTask; import com.microsoft.azure.toolkit.lib.common.bundle.AzureString; -import com.microsoft.azure.toolkit.lib.common.entity.CheckNameAvailabilityResultEntity; import com.microsoft.azure.toolkit.lib.common.exception.AzureExecutionException; -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.model.ResourceGroup; -import com.microsoft.azure.toolkit.lib.resource.task.CreateResourceGroupTask; -import org.apache.commons.collections4.CollectionUtils; -import org.apache.commons.io.FileUtils; -import org.apache.commons.lang3.StringUtils; +import org.apache.commons.net.ftp.FTPClient; import org.apache.maven.plugins.annotations.LifecyclePhase; import org.apache.maven.plugins.annotations.Mojo; -import org.zeroturnaround.zip.ZipUtil; import java.io.File; import java.io.IOException; -import java.nio.file.Files; -import java.util.ArrayList; -import java.util.Collections; import java.util.List; -import java.util.Objects; -import java.util.UUID; -import java.util.function.Predicate; -import java.util.stream.Collectors; /** * Deploy an Azure Web App, either Windows-based or Linux-based. */ @Mojo(name = "deploy", defaultPhase = LifecyclePhase.DEPLOY) public class DeployMojo extends AbstractWebAppMojo { - private static final String CREATE_WEBAPP = "Creating web app %s..."; - private static final String CREATE_WEB_APP_DONE = "Successfully created Web App %s."; - private static final String UPDATE_WEBAPP = "Updating target Web App %s..."; - private static final String UPDATE_WEBAPP_DONE = "Successfully updated Web App %s."; - private static final String CREATE_RESOURCE_GROUP = "Creating resource group %s in region %s..."; - private static final String CREATE_RESOURCE_GROUP_DONE = "Successfully created resource group %s."; - private static final String CREATE_APP_SERVICE_PLAN = "Creating app service plan..."; - private static final String CREATE_APP_SERVICE_DONE = "Successfully created app service plan %s."; private static final String WEBAPP_NOT_EXIST_FOR_SLOT = "The Web App specified in pom.xml does not exist. " + "Please make sure the Web App name is correct."; private static final String CREATE_DEPLOYMENT_SLOT = "Creating deployment slot %s in web app %s"; private static final String CREATE_DEPLOYMENT_SLOT_DONE = "Successfully created the Deployment Slot."; - private static final String DEPLOY_START = "Trying to deploy artifact to %s..."; - private static final String DEPLOY_FINISH = "Successfully deployed the artifact to https://%s"; - private static final String SKIP_DEPLOYMENT_FOR_DOCKER_APP_SERVICE = "Skip deployment for docker app service"; - private static final String NO_RUNTIME_CONFIG = "You need to specified in pom.xml for creating azure webapps."; - private static final String CREATE_NEW_APP_SERVICE_PLAN = "createNewAppServicePlan"; - private static final String CREATE_NEW_RESOURCE_GROUP = "createNewResourceGroup"; - private static final String CREATE_NEW_WEB_APP = "createNewWebApp"; private static final String CREATE_NEW_DEPLOYMENT_SLOT = "createNewDeploymentSlot"; @Override @@ -74,225 +44,72 @@ protected void doExecute() throws AzureExecutionException { validateConfiguration(message -> AzureMessager.getMessager().error(message.getMessage()), true); // initialize library client az = getOrCreateAzureAppServiceClient(); - - final WebAppConfig config = getWebAppConfig(); - final IWebAppBase target = createOrUpdateResource(config); - deploy(target, config); + final IWebAppBase target = createOrUpdateResource(); + deployExternalResources(target, getConfigParser().getExternalArtifacts()); + deploy(target, getConfigParser().getArtifacts()); } - private IWebAppBase createOrUpdateResource(final WebAppConfig config) throws AzureExecutionException { - if (StringUtils.isEmpty(config.getDeploymentSlotName())) { - final IWebApp webApp = getWebApp(config); - return webApp.exists() ? updateWebApp(webApp, config) : createWebApp(webApp, config); + private IWebAppBase createOrUpdateResource() throws AzureExecutionException { + if (!isDeployToDeploymentSlot()) { + return new CreateOrUpdateWebAppTask(getConfigParser().getAppServiceConfig()).execute(); } else { + // todo: New CreateOrUpdateDeploymentSlotTask + final DeploymentSlotConfig config = getConfigParser().getDeploymentSlotConfig(); final IWebAppDeploymentSlot slot = getDeploymentSlot(config); return slot.exists() ? updateDeploymentSlot(slot, config) : createDeploymentSlot(slot, config); } } - private IWebApp getWebApp(final WebAppConfig config) { - return az.webapp(config.getResourceGroup(), config.getAppName()); - } - - private IWebAppDeploymentSlot getDeploymentSlot(final WebAppConfig config) throws AzureExecutionException { - final IWebApp webApp = getWebApp(config); + private IWebAppDeploymentSlot getDeploymentSlot(final DeploymentSlotConfig config) throws AzureExecutionException { + final IWebApp webApp = az.webapp(config.getResourceGroup(), config.getAppName()); if (!webApp.exists()) { throw new AzureExecutionException(WEBAPP_NOT_EXIST_FOR_SLOT); } - return webApp.deploymentSlot(config.getDeploymentSlotName()); - } - - private IWebApp createWebApp(final IWebApp webApp, final WebAppConfig webAppConfig) throws AzureExecutionException { - if (webAppConfig.getRuntime() == null) { - throw new AzureExecutionException(NO_RUNTIME_CONFIG); - } - - CheckNameAvailabilityResultEntity checkNameResult = az.checkNameAvailability(webAppConfig.getSubscriptionId(), webAppConfig.getAppName()); - if (!checkNameResult.isAvailable()) { - throw new AzureToolkitRuntimeException(AzureString.format("Cannot create webapp {0} due to error: {1}", - webAppConfig.getAppName(), - checkNameResult.getUnavailabilityReason()).getString()); - } - - getTelemetryProxy().addDefaultProperty(CREATE_NEW_WEB_APP, String.valueOf(true)); - final ResourceGroup resourceGroup = getOrCreateResourceGroup(webAppConfig); - final IAppServicePlan appServicePlan = getOrCreateAppServicePlan(webAppConfig); - AzureMessager.getMessager().info(String.format(CREATE_WEBAPP, webAppConfig.getAppName())); - final IWebApp result = webApp.create().withName(webAppConfig.getAppName()) - .withResourceGroup(resourceGroup.getName()) - .withPlan(appServicePlan.id()) - .withRuntime(webAppConfig.getRuntime()) - .withDockerConfiguration(webAppConfig.getDockerConfiguration()) - .withAppSettings(webAppConfig.getAppSettings()) - .commit(); - AzureMessager.getMessager().info(String.format(CREATE_WEB_APP_DONE, result.name())); - return result; - } - - private IWebApp updateWebApp(final IWebApp webApp, final WebAppConfig webAppConfig) { - // update app service plan - AzureMessager.getMessager().info(String.format(UPDATE_WEBAPP, webApp.name())); - final IAppServicePlan currentPlan = webApp.plan(); - IAppServicePlan targetServicePlan = StringUtils.isEmpty(webAppConfig.getServicePlanName()) ? currentPlan : - az.appServicePlan(getServicePlanResourceGroup(webAppConfig), webAppConfig.getServicePlanName()); - if (!targetServicePlan.exists()) { - targetServicePlan = getOrCreateAppServicePlan(webAppConfig); - } else { - if (region != null && !Objects.equals(Region.fromName(region), Region.fromName(targetServicePlan.entity().getRegion()))) { - AzureMessager.getMessager().warning(String.format("Skip region update for existing service plan '%s' since it is not allowed.", - targetServicePlan.name())); - } - - if (webAppConfig.getPricingTier() != null) { - targetServicePlan.update().withPricingTier(webAppConfig.getPricingTier()).commit(); - } - } - - final IWebApp result = webApp.update().withPlan(targetServicePlan.id()) - .withRuntime(webAppConfig.getRuntime()) - .withDockerConfiguration(webAppConfig.getDockerConfiguration()) - .withAppSettings(webAppConfig.getAppSettings()) - .commit(); - AzureMessager.getMessager().info(String.format(UPDATE_WEBAPP_DONE, webApp.name())); - return result; - } - - private ResourceGroup getOrCreateResourceGroup(final WebAppConfig webAppConfig) { - // todo: Extract resource group logic to library - return new CreateResourceGroupTask(webAppConfig.getSubscriptionId(), webAppConfig.getResourceGroup(), webAppConfig.getRegion()).execute(); - } - - private IAppServicePlan getOrCreateAppServicePlan(final WebAppConfig webAppConfig) { - final String servicePlanName = StringUtils.isEmpty(webAppConfig.getServicePlanName()) ? - getNewAppServicePlanName(webAppConfig) : webAppConfig.getServicePlanName(); - final String servicePlanGroup = getServicePlanResourceGroup(webAppConfig); - final IAppServicePlan appServicePlan = az.appServicePlan(servicePlanGroup, servicePlanName); - if (!appServicePlan.exists()) { - AzureMessager.getMessager().info(CREATE_APP_SERVICE_PLAN); - getTelemetryProxy().addDefaultProperty(CREATE_NEW_APP_SERVICE_PLAN, String.valueOf(true)); - appServicePlan.create() - .withName(servicePlanName) - .withResourceGroup(servicePlanGroup) - .withRegion(webAppConfig.getRegion()) - .withPricingTier(webAppConfig.getPricingTier()) - .withOperatingSystem(webAppConfig.getRuntime().getOperatingSystem()) - .commit(); - AzureMessager.getMessager().info(String.format(CREATE_APP_SERVICE_DONE, appServicePlan.name())); - } - return appServicePlan; + return webApp.deploymentSlot(config.getName()); } - private String getNewAppServicePlanName(final WebAppConfig webAppConfig) { - return StringUtils.isEmpty(webAppConfig.getServicePlanName()) ? String.format("asp-%s", webAppConfig.getAppName()) : - webAppConfig.getServicePlanName(); - } - - private String getServicePlanResourceGroup(final WebAppConfig webAppConfig) { - return StringUtils.isEmpty(webAppConfig.getServicePlanResourceGroup()) ? webAppConfig.getResourceGroup() : - webAppConfig.getServicePlanResourceGroup(); - } - - private IWebAppDeploymentSlot createDeploymentSlot(final IWebAppDeploymentSlot slot, final WebAppConfig webAppConfig) { - AzureMessager.getMessager().info(String.format(CREATE_DEPLOYMENT_SLOT, webAppConfig.getDeploymentSlotName(), webAppConfig.getAppName())); + private IWebAppDeploymentSlot createDeploymentSlot(final IWebAppDeploymentSlot slot, final DeploymentSlotConfig slotConfig) { + AzureMessager.getMessager().info(AzureString.format(CREATE_DEPLOYMENT_SLOT, slotConfig.getName(), slotConfig.getAppName())); getTelemetryProxy().addDefaultProperty(CREATE_NEW_DEPLOYMENT_SLOT, String.valueOf(true)); - final IWebAppDeploymentSlot result = slot.create().withName(webAppConfig.getDeploymentSlotName()) - .withConfigurationSource(webAppConfig.getDeploymentSlotConfigurationSource()) - .withAppSettings(webAppConfig.getAppSettings()) + final IWebAppDeploymentSlot result = slot.create().withName(slotConfig.getName()) + .withConfigurationSource(slotConfig.getConfigurationSource()) + .withAppSettings(slotConfig.getAppSettings()) .commit(); AzureMessager.getMessager().info(CREATE_DEPLOYMENT_SLOT_DONE); return result; } - private void deploy(IWebAppBase target, WebAppConfig config) throws AzureExecutionException { - if (target.getRuntime().isDocker()) { - AzureMessager.getMessager().info(SKIP_DEPLOYMENT_FOR_DOCKER_APP_SERVICE); - return; - } - try { - AzureMessager.getMessager().info(String.format(DEPLOY_START, config.getAppName())); - if (isStopAppDuringDeployment()) { - WebAppUtils.stopAppService(target); - } - deployArtifacts(target, config); - deployExternalResources(target); - AzureMessager.getMessager().info(String.format(DEPLOY_FINISH, target.hostName())); - } finally { - WebAppUtils.startAppService(target); - } - } - // update existing slot is not supported in current version, will implement it later - private IWebAppDeploymentSlot updateDeploymentSlot(final IWebAppDeploymentSlot slot, final WebAppConfig webAppConfig) { + private IWebAppDeploymentSlot updateDeploymentSlot(final IWebAppDeploymentSlot slot, final DeploymentSlotConfig slotConfig) { return slot; } - private void deployArtifacts(IWebAppBase target, WebAppConfig config) throws AzureExecutionException { - final List artifactsOneDeploy = config.getWebAppArtifacts().stream() - .filter(artifact -> artifact.getDeployType() != null) - .collect(Collectors.toList()); - artifactsOneDeploy.forEach(resource -> target.deploy(resource.getDeployType(), resource.getFile(), resource.getPath())); - - // This is the codes for one deploy API, for current release, will replace it with zip all files and deploy with zip deploy - final List artifacts = config.getWebAppArtifacts().stream() - .filter(artifact -> artifact.getDeployType() == null) - .collect(Collectors.toList()); - - if (CollectionUtils.isEmpty(artifacts)) { - return; - } - // call correspond deploy method when deploy artifact only - if (artifacts.size() == 1) { - final WebAppArtifact artifact = artifacts.get(0); - final DeployType deployType = DeployType.getDeployTypeFromFile(artifact.getFile()); - target.deploy(deployType, artifact.getFile(), artifact.getPath()); - return; - } - // Support deploy multi war to different paths - if (DeployUtils.isAllWarArtifacts(artifacts)) { - artifacts.forEach(resource -> target.deploy(DeployType.getDeployTypeFromFile(resource.getFile()), resource.getFile(), resource.getPath())); - return; - } - // package all resource and do zip deploy - // todo: migrate to use one deploy - deployArtifactsWithZipDeploy(target, artifacts); + private void deploy(IWebAppBase target, List artifacts) { + new DeployWebAppTask(target, artifacts, isStopAppDuringDeployment()).execute(); } - private void deployArtifactsWithZipDeploy(IWebAppBase target, List artifacts) throws AzureExecutionException { - final File stagingDirectory = prepareStagingDirectory(artifacts); - // Rename jar once java_se runtime - if (Objects.equals(target.getRuntime().getWebContainer(), WebContainer.JAVA_SE)) { - final List files = new ArrayList<>(FileUtils.listFiles(stagingDirectory, null, true)); - DeployUtils.prepareJavaSERuntimeJarArtifact(files, project.getBuild().getFinalName()); + private void deployExternalResources(final IAppService target, final List resources) throws AzureExecutionException { + if (resources.isEmpty()) { + return; } - final File zipFile = Utils.createTempFile(appName + UUID.randomUUID(), ".zip"); - ZipUtil.pack(stagingDirectory, zipFile); - // Deploy zip with zip deploy - target.deploy(DeployType.ZIP, zipFile); - } - - private static File prepareStagingDirectory(List webAppArtifacts) throws AzureExecutionException { + AzureMessager.getMessager().info(AzureString.format("Uploading resources to %s", target.name())); + final PublishingProfile publishingProfile = target.getPublishingProfile(); + final String serverUrl = publishingProfile.getFtpUrl().split("/", 2)[0]; try { - final File stagingDirectory = Files.createTempDirectory("azure-functions").toFile(); - FileUtils.forceDeleteOnExit(stagingDirectory); - // Copy maven artifacts to staging folder - for (final WebAppArtifact webAppArtifact : webAppArtifacts) { - final File targetFolder = StringUtils.isEmpty(webAppArtifact.getPath()) ? stagingDirectory : - new File(stagingDirectory, webAppArtifact.getPath()); - FileUtils.copyFileToDirectory(webAppArtifact.getFile(), targetFolder); + final FTPClient ftpClient = FTPUtils.getFTPClient(serverUrl, publishingProfile.getFtpUsername(), publishingProfile.getFtpPassword()); + for (final DeploymentResource externalResource : resources) { + uploadResource(externalResource, ftpClient); } - return stagingDirectory; } catch (IOException e) { - throw new AzureExecutionException("Failed to package resources", e); + throw new AzureExecutionException(e.getMessage(), e); } } - private void deployExternalResources(IAppService target) throws AzureExecutionException { - DeployUtils.deployResourcesWithFtp(target, filterResources(DeploymentResource::isExternalResource)); - } - - private List filterResources(Predicate predicate) { - final List resources = this.deployment == null ? Collections.emptyList() : this.deployment.getResources(); - return resources.stream() - .filter(predicate).collect(Collectors.toList()); + private static void uploadResource(DeploymentResource resource, FTPClient ftpClient) throws IOException { + final List files = Utils.getArtifacts(resource); + final String target = resource.getAbsoluteTargetPath(); + for (final File file : files) { + FTPUtils.uploadFile(ftpClient, file.getPath(), target); + } } } diff --git a/azure-webapp-maven-plugin/src/main/java/com/microsoft/azure/maven/webapp/configuration/DeploymentSlotConfig.java b/azure-webapp-maven-plugin/src/main/java/com/microsoft/azure/maven/webapp/configuration/DeploymentSlotConfig.java new file mode 100644 index 0000000000..fe5d19dc95 --- /dev/null +++ b/azure-webapp-maven-plugin/src/main/java/com/microsoft/azure/maven/webapp/configuration/DeploymentSlotConfig.java @@ -0,0 +1,21 @@ +/* + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + */ +package com.microsoft.azure.maven.webapp.configuration; + +import lombok.Builder; +import lombok.Getter; + +import java.util.Map; + +@Getter +@Builder +public class DeploymentSlotConfig { + private final String subscriptionId; + private final String resourceGroup; + private final String appName; + private final String name; + private final String configurationSource; + private final Map appSettings; +} diff --git a/azure-webapp-maven-plugin/src/main/java/com/microsoft/azure/maven/webapp/parser/ConfigParser.java b/azure-webapp-maven-plugin/src/main/java/com/microsoft/azure/maven/webapp/parser/ConfigParser.java index 07d8777963..d2d385bd0a 100644 --- a/azure-webapp-maven-plugin/src/main/java/com/microsoft/azure/maven/webapp/parser/ConfigParser.java +++ b/azure-webapp-maven-plugin/src/main/java/com/microsoft/azure/maven/webapp/parser/ConfigParser.java @@ -9,12 +9,13 @@ import com.microsoft.azure.maven.model.DeploymentResource; import com.microsoft.azure.maven.utils.MavenArtifactUtils; import com.microsoft.azure.maven.webapp.AbstractWebAppMojo; -import com.microsoft.azure.maven.webapp.WebAppConfig; import com.microsoft.azure.maven.webapp.WebAppConfiguration; import com.microsoft.azure.maven.webapp.configuration.Deployment; +import com.microsoft.azure.maven.webapp.configuration.DeploymentSlotConfig; import com.microsoft.azure.maven.webapp.configuration.MavenRuntimeConfig; +import com.microsoft.azure.toolkit.lib.appservice.config.AppServiceConfig; +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.DockerConfiguration; 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.PricingTier; @@ -59,6 +60,87 @@ public ConfigParser(AbstractWebAppMojo mojo) { this.mojo = mojo; } + public AppServiceConfig getAppServiceConfig() throws AzureExecutionException { + return new AppServiceConfig() + .subscriptionId(getSubscriptionId()) + .resourceGroup(getResourceGroup()) + .appName(getAppName()) + .servicePlanName(getAppServicePlanName()) + .servicePlanResourceGroup(getAppServicePlanResourceGroup()) + .deploymentSlotName(getDeploymentSlotName()) + .deploymentSlotConfigurationSource(getDeploymentSlotConfigurationSource()) + .pricingTier(getPricingTier()) + .region(getRegion()) + .runtime(getRuntimeConfig()) + .appSettings(mojo.getAppSettings()); + } + + // todo: replace WebAppConfiguration with WebAppConfig + public WebAppConfiguration getWebAppConfiguration() { + WebAppConfiguration.WebAppConfigurationBuilder builder = WebAppConfiguration.builder(); + final Runtime runtime = getRuntime(); + final OperatingSystem os = Optional.ofNullable(runtime).map(Runtime::getOperatingSystem).orElse(null); + if (os == null) { + Log.debug("No runtime related config is specified. It will cause error if creating a new web app."); + } else { + switch (os) { + case WINDOWS: + case LINUX: + builder = builder.javaVersion(Objects.toString(runtime.getJavaVersion())).webContainer(Objects.toString(runtime.getWebContainer())); + break; + case DOCKER: + final MavenRuntimeConfig runtimeConfig = mojo.getRuntime(); + builder = builder.image(runtimeConfig.getImage()).serverId(runtimeConfig.getServerId()).registryUrl(runtimeConfig.getRegistryUrl()); + break; + default: + Log.debug("Invalid operating system from the configuration."); + } + } + return builder.appName(getAppName()) + .resourceGroup(getResourceGroup()) + .region(getRegion()) + .pricingTier(getPricingTier().getSize()) + .servicePlanName(mojo.getAppServicePlanName()) + .servicePlanResourceGroup(mojo.getAppServicePlanResourceGroup()) + .deploymentSlotSetting(mojo.getDeploymentSlotSetting()) + .os(os) + .mavenSettings(mojo.getSettings()) + .resources(Optional.ofNullable(mojo.getDeployment()).map(Deployment::getResources).orElse(null)) + .stagingDirectoryPath(mojo.getDeploymentStagingDirectoryPath()) + .buildDirectoryAbsolutePath(mojo.getBuildDirectoryAbsolutePath()) + .project(mojo.getProject()) + .session(mojo.getSession()) + .filtering(mojo.getMavenResourcesFiltering()) + .schemaVersion("v2") + .build(); + } + + public DeploymentSlotConfig getDeploymentSlotConfig() { + return DeploymentSlotConfig.builder() + .subscriptionId(getSubscriptionId()) + .resourceGroup(getResourceGroup()) + .appName(getAppName()) + .name(getDeploymentSlotName()) + .configurationSource(getDeploymentSlotConfigurationSource()) + .appSettings(mojo.getAppSettings()) + .build(); + } + + public List getArtifacts() throws AzureExecutionException { + if (mojo.getDeployment() == null || mojo.getDeployment().getResources() == null) { + return Collections.emptyList(); + } + return convertResourceToArtifacts(mojo.getDeployment().getResources()); + } + + public List getExternalArtifacts() { + if (mojo.getDeployment() == null || mojo.getDeployment().getResources() == null) { + return Collections.emptyList(); + } + return mojo.getDeployment().getResources().stream() + .filter(DeploymentResource::isExternalResource).collect(Collectors.toList()); + } + public String getAppName() { return mojo.getAppName(); } @@ -76,6 +158,9 @@ public String getDeploymentSlotConfigurationSource() { } public PricingTier getPricingTier() { + if (StringUtils.isEmpty(mojo.getPricingTier())) { + return null; + } return parseExpandableParameter(input -> { if (StringUtils.contains(mojo.getPricingTier(), "_")) { final String[] pricingParams = mojo.getPricingTier().split("_"); @@ -99,31 +184,10 @@ public String getSubscriptionId() { } public Region getRegion() { - return parseExpandableParameter(Region::fromName, mojo.getRegion(), EXPANDABLE_REGION_WARNING); - } - - public DockerConfiguration getDockerConfiguration() throws AzureExecutionException { - final MavenRuntimeConfig runtime = mojo.getRuntime(); - if (runtime == null) { + if (StringUtils.isEmpty(mojo.getRegion())) { return null; } - final OperatingSystem os = getOs(runtime); - if (os != OperatingSystem.DOCKER) { - return null; - } - final MavenDockerCredentialProvider credentialProvider = getDockerCredential(runtime.getServerId()); - return DockerConfiguration.builder() - .registryUrl(runtime.getRegistryUrl()) - .image(runtime.getImage()) - .userName(credentialProvider.getUsername()) - .password(credentialProvider.getPassword()).build(); - } - - public List getMavenArtifacts() throws AzureExecutionException { - if (mojo.getDeployment() == null || mojo.getDeployment().getResources() == null) { - return Collections.emptyList(); - } - return convertResourceToArtifacts(mojo.getDeployment().getResources()); + return parseExpandableParameter(Region::fromName, mojo.getRegion(), EXPANDABLE_REGION_WARNING); } public Runtime getRuntime() { @@ -135,8 +199,10 @@ public Runtime getRuntime() { if (os == OperatingSystem.DOCKER) { return Runtime.DOCKER; } - final JavaVersion javaVersion = parseExpandableParameter(JavaVersion::fromString, runtime.getJavaVersion(), EXPANDABLE_JAVA_VERSION_WARNING); - final WebContainer webContainer = parseExpandableParameter(WebContainer::fromString, runtime.getWebContainer(), EXPANDABLE_WEB_CONTAINER_WARNING); + final JavaVersion javaVersion = StringUtils.isEmpty(runtime.getJavaVersion()) ? null : + parseExpandableParameter(JavaVersion::fromString, runtime.getJavaVersion(), EXPANDABLE_JAVA_VERSION_WARNING); + final WebContainer webContainer = StringUtils.isEmpty(runtime.getWebContainer()) ? null : + parseExpandableParameter(WebContainer::fromString, runtime.getWebContainer(), EXPANDABLE_WEB_CONTAINER_WARNING); return Runtime.getRuntime(os, webContainer, javaVersion); } @@ -144,62 +210,29 @@ private OperatingSystem getOs(final MavenRuntimeConfig runtime) { return OperatingSystem.fromString(runtime.getOs()); } - public WebAppConfig parse() throws AzureExecutionException { - return WebAppConfig.builder() - .subscriptionId(getSubscriptionId()) - .appName(getAppName()) - .resourceGroup(getResourceGroup()) - .servicePlanName(getAppServicePlanName()) - .servicePlanResourceGroup(getAppServicePlanResourceGroup()) - .pricingTier(getPricingTier()) - .region(getRegion()) - .runtime(getRuntime()) - .dockerConfiguration(getDockerConfiguration()) - .deploymentSlotName(getDeploymentSlotName()) - .deploymentSlotConfigurationSource(getDeploymentSlotConfigurationSource()) - .webAppArtifacts(getMavenArtifacts()) - .appSettings(this.mojo.getAppSettings()) - .build(); + private RuntimeConfig getRuntimeConfig() throws AzureExecutionException { + final MavenRuntimeConfig runtime = mojo.getRuntime(); + if (runtime == null || runtime.isEmpty()) { + return null; + } + final OperatingSystem os = getOs(runtime); + return os == OperatingSystem.DOCKER ? getRuntimeConfigForDocker(runtime) : getRuntimeConfigForWebContainer(runtime, os); } - // todo: replace WebAppConfiguration with WebAppConfig - public WebAppConfiguration getWebAppConfiguration() { - WebAppConfiguration.WebAppConfigurationBuilder builder = WebAppConfiguration.builder(); - final Runtime runtime = getRuntime(); - final OperatingSystem os = Optional.ofNullable(runtime).map(Runtime::getOperatingSystem).orElse(null); - if (os == null) { - Log.debug("No runtime related config is specified. It will cause error if creating a new web app."); - } else { - switch (os) { - case WINDOWS: - case LINUX: - builder = builder.javaVersion(Objects.toString(runtime.getJavaVersion())).webContainer(Objects.toString(runtime.getWebContainer())); - break; - case DOCKER: - final MavenRuntimeConfig runtimeConfig = mojo.getRuntime(); - builder = builder.image(runtimeConfig.getImage()).serverId(runtimeConfig.getServerId()).registryUrl(runtimeConfig.getRegistryUrl()); - break; - default: - Log.debug("Invalid operating system from the configuration."); - } - } - return builder.appName(getAppName()) - .resourceGroup(getResourceGroup()) - .region(getRegion()) - .pricingTier(getPricingTier().getSize()) - .servicePlanName(mojo.getAppServicePlanName()) - .servicePlanResourceGroup(mojo.getAppServicePlanResourceGroup()) - .deploymentSlotSetting(mojo.getDeploymentSlotSetting()) - .os(os) - .mavenSettings(mojo.getSettings()) - .resources(Optional.ofNullable(mojo.getDeployment()).map(Deployment::getResources).orElse(null)) - .stagingDirectoryPath(mojo.getDeploymentStagingDirectoryPath()) - .buildDirectoryAbsolutePath(mojo.getBuildDirectoryAbsolutePath()) - .project(mojo.getProject()) - .session(mojo.getSession()) - .filtering(mojo.getMavenResourcesFiltering()) - .schemaVersion("v2") - .build(); + private RuntimeConfig getRuntimeConfigForWebContainer(final MavenRuntimeConfig runtime, final OperatingSystem os) { + final JavaVersion javaVersion = StringUtils.isEmpty(runtime.getJavaVersion()) ? null : + parseExpandableParameter(JavaVersion::fromString, runtime.getJavaVersion(), EXPANDABLE_JAVA_VERSION_WARNING); + final WebContainer webContainer = StringUtils.isEmpty(runtime.getWebContainer()) ? null : + parseExpandableParameter(WebContainer::fromString, runtime.getWebContainer(), EXPANDABLE_WEB_CONTAINER_WARNING); + return new RuntimeConfig().os(os).javaVersion(javaVersion).webContainer(webContainer); + } + + private RuntimeConfig getRuntimeConfigForDocker(final MavenRuntimeConfig runtime) throws AzureExecutionException { + final MavenDockerCredentialProvider credentialProvider = getDockerCredential(runtime.getServerId()); + return new RuntimeConfig().image(runtime.getImage()) + .registryUrl(runtime.getRegistryUrl()) + .username(credentialProvider.getUsername()) + .password(credentialProvider.getPassword()); } protected MavenDockerCredentialProvider getDockerCredential(String serverId) { @@ -253,12 +286,10 @@ private static List convertOneDeployResourceToArtifacts(Resource } if (artifacts.isEmpty()) { - Log.warn(String.format("Cannot find any files defined by resource(%s)", - StringUtils.firstNonBlank(resource.toString()))); + Log.warn(String.format("Cannot find any files defined by resource(%s)", StringUtils.firstNonBlank(resource.toString()))); } if (type.ignorePath() && StringUtils.isNotBlank(resource.getTargetPath())) { - throw new AzureToolkitRuntimeException(String.format("'' is not allowed for deployable type('%s').", - type)); + throw new AzureToolkitRuntimeException(String.format("'' is not allowed for deployable type('%s').", type)); } if (StringUtils.isNotBlank(type.getFileExt())) { final String expectFileExtension = type.getFileExt(); @@ -307,5 +338,4 @@ private static String normalizePath(String path) { } return StringUtils.removeEnd(path.replaceAll("([\\\\/])+", Matcher.quoteReplacement("/")), "/"); } - } From 926131719c26aa123b9caeb5e0905cc5e9584c66 Mon Sep 17 00:00:00 2001 From: Hanxiao Liu Date: Wed, 15 Sep 2021 16:12:08 +0800 Subject: [PATCH 060/126] Remove outdated classes --- .../azure/maven/webapp/WebAppConfig.java | 35 ------ .../azure/maven/webapp/utils/DeployUtils.java | 114 ------------------ 2 files changed, 149 deletions(-) delete mode 100644 azure-webapp-maven-plugin/src/main/java/com/microsoft/azure/maven/webapp/WebAppConfig.java delete mode 100644 azure-webapp-maven-plugin/src/main/java/com/microsoft/azure/maven/webapp/utils/DeployUtils.java diff --git a/azure-webapp-maven-plugin/src/main/java/com/microsoft/azure/maven/webapp/WebAppConfig.java b/azure-webapp-maven-plugin/src/main/java/com/microsoft/azure/maven/webapp/WebAppConfig.java deleted file mode 100644 index e2a2ca6a41..0000000000 --- a/azure-webapp-maven-plugin/src/main/java/com/microsoft/azure/maven/webapp/WebAppConfig.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - */ -package com.microsoft.azure.maven.webapp; - -import com.microsoft.azure.toolkit.lib.appservice.model.WebAppArtifact; -import com.microsoft.azure.toolkit.lib.appservice.model.DockerConfiguration; -import com.microsoft.azure.toolkit.lib.appservice.model.PricingTier; -import com.microsoft.azure.toolkit.lib.appservice.model.Runtime; -import com.microsoft.azure.toolkit.lib.common.model.Region; -import lombok.Getter; -import lombok.experimental.SuperBuilder; - -import java.util.List; -import java.util.Map; - -@Getter -@SuperBuilder(toBuilder = true) -public class WebAppConfig { - private String subscriptionId; - private String resourceGroup; - private String appName; - private String servicePlanName; - private String servicePlanResourceGroup; - private Region region; - private PricingTier pricingTier; - private Runtime runtime; - private DockerConfiguration dockerConfiguration; - private String deploymentSlotName; - private String deploymentSlotConfigurationSource; - private Map appSettings; - // resources - private List webAppArtifacts; -} diff --git a/azure-webapp-maven-plugin/src/main/java/com/microsoft/azure/maven/webapp/utils/DeployUtils.java b/azure-webapp-maven-plugin/src/main/java/com/microsoft/azure/maven/webapp/utils/DeployUtils.java deleted file mode 100644 index 99eb90f6a1..0000000000 --- a/azure-webapp-maven-plugin/src/main/java/com/microsoft/azure/maven/webapp/utils/DeployUtils.java +++ /dev/null @@ -1,114 +0,0 @@ -/* - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - */ - -package com.microsoft.azure.maven.webapp.utils; - -import com.microsoft.azure.toolkit.lib.common.exception.AzureExecutionException; -import com.microsoft.azure.toolkit.lib.common.logging.Log; -import com.microsoft.azure.maven.model.DeploymentResource; -import com.microsoft.azure.toolkit.lib.appservice.model.WebAppArtifact; -import com.microsoft.azure.toolkit.lib.appservice.model.DeployType; -import com.microsoft.azure.toolkit.lib.appservice.model.PublishingProfile; -import com.microsoft.azure.toolkit.lib.appservice.service.IAppService; -import org.apache.commons.io.FilenameUtils; -import org.apache.commons.lang3.StringUtils; -import org.apache.commons.net.ftp.FTPClient; - -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.util.List; -import java.util.Set; -import java.util.jar.JarInputStream; -import java.util.jar.Manifest; -import java.util.stream.Collectors; - -public class DeployUtils { - private static final String DEFAULT_APP_SERVICE_JAR_NAME = "app.jar"; - private static final String WEB_CONFIG = "web.config"; - private static final String RENAMING_MESSAGE = "Renaming %s to %s"; - private static final String RENAMING_FAILED_MESSAGE = "Failed to rename artifact to %s, which is required in Java SE environment, " + - "refer to https://docs.microsoft.com/en-us/azure/app-service/containers/configure-language-java#set-java-runtime-options for details."; - private static final String NO_EXECUTABLE_JAR = "No executable jar found in target folder according to resource filter in , " + - "please make sure the resource filter is correct and you have built the jar."; - private static final String MULTI_EXECUTABLE_JARS = "Multi executable jars found in , please check the configuration"; - - public static void deployResourcesWithFtp(IAppService appService, List externalResources) throws AzureExecutionException { - if (externalResources.isEmpty()) { - return; - } - final PublishingProfile publishingProfile = appService.getPublishingProfile(); - final String serverUrl = publishingProfile.getFtpUrl().split("/", 2)[0]; - try { - - final FTPClient ftpClient = FTPUtils.getFTPClient(serverUrl, publishingProfile.getFtpUsername(), publishingProfile.getFtpPassword()); - for (final DeploymentResource externalResource : externalResources) { - uploadResource(externalResource, ftpClient); - } - } catch (IOException e) { - throw new AzureExecutionException(e.getMessage(), e); - } - } - - public static boolean isAllWarArtifacts(List webAppArtifacts) { - final Set deployTypes = webAppArtifacts.stream().map(WebAppArtifact::getDeployType).collect(Collectors.toSet()); - return deployTypes.size() == 1 && deployTypes.iterator().next() == DeployType.WAR; - } - - private static void uploadResource(DeploymentResource resource, FTPClient ftpClient) throws IOException { - final List files = Utils.getArtifacts(resource); - final String target = resource.getAbsoluteTargetPath(); - for (final File file : files) { - FTPUtils.uploadFile(ftpClient, file.getPath(), target); - } - } - - /** - * Rename project jar to app.jar for java se app service - */ - public static void prepareJavaSERuntimeJarArtifact(final List artifacts, final String finalName) throws AzureExecutionException { - if (existsWebConfig(artifacts)) { - return; - } - final File artifact = getProjectJarArtifact(artifacts, finalName); - final File renamedArtifact = new File(artifact.getParent(), DEFAULT_APP_SERVICE_JAR_NAME); - if (!StringUtils.equals(artifact.getName(), DEFAULT_APP_SERVICE_JAR_NAME)) { - Log.info(String.format(RENAMING_MESSAGE, artifact.getAbsolutePath(), DEFAULT_APP_SERVICE_JAR_NAME)); - if (!artifact.renameTo(renamedArtifact)) { - throw new AzureExecutionException(String.format(RENAMING_FAILED_MESSAGE, DEFAULT_APP_SERVICE_JAR_NAME)); - } - } - } - - private static File getProjectJarArtifact(final List artifacts, final String finalName) throws AzureExecutionException { - final List executableArtifacts = artifacts.stream() - .filter(DeployUtils::isExecutableJar).collect(Collectors.toList()); - final File finalArtifact = executableArtifacts.stream() - .filter(file -> StringUtils.equals(finalName, file.getName())).findFirst().orElse(null); - if (executableArtifacts.size() == 0) { - throw new AzureExecutionException(NO_EXECUTABLE_JAR); - } else if (finalArtifact == null && executableArtifacts.size() > 1) { - throw new AzureExecutionException(MULTI_EXECUTABLE_JARS); - } - return finalArtifact == null ? executableArtifacts.get(0) : finalArtifact; - } - - private static boolean existsWebConfig(final List artifacts) { - return artifacts.stream().anyMatch(file -> StringUtils.equals(file.getName(), WEB_CONFIG)); - } - - private static boolean isExecutableJar(File file) { - if (!StringUtils.equalsIgnoreCase(FilenameUtils.getExtension(file.getName()), "jar")) { - return false; - } - try (final FileInputStream fileInputStream = new FileInputStream(file); - final JarInputStream jarInputStream = new JarInputStream(fileInputStream)) { - final Manifest manifest = jarInputStream.getManifest(); - return manifest != null && manifest.getMainAttributes().getValue("Main-Class") != null; - } catch (IOException e) { - return false; - } - } -} From b04ba564b5121c0bdfff682168c1d02405a0aa21 Mon Sep 17 00:00:00 2001 From: Hanxiao Liu Date: Thu, 16 Sep 2021 17:29:17 +0800 Subject: [PATCH 061/126] Create config parser inline --- .../azure/maven/webapp/AbstractWebAppMojo.java | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/azure-webapp-maven-plugin/src/main/java/com/microsoft/azure/maven/webapp/AbstractWebAppMojo.java b/azure-webapp-maven-plugin/src/main/java/com/microsoft/azure/maven/webapp/AbstractWebAppMojo.java index 539ddd161c..0e994c5878 100644 --- a/azure-webapp-maven-plugin/src/main/java/com/microsoft/azure/maven/webapp/AbstractWebAppMojo.java +++ b/azure-webapp-maven-plugin/src/main/java/com/microsoft/azure/maven/webapp/AbstractWebAppMojo.java @@ -136,7 +136,8 @@ public abstract class AbstractWebAppMojo extends AbstractAppServiceMojo { private boolean isRuntimeInjected = false; @JsonIgnore - protected ConfigParser configParser; + @Getter + protected ConfigParser configParser = new ConfigParser(this); //endregion @@ -238,13 +239,6 @@ protected void validateConfiguration(Consumer validationMessa } } - public ConfigParser getConfigParser() { - if (configParser == null) { - configParser = new ConfigParser(this); - } - return configParser; - } - @Override public String getSubscriptionId() { return appServiceClient == null ? this.subscriptionId : appServiceClient.getDefaultSubscription().getId(); From c2897dc734c55dfd6739c0daa6c3e7881a920071 Mon Sep 17 00:00:00 2001 From: Hanxiao Liu Date: Thu, 16 Sep 2021 17:29:53 +0800 Subject: [PATCH 062/126] Handle no os cases when parse runtime config --- .../maven/webapp/parser/ConfigParser.java | 20 +++++++------------ 1 file changed, 7 insertions(+), 13 deletions(-) diff --git a/azure-webapp-maven-plugin/src/main/java/com/microsoft/azure/maven/webapp/parser/ConfigParser.java b/azure-webapp-maven-plugin/src/main/java/com/microsoft/azure/maven/webapp/parser/ConfigParser.java index d2d385bd0a..2941818614 100644 --- a/azure-webapp-maven-plugin/src/main/java/com/microsoft/azure/maven/webapp/parser/ConfigParser.java +++ b/azure-webapp-maven-plugin/src/main/java/com/microsoft/azure/maven/webapp/parser/ConfigParser.java @@ -216,23 +216,17 @@ private RuntimeConfig getRuntimeConfig() throws AzureExecutionException { return null; } final OperatingSystem os = getOs(runtime); - return os == OperatingSystem.DOCKER ? getRuntimeConfigForDocker(runtime) : getRuntimeConfigForWebContainer(runtime, os); - } - - private RuntimeConfig getRuntimeConfigForWebContainer(final MavenRuntimeConfig runtime, final OperatingSystem os) { final JavaVersion javaVersion = StringUtils.isEmpty(runtime.getJavaVersion()) ? null : parseExpandableParameter(JavaVersion::fromString, runtime.getJavaVersion(), EXPANDABLE_JAVA_VERSION_WARNING); final WebContainer webContainer = StringUtils.isEmpty(runtime.getWebContainer()) ? null : parseExpandableParameter(WebContainer::fromString, runtime.getWebContainer(), EXPANDABLE_WEB_CONTAINER_WARNING); - return new RuntimeConfig().os(os).javaVersion(javaVersion).webContainer(webContainer); - } - - private RuntimeConfig getRuntimeConfigForDocker(final MavenRuntimeConfig runtime) throws AzureExecutionException { - final MavenDockerCredentialProvider credentialProvider = getDockerCredential(runtime.getServerId()); - return new RuntimeConfig().image(runtime.getImage()) - .registryUrl(runtime.getRegistryUrl()) - .username(credentialProvider.getUsername()) - .password(credentialProvider.getPassword()); + final RuntimeConfig result = new RuntimeConfig().os(os).javaVersion(javaVersion).webContainer(webContainer) + .image(runtime.getImage()).registryUrl(runtime.getRegistryUrl()); + if (StringUtils.isNotEmpty(runtime.getServerId())) { + final MavenDockerCredentialProvider credentialProvider = getDockerCredential(runtime.getServerId()); + result.username(credentialProvider.getUsername()).password(credentialProvider.getPassword()); + } + return result; } protected MavenDockerCredentialProvider getDockerCredential(String serverId) { From fac0c74b7b8182273cc1ed447dc169fc31d8ac69 Mon Sep 17 00:00:00 2001 From: Hanxiao Liu Date: Thu, 16 Sep 2021 17:30:22 +0800 Subject: [PATCH 063/126] Create seperate task to deploy external resources --- .../azure/maven/webapp/DeployMojo.java | 33 +-------- .../task/DeployExternalResourcesTask.java | 69 +++++++++++++++++++ 2 files changed, 72 insertions(+), 30 deletions(-) create mode 100644 azure-webapp-maven-plugin/src/main/java/com/microsoft/azure/maven/webapp/task/DeployExternalResourcesTask.java diff --git a/azure-webapp-maven-plugin/src/main/java/com/microsoft/azure/maven/webapp/DeployMojo.java b/azure-webapp-maven-plugin/src/main/java/com/microsoft/azure/maven/webapp/DeployMojo.java index ac66934b5e..b93874bd87 100644 --- a/azure-webapp-maven-plugin/src/main/java/com/microsoft/azure/maven/webapp/DeployMojo.java +++ b/azure-webapp-maven-plugin/src/main/java/com/microsoft/azure/maven/webapp/DeployMojo.java @@ -7,11 +7,8 @@ import com.microsoft.azure.maven.model.DeploymentResource; import com.microsoft.azure.maven.webapp.configuration.DeploymentSlotConfig; -import com.microsoft.azure.maven.webapp.utils.FTPUtils; -import com.microsoft.azure.maven.webapp.utils.Utils; -import com.microsoft.azure.toolkit.lib.appservice.model.PublishingProfile; +import com.microsoft.azure.maven.webapp.task.DeployExternalResourcesTask; import com.microsoft.azure.toolkit.lib.appservice.model.WebAppArtifact; -import com.microsoft.azure.toolkit.lib.appservice.service.IAppService; import com.microsoft.azure.toolkit.lib.appservice.service.IWebApp; import com.microsoft.azure.toolkit.lib.appservice.service.IWebAppBase; import com.microsoft.azure.toolkit.lib.appservice.service.IWebAppDeploymentSlot; @@ -20,12 +17,9 @@ import com.microsoft.azure.toolkit.lib.common.bundle.AzureString; import com.microsoft.azure.toolkit.lib.common.exception.AzureExecutionException; import com.microsoft.azure.toolkit.lib.common.messager.AzureMessager; -import org.apache.commons.net.ftp.FTPClient; import org.apache.maven.plugins.annotations.LifecyclePhase; import org.apache.maven.plugins.annotations.Mojo; -import java.io.File; -import java.io.IOException; import java.util.List; /** @@ -88,28 +82,7 @@ private void deploy(IWebAppBase target, List artifacts) { new DeployWebAppTask(target, artifacts, isStopAppDuringDeployment()).execute(); } - private void deployExternalResources(final IAppService target, final List resources) throws AzureExecutionException { - if (resources.isEmpty()) { - return; - } - AzureMessager.getMessager().info(AzureString.format("Uploading resources to %s", target.name())); - final PublishingProfile publishingProfile = target.getPublishingProfile(); - final String serverUrl = publishingProfile.getFtpUrl().split("/", 2)[0]; - try { - final FTPClient ftpClient = FTPUtils.getFTPClient(serverUrl, publishingProfile.getFtpUsername(), publishingProfile.getFtpPassword()); - for (final DeploymentResource externalResource : resources) { - uploadResource(externalResource, ftpClient); - } - } catch (IOException e) { - throw new AzureExecutionException(e.getMessage(), e); - } - } - - private static void uploadResource(DeploymentResource resource, FTPClient ftpClient) throws IOException { - final List files = Utils.getArtifacts(resource); - final String target = resource.getAbsoluteTargetPath(); - for (final File file : files) { - FTPUtils.uploadFile(ftpClient, file.getPath(), target); - } + private void deployExternalResources(final IWebAppBase target, final List resources) { + new DeployExternalResourcesTask(target, resources).execute(); } } diff --git a/azure-webapp-maven-plugin/src/main/java/com/microsoft/azure/maven/webapp/task/DeployExternalResourcesTask.java b/azure-webapp-maven-plugin/src/main/java/com/microsoft/azure/maven/webapp/task/DeployExternalResourcesTask.java new file mode 100644 index 0000000000..60efb20bc4 --- /dev/null +++ b/azure-webapp-maven-plugin/src/main/java/com/microsoft/azure/maven/webapp/task/DeployExternalResourcesTask.java @@ -0,0 +1,69 @@ +/* + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + */ + +package com.microsoft.azure.maven.webapp.task; + +import com.microsoft.azure.maven.model.DeploymentResource; +import com.microsoft.azure.maven.webapp.utils.FTPUtils; +import com.microsoft.azure.maven.webapp.utils.Utils; +import com.microsoft.azure.toolkit.lib.appservice.model.PublishingProfile; +import com.microsoft.azure.toolkit.lib.appservice.service.IAppService; +import com.microsoft.azure.toolkit.lib.appservice.service.IWebAppBase; +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.task.AzureTask; +import org.apache.commons.net.ftp.FTPClient; + +import java.io.File; +import java.io.IOException; +import java.util.List; + +@Deprecated +public class DeployExternalResourcesTask extends AzureTask> { + private static final String DEPLOY_START = "Trying to deploy external resources to %s..."; + private static final String DEPLOY_FINISH = "Successfully deployed the resources to %s"; + + final IWebAppBase target; + final List resources; + + public DeployExternalResourcesTask(final IWebAppBase target, final List resources) { + this.target = target; + this.resources = resources; + } + + @Override + public IWebAppBase execute() { + AzureMessager.getMessager().info(AzureString.format(DEPLOY_START, target.name())); + deployExternalResources(target, resources); + AzureMessager.getMessager().info(AzureString.format(DEPLOY_FINISH, target.name())); + return target; + } + + private void deployExternalResources(final IAppService target, final List resources) { + if (resources.isEmpty()) { + return; + } + AzureMessager.getMessager().info(AzureString.format("Uploading resources to %s", target.name())); + final PublishingProfile publishingProfile = target.getPublishingProfile(); + final String serverUrl = publishingProfile.getFtpUrl().split("/", 2)[0]; + try { + final FTPClient ftpClient = FTPUtils.getFTPClient(serverUrl, publishingProfile.getFtpUsername(), publishingProfile.getFtpPassword()); + for (final DeploymentResource externalResource : resources) { + uploadResource(externalResource, ftpClient); + } + } catch (IOException e) { + throw new AzureToolkitRuntimeException(e.getMessage(), e); + } + } + + private static void uploadResource(DeploymentResource resource, FTPClient ftpClient) throws IOException { + final List files = Utils.getArtifacts(resource); + final String target = resource.getAbsoluteTargetPath(); + for (final File file : files) { + FTPUtils.uploadFile(ftpClient, file.getPath(), target); + } + } +} From 8a548c54543712c5d22505f9c0db471659967260 Mon Sep 17 00:00:00 2001 From: Hanxiao Liu Date: Fri, 17 Sep 2021 14:25:35 +0800 Subject: [PATCH 064/126] Add resource creation task for function app and application insights --- .../azure-toolkit-appservice-lib/pom.xml | 4 + .../appservice/config/FunctionAppConfig.java | 18 ++ .../task/CreateOrUpdateFunctionAppTask.java | 221 ++++++++++++++++++ .../GetOrCreateApplicationInsightsTask.java | 51 ++++ 4 files changed, 294 insertions(+) create mode 100644 azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/config/FunctionAppConfig.java create mode 100644 azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/task/CreateOrUpdateFunctionAppTask.java create mode 100644 azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/task/GetOrCreateApplicationInsightsTask.java diff --git a/azure-toolkit-libs/azure-toolkit-appservice-lib/pom.xml b/azure-toolkit-libs/azure-toolkit-appservice-lib/pom.xml index c7f31b0038..37d4670eb6 100644 --- a/azure-toolkit-libs/azure-toolkit-appservice-lib/pom.xml +++ b/azure-toolkit-libs/azure-toolkit-appservice-lib/pom.xml @@ -150,6 +150,10 @@ com.microsoft.azure azure-toolkit-common-lib + + com.microsoft.azure + azure-toolkit-applicationinsights-lib + diff --git a/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/config/FunctionAppConfig.java b/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/config/FunctionAppConfig.java new file mode 100644 index 0000000000..7490414180 --- /dev/null +++ b/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/config/FunctionAppConfig.java @@ -0,0 +1,18 @@ +/* + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + */ +package com.microsoft.azure.toolkit.lib.appservice.config; + +import lombok.Getter; +import lombok.Setter; +import lombok.experimental.Accessors; + +@Getter +@Setter +@Accessors(fluent = true) +public class FunctionAppConfig extends AppServiceConfig { + private String appInsightsInstance; + private String appInsightsKey; + private boolean disableAppInsights; +} diff --git a/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/task/CreateOrUpdateFunctionAppTask.java b/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/task/CreateOrUpdateFunctionAppTask.java new file mode 100644 index 0000000000..a75d7bf9e2 --- /dev/null +++ b/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/task/CreateOrUpdateFunctionAppTask.java @@ -0,0 +1,221 @@ +/* + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + */ + +package com.microsoft.azure.toolkit.lib.appservice.task; + +import com.microsoft.azure.toolkit.lib.Azure; +import com.microsoft.azure.toolkit.lib.applicationinsights.ApplicationInsightsEntity; +import com.microsoft.azure.toolkit.lib.appservice.AzureAppService; +import com.microsoft.azure.toolkit.lib.appservice.config.AppServicePlanConfig; +import com.microsoft.azure.toolkit.lib.appservice.config.FunctionAppConfig; +import com.microsoft.azure.toolkit.lib.appservice.config.RuntimeConfig; +import com.microsoft.azure.toolkit.lib.appservice.model.DockerConfiguration; +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; +import com.microsoft.azure.toolkit.lib.appservice.model.WebContainer; +import com.microsoft.azure.toolkit.lib.appservice.service.IAppServicePlan; +import com.microsoft.azure.toolkit.lib.appservice.service.IAppServiceUpdater; +import com.microsoft.azure.toolkit.lib.appservice.service.IFunctionApp; +import com.microsoft.azure.toolkit.lib.appservice.service.IFunctionAppBase; +import com.microsoft.azure.toolkit.lib.common.bundle.AzureString; +import com.microsoft.azure.toolkit.lib.common.messager.AzureMessager; +import com.microsoft.azure.toolkit.lib.common.model.ResourceGroup; +import com.microsoft.azure.toolkit.lib.common.task.AzureTask; +import com.microsoft.azure.toolkit.lib.common.telemetry.AzureTelemetry; +import com.microsoft.azure.toolkit.lib.resource.task.CreateResourceGroupTask; +import org.apache.commons.lang3.StringUtils; + +import javax.annotation.Nonnull; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.function.Consumer; + +public class CreateOrUpdateFunctionAppTask extends AzureTask> { + private static final String APPINSIGHTS_INSTRUMENTATION_KEY = "APPINSIGHTS_INSTRUMENTATIONKEY"; + private static final String APPLICATION_INSIGHTS_CREATE_FAILED = "Unable to create the Application Insights " + + "for the Function App due to error %s. Please use the Azure Portal to manually create and configure the " + + "Application Insights if needed."; + private static final String CREATE_FUNCTION_APP = "Creating function app %s..."; + private static final String CREATE_FUNCTION_APP_DONE = "Successfully created function app %s."; + private static final String CREATE_NEW_FUNCTION_APP = "isCreateNewFunctionApp"; + private static final String UPDATE_FUNCTION_APP = "Updating target Function App %s..."; + private static final String UPDATE_FUNCTION_DONE = "Successfully updated Function App %s."; + private static final String FUNCTIONS_WORKER_RUNTIME_NAME = "FUNCTIONS_WORKER_RUNTIME"; + private static final String FUNCTIONS_WORKER_RUNTIME_VALUE = "java"; + private static final String SET_FUNCTIONS_WORKER_RUNTIME = "Set function worker runtime to java."; + private static final String CUSTOMIZED_FUNCTIONS_WORKER_RUNTIME_WARNING = "App setting `FUNCTIONS_WORKER_RUNTIME` doesn't " + + "meet the requirement of Azure Java Functions, the value should be `java`."; + private static final String FUNCTIONS_EXTENSION_VERSION_NAME = "FUNCTIONS_EXTENSION_VERSION"; + private static final String FUNCTIONS_EXTENSION_VERSION_VALUE = "~3"; + private static final String SET_FUNCTIONS_EXTENSION_VERSION = "Functions extension version " + + "isn't configured, setting up the default value."; + + private final FunctionAppConfig functionAppConfig; + private final List> tasks = new ArrayList<>(); + + private ResourceGroup resourceGroup; + private IAppServicePlan appServicePlan; + private ApplicationInsightsEntity applicationInsights; + private IFunctionAppBase functionApp; + + public CreateOrUpdateFunctionAppTask(@Nonnull final FunctionAppConfig config) { + this.functionAppConfig = config; + initTasks(); + } + + private void initTasks() { + final IFunctionApp functionApp = Azure.az(AzureAppService.class).functionApp(functionAppConfig.resourceGroup(), functionAppConfig.appName()); + registerSubTask(getResourceGroupTask(), result -> this.resourceGroup = result); + registerSubTask(getServicePlanTask(functionApp), result -> this.appServicePlan = result); + if (!functionAppConfig.disableAppInsights() && !functionAppConfig.appSettings().containsKey(APPINSIGHTS_INSTRUMENTATION_KEY)) { + // get/create ai instances only if user didn't specify ai connection string in app settings + registerSubTask(getApplicationInsightsTask(), result -> this.applicationInsights = result); + } + final AzureTask> functionTask = functionApp.exists() ? + getCreateFunctionAppTask(functionApp) : getUpdateFunctionAppTask(functionApp); + registerSubTask(functionTask, result -> this.functionApp = result); + } + + private void registerSubTask(AzureTask task, Consumer consumer) { + tasks.add(new AzureTask<>(() -> { + T result = task.execute(); + consumer.accept(result); + return result; + })); + } + + private AzureTask> getCreateFunctionAppTask(final IFunctionApp functionApp) { + final AzureString title = AzureString.format("Create new app({0}) on subscription({1})", + functionAppConfig.appName(), functionAppConfig.subscriptionId()); + return new AzureTask<>(title, () -> { + AzureTelemetry.getActionContext().setProperty(CREATE_NEW_FUNCTION_APP, String.valueOf(true)); + AzureMessager.getMessager().info(String.format(CREATE_FUNCTION_APP, functionAppConfig.appName())); + final Map appSettings = processAppSettingsWithDefaultValue(); + Optional.ofNullable(applicationInsights).ifPresent(insights -> + appSettings.put(APPINSIGHTS_INSTRUMENTATION_KEY, applicationInsights.getInstrumentationKey())); + final IFunctionApp result = functionApp.create().withName(functionAppConfig.appName()) + .withResourceGroup(resourceGroup.getName()) + .withPlan(appServicePlan.id()) + .withRuntime(getRuntime(functionAppConfig.runtime())) + .withDockerConfiguration(getDockerConfiguration(functionAppConfig.runtime())) + .withAppSettings(appSettings) + .commit(); + AzureMessager.getMessager().info(String.format(CREATE_FUNCTION_APP_DONE, result.name())); + return result; + }); + } + + private Map processAppSettingsWithDefaultValue() { + final Map appSettings = functionAppConfig.appSettings(); + setDefaultAppSetting(appSettings, FUNCTIONS_WORKER_RUNTIME_NAME, SET_FUNCTIONS_WORKER_RUNTIME, + FUNCTIONS_WORKER_RUNTIME_VALUE, CUSTOMIZED_FUNCTIONS_WORKER_RUNTIME_WARNING); + setDefaultAppSetting(appSettings, FUNCTIONS_EXTENSION_VERSION_NAME, SET_FUNCTIONS_EXTENSION_VERSION, + FUNCTIONS_EXTENSION_VERSION_VALUE, null); + return appSettings; + } + + private void setDefaultAppSetting(Map result, String settingName, String settingIsEmptyMessage, + String defaultValue, String warningMessage) { + final String setting = result.get(settingName); + if (StringUtils.isEmpty(setting)) { + AzureMessager.getMessager().info(settingIsEmptyMessage); + result.put(settingName, defaultValue); + return; + } + // Show warning message when user set a different value + if (!StringUtils.equalsIgnoreCase(setting, defaultValue) && StringUtils.isNotEmpty(warningMessage)) { + AzureMessager.getMessager().warning(warningMessage); + } + } + + private AzureTask> getUpdateFunctionAppTask(final IFunctionApp functionApp) { + final AzureString title = AzureString.format("Create new app({0}) on subscription({1})", + functionAppConfig.appName(), functionAppConfig.subscriptionId()); + return new AzureTask<>(title, () -> { + AzureMessager.getMessager().info(String.format(UPDATE_FUNCTION_APP, functionApp.name())); + // update app settings + final IAppServiceUpdater update = functionApp.update(); + final Map appSettings = processAppSettingsWithDefaultValue(); + if (functionAppConfig.disableAppInsights()) { + update.withoutAppSettings(APPINSIGHTS_INSTRUMENTATION_KEY); + } else if (applicationInsights != null) { + appSettings.put(APPINSIGHTS_INSTRUMENTATION_KEY, applicationInsights.getInstrumentationKey()); + } + final IFunctionApp result = update.withPlan(appServicePlan.id()) + .withRuntime(getRuntime(functionAppConfig.runtime())) + .withDockerConfiguration(getDockerConfiguration(functionAppConfig.runtime())) + .withAppSettings(appSettings) + .commit(); + AzureMessager.getMessager().info(String.format(UPDATE_FUNCTION_DONE, functionApp.name())); + return result; + }); + } + + private AzureTask getApplicationInsightsTask() { + return new AzureTask<>(() -> { + if (StringUtils.isNotEmpty(functionAppConfig.appInsightsKey())) { + // validate insights key with schema validator + return ApplicationInsightsEntity.builder().instrumentationKey(functionAppConfig.appInsightsKey()).build(); + } else { + try { + return new GetOrCreateApplicationInsightsTask(functionAppConfig.subscriptionId(), functionAppConfig.resourceGroup(), + functionAppConfig.region(), functionAppConfig.appInsightsInstance()).execute(); + } catch (final Exception e) { + AzureMessager.getMessager().warning(String.format(APPLICATION_INSIGHTS_CREATE_FAILED, e.getMessage())); + return null; + } + } + }); + } + + private CreateResourceGroupTask getResourceGroupTask() { + return new CreateResourceGroupTask(functionAppConfig.subscriptionId(), functionAppConfig.resourceGroup(), functionAppConfig.region()); + } + + private CreateOrUpdateAppServicePlanTask getServicePlanTask(final IFunctionApp functionApp) { + final String servicePlanName = functionApp.exists() ? functionApp.plan().name() : + StringUtils.firstNonBlank(functionAppConfig.servicePlanName(), String.format("asp-%s", appServicePlan.name())); + final String servicePlanGroup = functionApp.exists() ? functionApp.plan().resourceGroup() : + StringUtils.firstNonBlank(functionAppConfig.resourceGroup(), functionAppConfig.servicePlanResourceGroup()); + final AppServicePlanConfig servicePlanConfig = functionAppConfig.getServicePlanConfig().servicePlanName(servicePlanName) + .servicePlanResourceGroup(servicePlanGroup); + return new CreateOrUpdateAppServicePlanTask(servicePlanConfig); + } + + // todo: remove duplicated with Create Web App Task + private Runtime getRuntime(RuntimeConfig runtime) { + if (runtime != null && OperatingSystem.DOCKER != runtime.os()) { + return Runtime.getRuntime(runtime.os(), + runtime.webContainer(), + runtime.javaVersion()); + } else if (runtime != null && OperatingSystem.DOCKER == runtime.os()) { + return Runtime.getRuntime(OperatingSystem.DOCKER, WebContainer.JAVA_OFF, JavaVersion.OFF); + } + return null; + } + + // todo: remove duplicated with Create Web App Task + private DockerConfiguration getDockerConfiguration(RuntimeConfig runtime) { + if (runtime != null && OperatingSystem.DOCKER == runtime.os()) { + return DockerConfiguration.builder() + .userName(runtime.username()) + .password(runtime.password()) + .registryUrl(runtime.registryUrl()) + .image(runtime.image()) + .startUpCommand(runtime.startUpCommand()) + .build(); + } + return null; + } + + @Override + public IFunctionAppBase execute() { + this.tasks.forEach(t -> t.getSupplier().get()); + return functionApp; + } +} diff --git a/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/task/GetOrCreateApplicationInsightsTask.java b/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/task/GetOrCreateApplicationInsightsTask.java new file mode 100644 index 0000000000..fc16441657 --- /dev/null +++ b/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/task/GetOrCreateApplicationInsightsTask.java @@ -0,0 +1,51 @@ +package com.microsoft.azure.toolkit.lib.appservice.task; + +import com.azure.core.management.AzureEnvironment; +import com.azure.core.management.exception.ManagementException; +import com.microsoft.azure.toolkit.lib.Azure; +import com.microsoft.azure.toolkit.lib.applicationinsights.ApplicationInsights; +import com.microsoft.azure.toolkit.lib.applicationinsights.ApplicationInsightsEntity; +import com.microsoft.azure.toolkit.lib.auth.AzureAccount; +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 javax.annotation.Nonnull; + +import static com.microsoft.azure.toolkit.lib.auth.util.AzureEnvironmentUtils.getPortalUrl; + +public class GetOrCreateApplicationInsightsTask extends AzureTask { + private static final String APPLICATION_INSIGHTS_CREATE_START = "Creating application insights..."; + private static final String APPLICATION_INSIGHTS_CREATED = "Successfully created the application insights %s " + + "for this Function App. You can visit %s/#@/resource%s/overview to view your " + + "Application Insights component."; + + private final String subscriptionId; + private final String resourceGroup; + private final String name; + private final Region region; + + public GetOrCreateApplicationInsightsTask(@Nonnull String subscriptionId, @Nonnull String resourceGroup, @Nonnull Region region, @Nonnull String name) { + this.subscriptionId = subscriptionId; + this.resourceGroup = resourceGroup; + this.name = name; + this.region = region; + } + + @Override + public ApplicationInsightsEntity execute() { + final ApplicationInsights az = Azure.az(ApplicationInsights.class).subscription(subscriptionId); + try { + return az.get(resourceGroup, name); + } catch (ManagementException e) { + if (e.getResponse().getStatusCode() != 404) { + throw e; + } + } + AzureMessager.getMessager().info(APPLICATION_INSIGHTS_CREATE_START); + final AzureEnvironment environment = Azure.az(AzureAccount.class).account().getEnvironment(); + final ApplicationInsightsEntity resource = Azure.az(ApplicationInsights.class).create(resourceGroup, region, name); + AzureMessager.getMessager().info(String.format(APPLICATION_INSIGHTS_CREATED, resource.getName(), getPortalUrl(environment), resource.getId())); + return resource; + } +} From 6f038138f6c920d8a69de490bbd22dc3281b0624 Mon Sep 17 00:00:00 2001 From: Hanxiao Liu Date: Fri, 17 Sep 2021 15:29:00 +0800 Subject: [PATCH 065/126] Support deployment slot in function creation task --- .../task/CreateOrUpdateFunctionAppTask.java | 97 +++++++++++++++---- 1 file changed, 77 insertions(+), 20 deletions(-) diff --git a/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/task/CreateOrUpdateFunctionAppTask.java b/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/task/CreateOrUpdateFunctionAppTask.java index a75d7bf9e2..ddb83122b1 100644 --- a/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/task/CreateOrUpdateFunctionAppTask.java +++ b/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/task/CreateOrUpdateFunctionAppTask.java @@ -20,7 +20,9 @@ import com.microsoft.azure.toolkit.lib.appservice.service.IAppServiceUpdater; import com.microsoft.azure.toolkit.lib.appservice.service.IFunctionApp; import com.microsoft.azure.toolkit.lib.appservice.service.IFunctionAppBase; +import com.microsoft.azure.toolkit.lib.appservice.service.IFunctionAppDeploymentSlot; 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.ResourceGroup; import com.microsoft.azure.toolkit.lib.common.task.AzureTask; @@ -54,6 +56,13 @@ public class CreateOrUpdateFunctionAppTask extends AzureTask private static final String FUNCTIONS_EXTENSION_VERSION_VALUE = "~3"; private static final String SET_FUNCTIONS_EXTENSION_VERSION = "Functions extension version " + "isn't configured, setting up the default value."; + private static final String FUNCTION_APP_NOT_EXIST_FOR_SLOT = "The Function App specified in pom.xml does not exist. " + + "Please make sure the Web App name is correct."; + private static final String FUNCTION_SLOT_CREATE_START = "The specified function slot does not exist. " + + "Creating a new slot..."; + private static final String FUNCTION_SLOT_CREATED = "Successfully created the function slot: %s."; + private static final String FUNCTION_SLOT_UPDATE = "Updating the specified function slot..."; + private static final String FUNCTION_SLOT_UPDATE_DONE = "Successfully updated the function slot: %s."; private final FunctionAppConfig functionAppConfig; private final List> tasks = new ArrayList<>(); @@ -63,6 +72,7 @@ public class CreateOrUpdateFunctionAppTask extends AzureTask private ApplicationInsightsEntity applicationInsights; private IFunctionAppBase functionApp; + public CreateOrUpdateFunctionAppTask(@Nonnull final FunctionAppConfig config) { this.functionAppConfig = config; initTasks(); @@ -72,13 +82,25 @@ private void initTasks() { final IFunctionApp functionApp = Azure.az(AzureAppService.class).functionApp(functionAppConfig.resourceGroup(), functionAppConfig.appName()); registerSubTask(getResourceGroupTask(), result -> this.resourceGroup = result); registerSubTask(getServicePlanTask(functionApp), result -> this.appServicePlan = result); + // get/create ai instances only if user didn't specify ai connection string in app settings if (!functionAppConfig.disableAppInsights() && !functionAppConfig.appSettings().containsKey(APPINSIGHTS_INSTRUMENTATION_KEY)) { - // get/create ai instances only if user didn't specify ai connection string in app settings - registerSubTask(getApplicationInsightsTask(), result -> this.applicationInsights = result); + if (StringUtils.isNotEmpty(functionAppConfig.appInsightsKey())) { + this.applicationInsights = ApplicationInsightsEntity.builder().instrumentationKey(functionAppConfig.appInsightsKey()).build(); + } else if (StringUtils.isNotEmpty(functionAppConfig.appInsightsInstance()) || !functionApp.exists()) { + // create ai instance by default when create new function + registerSubTask(getApplicationInsightsTask(), result -> this.applicationInsights = result); + } + } + if (StringUtils.isEmpty(functionAppConfig.deploymentSlotName())) { + final AzureTask functionTask = functionApp.exists() ? + getCreateFunctionAppTask(functionApp) : getUpdateFunctionAppTask(functionApp); + registerSubTask(functionTask, result -> this.functionApp = result); + } else { + final IFunctionAppDeploymentSlot deploymentSlot = getFunctionDeploymentSlot(functionApp); + final AzureTask slotTask = deploymentSlot.exists() ? + getCreateFunctionSlotTask(deploymentSlot) : getUpdateFunctionSlotTask(deploymentSlot); + registerSubTask(slotTask, result -> this.functionApp = result); } - final AzureTask> functionTask = functionApp.exists() ? - getCreateFunctionAppTask(functionApp) : getUpdateFunctionAppTask(functionApp); - registerSubTask(functionTask, result -> this.functionApp = result); } private void registerSubTask(AzureTask task, Consumer consumer) { @@ -89,7 +111,7 @@ private void registerSubTask(AzureTask task, Consumer consumer) { })); } - private AzureTask> getCreateFunctionAppTask(final IFunctionApp functionApp) { + private AzureTask getCreateFunctionAppTask(final IFunctionApp functionApp) { final AzureString title = AzureString.format("Create new app({0}) on subscription({1})", functionAppConfig.appName(), functionAppConfig.subscriptionId()); return new AzureTask<>(title, () -> { @@ -133,9 +155,8 @@ private void setDefaultAppSetting(Map result, String settingName } } - private AzureTask> getUpdateFunctionAppTask(final IFunctionApp functionApp) { - final AzureString title = AzureString.format("Create new app({0}) on subscription({1})", - functionAppConfig.appName(), functionAppConfig.subscriptionId()); + private AzureTask getUpdateFunctionAppTask(final IFunctionApp functionApp) { + final AzureString title = AzureString.format("Update function app({0})", functionAppConfig.appName()); return new AzureTask<>(title, () -> { AzureMessager.getMessager().info(String.format(UPDATE_FUNCTION_APP, functionApp.name())); // update app settings @@ -156,19 +177,55 @@ private AzureTask> getUpdateFunctionAppTask(final IFunctionA }); } + private AzureTask getCreateFunctionSlotTask(IFunctionAppDeploymentSlot deploymentSlot) { + final AzureString title = AzureString.format("Create new slot({0}) on function app ({1})", + functionAppConfig.deploymentSlotName(), functionAppConfig.appName()); + return new AzureTask<>(title, () -> { + AzureMessager.getMessager().info(FUNCTION_SLOT_CREATE_START); + final Map appSettings = processAppSettingsWithDefaultValue(); + Optional.ofNullable(applicationInsights).ifPresent(insights -> + appSettings.put(APPINSIGHTS_INSTRUMENTATION_KEY, applicationInsights.getInstrumentationKey())); + final IFunctionAppDeploymentSlot result = deploymentSlot.create().withAppSettings(appSettings) + .withConfigurationSource(functionAppConfig.deploymentSlotConfigurationSource()) + .withName(functionAppConfig.deploymentSlotName()).commit(); + AzureMessager.getMessager().info(String.format(FUNCTION_SLOT_CREATED, result.name())); + return result; + }); + } + + private AzureTask getUpdateFunctionSlotTask(IFunctionAppDeploymentSlot deploymentSlot) { + final AzureString title = AzureString.format("Update function deployment slot({0})", functionAppConfig.deploymentSlotName()); + return new AzureTask<>(title, () -> { + AzureMessager.getMessager().info(FUNCTION_SLOT_UPDATE); + final Map appSettings = processAppSettingsWithDefaultValue(); + final IFunctionAppDeploymentSlot.Updater update = deploymentSlot.update(); + if (functionAppConfig.disableAppInsights()) { + update.withoutAppSettings(APPINSIGHTS_INSTRUMENTATION_KEY); + } else if (applicationInsights != null) { + appSettings.put(APPINSIGHTS_INSTRUMENTATION_KEY, applicationInsights.getInstrumentationKey()); + } + final IFunctionAppDeploymentSlot result = update.withAppSettings(appSettings).commit(); + AzureMessager.getMessager().info(String.format(FUNCTION_SLOT_UPDATE_DONE, result.name())); + return deploymentSlot; + }); + } + + private IFunctionAppDeploymentSlot getFunctionDeploymentSlot(final IFunctionApp functionApp) { + if (!functionApp.exists()) { + throw new AzureToolkitRuntimeException(FUNCTION_APP_NOT_EXIST_FOR_SLOT); + } + return functionApp.deploymentSlot(functionAppConfig.appName()); + } + private AzureTask getApplicationInsightsTask() { return new AzureTask<>(() -> { - if (StringUtils.isNotEmpty(functionAppConfig.appInsightsKey())) { - // validate insights key with schema validator - return ApplicationInsightsEntity.builder().instrumentationKey(functionAppConfig.appInsightsKey()).build(); - } else { - try { - return new GetOrCreateApplicationInsightsTask(functionAppConfig.subscriptionId(), functionAppConfig.resourceGroup(), - functionAppConfig.region(), functionAppConfig.appInsightsInstance()).execute(); - } catch (final Exception e) { - AzureMessager.getMessager().warning(String.format(APPLICATION_INSIGHTS_CREATE_FAILED, e.getMessage())); - return null; - } + try { + final String name = StringUtils.firstNonEmpty(functionAppConfig.appInsightsInstance(), functionAppConfig.appName()); + return new GetOrCreateApplicationInsightsTask(functionAppConfig.subscriptionId(), + functionAppConfig.resourceGroup(), functionAppConfig.region(), name).execute(); + } catch (final Exception e) { + AzureMessager.getMessager().warning(String.format(APPLICATION_INSIGHTS_CREATE_FAILED, e.getMessage())); + return null; } }); } From a98fed57822d18c7888b5c50d6b25b86ee99b7d5 Mon Sep 17 00:00:00 2001 From: Hanxiao Liu Date: Sat, 18 Sep 2021 09:31:10 +0800 Subject: [PATCH 066/126] Add default values in function creation task --- .../task/CreateOrUpdateFunctionAppTask.java | 36 +++++++++++++++---- 1 file changed, 30 insertions(+), 6 deletions(-) diff --git a/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/task/CreateOrUpdateFunctionAppTask.java b/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/task/CreateOrUpdateFunctionAppTask.java index ddb83122b1..691ad367fe 100644 --- a/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/task/CreateOrUpdateFunctionAppTask.java +++ b/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/task/CreateOrUpdateFunctionAppTask.java @@ -14,6 +14,7 @@ import com.microsoft.azure.toolkit.lib.appservice.model.DockerConfiguration; 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.PricingTier; import com.microsoft.azure.toolkit.lib.appservice.model.Runtime; import com.microsoft.azure.toolkit.lib.appservice.model.WebContainer; import com.microsoft.azure.toolkit.lib.appservice.service.IAppServicePlan; @@ -24,6 +25,7 @@ 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.Region; import com.microsoft.azure.toolkit.lib.common.model.ResourceGroup; import com.microsoft.azure.toolkit.lib.common.task.AzureTask; import com.microsoft.azure.toolkit.lib.common.telemetry.AzureTelemetry; @@ -64,6 +66,11 @@ public class CreateOrUpdateFunctionAppTask extends AzureTask private static final String FUNCTION_SLOT_UPDATE = "Updating the specified function slot..."; private static final String FUNCTION_SLOT_UPDATE_DONE = "Successfully updated the function slot: %s."; + public static final JavaVersion DEFAULT_FUNCTION_JAVA_VERSION = JavaVersion.JAVA_8; + public static final OperatingSystem DEFAULT_FUNCTION_OS = OperatingSystem.WINDOWS; + public static final PricingTier DEFAULT_FUNCTION_PRICING = PricingTier.CONSUMPTION; + public static final Region DEFAULT_FUNCTION_REGION = Region.US_WEST; + private final FunctionAppConfig functionAppConfig; private final List> tasks = new ArrayList<>(); @@ -75,11 +82,28 @@ public class CreateOrUpdateFunctionAppTask extends AzureTask public CreateOrUpdateFunctionAppTask(@Nonnull final FunctionAppConfig config) { this.functionAppConfig = config; + normalizeConfiguration(config); initTasks(); } + private void normalizeConfiguration(FunctionAppConfig config) { + if (config.region() == null) { + config.region(DEFAULT_FUNCTION_REGION); + } + if (config.pricingTier() == null) { + config.pricingTier(DEFAULT_FUNCTION_PRICING); + } + if (config.runtime() != null && config.runtime().os() == null) { + config.runtime().os(DEFAULT_FUNCTION_OS); + } + if (config.runtime() != null && config.runtime().javaVersion() == null) { + config.runtime().javaVersion(DEFAULT_FUNCTION_JAVA_VERSION); + } + } + private void initTasks() { - final IFunctionApp functionApp = Azure.az(AzureAppService.class).functionApp(functionAppConfig.resourceGroup(), functionAppConfig.appName()); + final IFunctionApp functionApp = Azure.az(AzureAppService.class).subscription(functionAppConfig.subscriptionId()) + .functionApp(functionAppConfig.resourceGroup(), functionAppConfig.appName()); registerSubTask(getResourceGroupTask(), result -> this.resourceGroup = result); registerSubTask(getServicePlanTask(functionApp), result -> this.appServicePlan = result); // get/create ai instances only if user didn't specify ai connection string in app settings @@ -93,19 +117,19 @@ private void initTasks() { } if (StringUtils.isEmpty(functionAppConfig.deploymentSlotName())) { final AzureTask functionTask = functionApp.exists() ? - getCreateFunctionAppTask(functionApp) : getUpdateFunctionAppTask(functionApp); + getUpdateFunctionAppTask(functionApp) : getCreateFunctionAppTask(functionApp); registerSubTask(functionTask, result -> this.functionApp = result); } else { final IFunctionAppDeploymentSlot deploymentSlot = getFunctionDeploymentSlot(functionApp); final AzureTask slotTask = deploymentSlot.exists() ? - getCreateFunctionSlotTask(deploymentSlot) : getUpdateFunctionSlotTask(deploymentSlot); + getUpdateFunctionSlotTask(deploymentSlot) : getCreateFunctionSlotTask(deploymentSlot); registerSubTask(slotTask, result -> this.functionApp = result); } } private void registerSubTask(AzureTask task, Consumer consumer) { tasks.add(new AzureTask<>(() -> { - T result = task.execute(); + T result = task.getSupplier().get(); consumer.accept(result); return result; })); @@ -222,7 +246,7 @@ private AzureTask getApplicationInsightsTask() { try { final String name = StringUtils.firstNonEmpty(functionAppConfig.appInsightsInstance(), functionAppConfig.appName()); return new GetOrCreateApplicationInsightsTask(functionAppConfig.subscriptionId(), - functionAppConfig.resourceGroup(), functionAppConfig.region(), name).execute(); + functionAppConfig.resourceGroup(), functionAppConfig.region(), name).getSupplier().get(); } catch (final Exception e) { AzureMessager.getMessager().warning(String.format(APPLICATION_INSIGHTS_CREATE_FAILED, e.getMessage())); return null; @@ -236,7 +260,7 @@ private CreateResourceGroupTask getResourceGroupTask() { private CreateOrUpdateAppServicePlanTask getServicePlanTask(final IFunctionApp functionApp) { final String servicePlanName = functionApp.exists() ? functionApp.plan().name() : - StringUtils.firstNonBlank(functionAppConfig.servicePlanName(), String.format("asp-%s", appServicePlan.name())); + StringUtils.firstNonBlank(functionAppConfig.servicePlanName(), String.format("asp-%s", functionAppConfig.appName())); final String servicePlanGroup = functionApp.exists() ? functionApp.plan().resourceGroup() : StringUtils.firstNonBlank(functionAppConfig.resourceGroup(), functionAppConfig.servicePlanResourceGroup()); final AppServicePlanConfig servicePlanConfig = functionAppConfig.getServicePlanConfig().servicePlanName(servicePlanName) From 3fc94846e82900da6e090e68212d6b836eb41199 Mon Sep 17 00:00:00 2001 From: Hanxiao Liu Date: Sat, 18 Sep 2021 09:35:33 +0800 Subject: [PATCH 067/126] Move application insights creation task to ai library --- .../task/GetOrCreateApplicationInsightsTask.java | 7 ++++++- .../lib/appservice/task/CreateOrUpdateFunctionAppTask.java | 1 + 2 files changed, 7 insertions(+), 1 deletion(-) rename azure-toolkit-libs/{azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice => azure-toolkit-applicationinsights-lib/src/main/java/com/microsoft/azure/toolkit/lib/applicationinsights}/task/GetOrCreateApplicationInsightsTask.java (91%) diff --git a/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/task/GetOrCreateApplicationInsightsTask.java b/azure-toolkit-libs/azure-toolkit-applicationinsights-lib/src/main/java/com/microsoft/azure/toolkit/lib/applicationinsights/task/GetOrCreateApplicationInsightsTask.java similarity index 91% rename from azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/task/GetOrCreateApplicationInsightsTask.java rename to azure-toolkit-libs/azure-toolkit-applicationinsights-lib/src/main/java/com/microsoft/azure/toolkit/lib/applicationinsights/task/GetOrCreateApplicationInsightsTask.java index fc16441657..022f3a1a0d 100644 --- a/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/task/GetOrCreateApplicationInsightsTask.java +++ b/azure-toolkit-libs/azure-toolkit-applicationinsights-lib/src/main/java/com/microsoft/azure/toolkit/lib/applicationinsights/task/GetOrCreateApplicationInsightsTask.java @@ -1,4 +1,9 @@ -package com.microsoft.azure.toolkit.lib.appservice.task; +/* + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + */ + +package com.microsoft.azure.toolkit.lib.applicationinsights.task; import com.azure.core.management.AzureEnvironment; import com.azure.core.management.exception.ManagementException; diff --git a/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/task/CreateOrUpdateFunctionAppTask.java b/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/task/CreateOrUpdateFunctionAppTask.java index 691ad367fe..269ef08cea 100644 --- a/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/task/CreateOrUpdateFunctionAppTask.java +++ b/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/task/CreateOrUpdateFunctionAppTask.java @@ -7,6 +7,7 @@ import com.microsoft.azure.toolkit.lib.Azure; import com.microsoft.azure.toolkit.lib.applicationinsights.ApplicationInsightsEntity; +import com.microsoft.azure.toolkit.lib.applicationinsights.task.GetOrCreateApplicationInsightsTask; import com.microsoft.azure.toolkit.lib.appservice.AzureAppService; import com.microsoft.azure.toolkit.lib.appservice.config.AppServicePlanConfig; import com.microsoft.azure.toolkit.lib.appservice.config.FunctionAppConfig; From 077346467a42c25d521c6e1aa5006a4176de17fa Mon Sep 17 00:00:00 2001 From: Hanxiao Liu Date: Sat, 18 Sep 2021 09:37:15 +0800 Subject: [PATCH 068/126] Migrate to use function creation task in function maven plugin --- .../maven/function/AbstractFunctionMojo.java | 5 + .../azure/maven/function/ConfigParser.java | 78 ++++ .../azure/maven/function/DeployMojo.java | 342 +----------------- .../azure/maven/AbstractAppServiceMojo.java | 1 + 4 files changed, 98 insertions(+), 328 deletions(-) create mode 100644 azure-functions-maven-plugin/src/main/java/com/microsoft/azure/maven/function/ConfigParser.java diff --git a/azure-functions-maven-plugin/src/main/java/com/microsoft/azure/maven/function/AbstractFunctionMojo.java b/azure-functions-maven-plugin/src/main/java/com/microsoft/azure/maven/function/AbstractFunctionMojo.java index ad7842d829..be0f618780 100644 --- a/azure-functions-maven-plugin/src/main/java/com/microsoft/azure/maven/function/AbstractFunctionMojo.java +++ b/azure-functions-maven-plugin/src/main/java/com/microsoft/azure/maven/function/AbstractFunctionMojo.java @@ -9,6 +9,7 @@ import com.microsoft.azure.toolkit.lib.appservice.service.IFunctionApp; import com.microsoft.azure.toolkit.lib.common.exception.AzureToolkitRuntimeException; import com.microsoft.azure.toolkit.lib.legacy.function.configurations.RuntimeConfiguration; +import lombok.Getter; import org.apache.commons.lang3.StringUtils; import org.apache.maven.plugins.annotations.Parameter; @@ -44,6 +45,7 @@ public abstract class AbstractFunctionMojo extends AbstractAppServiceMojo { *
  • P3V2
  • * */ + @Getter @Parameter(property = "functions.pricingTier") protected String pricingTier; @@ -79,6 +81,9 @@ public abstract class AbstractFunctionMojo extends AbstractAppServiceMojo { @Parameter(property = "functions.disableAppInsights", defaultValue = "false") protected boolean disableAppInsights; + @Getter + protected ConfigParser parser = new ConfigParser(this); + //endregion //region Getter diff --git a/azure-functions-maven-plugin/src/main/java/com/microsoft/azure/maven/function/ConfigParser.java b/azure-functions-maven-plugin/src/main/java/com/microsoft/azure/maven/function/ConfigParser.java new file mode 100644 index 0000000000..a00c05b60b --- /dev/null +++ b/azure-functions-maven-plugin/src/main/java/com/microsoft/azure/maven/function/ConfigParser.java @@ -0,0 +1,78 @@ +/* + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + */ +package com.microsoft.azure.maven.function; + +import com.microsoft.azure.maven.MavenDockerCredentialProvider; +import com.microsoft.azure.toolkit.lib.appservice.config.FunctionAppConfig; +import com.microsoft.azure.toolkit.lib.appservice.config.RuntimeConfig; +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.PricingTier; +import com.microsoft.azure.toolkit.lib.appservice.model.WebContainer; +import com.microsoft.azure.toolkit.lib.common.exception.AzureExecutionException; +import com.microsoft.azure.toolkit.lib.common.model.Region; +import com.microsoft.azure.toolkit.lib.legacy.appservice.DeploymentSlotSetting; +import com.microsoft.azure.toolkit.lib.legacy.function.configurations.RuntimeConfiguration; +import org.apache.commons.lang3.StringUtils; + +import java.util.Optional; + +public class ConfigParser { + private final AbstractFunctionMojo mojo; + + public ConfigParser(AbstractFunctionMojo mojo) { + this.mojo = mojo; + } + + public FunctionAppConfig parseConfig() throws AzureExecutionException { + return (FunctionAppConfig) new FunctionAppConfig() + .disableAppInsights(mojo.isDisableAppInsights()) + .appInsightsKey(mojo.getAppInsightsKey()) + .appInsightsInstance(mojo.getAppInsightsInstance()) + .subscriptionId(mojo.getSubscriptionId()) + .resourceGroup(mojo.getResourceGroup()) + .appName(mojo.getAppName()) + .servicePlanName(mojo.getAppServicePlanName()) + .servicePlanResourceGroup(mojo.getAppServicePlanResourceGroup()) + .deploymentSlotName(getDeploymentSlotName()) + .deploymentSlotConfigurationSource(getDeploymentSlotConfigurationSource()) + .pricingTier(getParsedPricingTier()) + .region(getParsedRegion()) + .runtime(getRuntimeConfig()) + .appSettings(mojo.getAppSettings()); + } + + public RuntimeConfig getRuntimeConfig() throws AzureExecutionException { + final RuntimeConfiguration runtime = mojo.getRuntimeConfiguration(); + if (runtime == null) { + return null; + } + final OperatingSystem os = Optional.ofNullable(runtime.getOs()).map(OperatingSystem::fromString).orElse(null); + final JavaVersion javaVersion = Optional.ofNullable(runtime.getJavaVersion()).map(JavaVersion::fromString).orElse(null); + final RuntimeConfig result = new RuntimeConfig().os(os).javaVersion(javaVersion).webContainer(WebContainer.JAVA_OFF) + .image(runtime.getImage()).registryUrl(runtime.getRegistryUrl()); + if (StringUtils.isNotEmpty(runtime.getServerId())) { + final MavenDockerCredentialProvider credentialProvider = MavenDockerCredentialProvider.fromMavenSettings(mojo.getSettings(), runtime.getServerId()); + result.username(credentialProvider.getUsername()).password(credentialProvider.getPassword()); + } + return result; + } + + private String getDeploymentSlotName() { + return Optional.ofNullable(mojo.getDeploymentSlotSetting()).map(DeploymentSlotSetting::getName).orElse(null); + } + + private String getDeploymentSlotConfigurationSource() { + return Optional.ofNullable(mojo.getDeploymentSlotSetting()).map(DeploymentSlotSetting::getConfigurationSource).orElse(null); + } + + private Region getParsedRegion() { + return Optional.ofNullable(mojo.getRegion()).map(Region::fromName).orElse(null); + } + + private PricingTier getParsedPricingTier() { + return Optional.ofNullable(mojo.getPricingTier()).map(PricingTier::fromString).orElse(null); + } +} diff --git a/azure-functions-maven-plugin/src/main/java/com/microsoft/azure/maven/function/DeployMojo.java b/azure-functions-maven-plugin/src/main/java/com/microsoft/azure/maven/function/DeployMojo.java index fb5d8a2948..b6d73698d9 100644 --- a/azure-functions-maven-plugin/src/main/java/com/microsoft/azure/maven/function/DeployMojo.java +++ b/azure-functions-maven-plugin/src/main/java/com/microsoft/azure/maven/function/DeployMojo.java @@ -5,38 +5,24 @@ package com.microsoft.azure.maven.function; -import com.azure.core.management.AzureEnvironment; -import com.azure.core.management.exception.ManagementException; import com.microsoft.azure.functions.annotation.AuthorizationLevel; -import com.microsoft.azure.maven.MavenDockerCredentialProvider; -import com.microsoft.azure.toolkit.lib.Azure; -import com.microsoft.azure.toolkit.lib.applicationinsights.ApplicationInsights; -import com.microsoft.azure.toolkit.lib.applicationinsights.ApplicationInsightsEntity; -import com.microsoft.azure.toolkit.lib.appservice.AzureAppService; +import com.microsoft.azure.toolkit.lib.appservice.config.FunctionAppConfig; +import com.microsoft.azure.toolkit.lib.appservice.config.RuntimeConfig; import com.microsoft.azure.toolkit.lib.appservice.entity.AppServiceBaseEntity; import com.microsoft.azure.toolkit.lib.appservice.entity.FunctionEntity; -import com.microsoft.azure.toolkit.lib.appservice.model.DockerConfiguration; 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.OperatingSystem; import com.microsoft.azure.toolkit.lib.appservice.model.PricingTier; -import com.microsoft.azure.toolkit.lib.appservice.model.Runtime; -import com.microsoft.azure.toolkit.lib.appservice.model.WebContainer; -import com.microsoft.azure.toolkit.lib.appservice.service.IAppServicePlan; -import com.microsoft.azure.toolkit.lib.appservice.service.IAppServiceUpdater; import com.microsoft.azure.toolkit.lib.appservice.service.IFunctionApp; import com.microsoft.azure.toolkit.lib.appservice.service.IFunctionAppBase; -import com.microsoft.azure.toolkit.lib.appservice.service.IFunctionAppDeploymentSlot; -import com.microsoft.azure.toolkit.lib.auth.AzureAccount; +import com.microsoft.azure.toolkit.lib.appservice.task.CreateOrUpdateFunctionAppTask; import com.microsoft.azure.toolkit.lib.common.bundle.AzureString; import com.microsoft.azure.toolkit.lib.common.exception.AzureExecutionException; 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.model.ResourceGroup; import com.microsoft.azure.toolkit.lib.common.utils.Utils; -import com.microsoft.azure.toolkit.lib.legacy.appservice.DeploymentSlotSetting; -import com.microsoft.azure.toolkit.lib.resource.AzureGroup; import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.io.FilenameUtils; import org.apache.commons.lang3.StringUtils; @@ -52,10 +38,7 @@ import java.time.Duration; import java.util.Arrays; import java.util.List; -import java.util.Map; -import java.util.Objects; import java.util.Optional; -import java.util.Properties; import java.util.stream.Collectors; /** @@ -63,31 +46,11 @@ */ @Mojo(name = "deploy", defaultPhase = LifecyclePhase.DEPLOY) public class DeployMojo extends AbstractFunctionMojo { - private static final String DEPLOY_START = "Starting deployment..."; - private static final String DEPLOY_FINISH = - "Deployment done, you may access your resource through %s"; - private static final String FUNCTION_SLOT_CREATE_START = "The specified function slot does not exist. " + - "Creating a new slot..."; - private static final String FUNCTION_SLOT_CREATED = "Successfully created the function slot: %s."; - private static final String FUNCTION_SLOT_UPDATE = "Updating the specified function slot..."; - private static final String FUNCTION_SLOT_UPDATE_DONE = "Successfully updated the function slot: %s."; - private static final String APPINSIGHTS_INSTRUMENTATION_KEY = "APPINSIGHTS_INSTRUMENTATIONKEY"; + private static final String DEPLOY_FINISH = "Deployment done, you may access your resource through %s"; private static final String APPLICATION_INSIGHTS_CONFIGURATION_CONFLICT = "Contradictory configurations for application insights," + " specify 'appInsightsKey' or 'appInsightsInstance' if you want to enable it, and specify " + "'disableAppInsights=true' if you want to disable it."; - private static final String FAILED_TO_GET_APPLICATION_INSIGHTS = "The application insights %s cannot be found, " + - "will create it in resource group %s."; - private static final String SKIP_CREATING_APPLICATION_INSIGHTS = "Skip creating application insights"; - private static final String APPLICATION_INSIGHTS_CREATE_START = "Creating application insights..."; - private static final String APPLICATION_INSIGHTS_CREATED = "Successfully created the application insights %s " + - "for this Function App. You can visit %s/#@/resource%s/overview to view your " + - "Application Insights component."; - private static final String APPLICATION_INSIGHTS_CREATE_FAILED = "Unable to create the Application Insights " + - "for the Function App due to error %s. Please use the Azure Portal to manually create and configure the " + - "Application Insights if needed."; - private static final String INSTRUMENTATION_KEY_IS_NOT_VALID = "Instrumentation key is not valid, " + - "please update the application insights configuration"; private static final String UNABLE_TO_LIST_NONE_ANONYMOUS_HTTP_TRIGGERS = "Some http trigger urls cannot be displayed " + "because they are non-anonymous. To access the non-anonymous triggers, please refer to https://aka.ms/azure-functions-key."; private static final String HTTP_TRIGGER_URLS = "HTTP Trigger Urls:"; @@ -98,27 +61,7 @@ public class DeployMojo extends AbstractFunctionMojo { "configuration."; private static final String ARTIFACT_INCOMPATIBLE_ERROR = "Your function app artifact compile version {0} is not compatible with java version {1} in " + "configuration, please downgrade the project compile version and try again."; - private static final String FUNCTIONS_WORKER_RUNTIME_NAME = "FUNCTIONS_WORKER_RUNTIME"; - private static final String FUNCTIONS_WORKER_RUNTIME_VALUE = "java"; - private static final String SET_FUNCTIONS_WORKER_RUNTIME = "Set function worker runtime to java."; - private static final String CUSTOMIZED_FUNCTIONS_WORKER_RUNTIME_WARNING = "App setting `FUNCTIONS_WORKER_RUNTIME` doesn't " + - "meet the requirement of Azure Java Functions, the value should be `java`."; - private static final String FUNCTIONS_EXTENSION_VERSION_NAME = "FUNCTIONS_EXTENSION_VERSION"; - private static final String FUNCTIONS_EXTENSION_VERSION_VALUE = "~3"; - private static final String SET_FUNCTIONS_EXTENSION_VERSION = "Functions extension version " + - "isn't configured, setting up the default value."; private static final String RUNNING = "Running"; - private static final String CREATE_FUNCTION_APP = "Creating function app %s..."; - private static final String CREATE_FUNCTION_APP_DONE = "Successfully created function app %s."; - private static final String CREATE_APP_SERVICE_PLAN = "Creating app service plan..."; - private static final String CREATE_APP_SERVICE_DONE = "Successfully created app service plan %s."; - private static final String CREATE_RESOURCE_GROUP = "Creating resource group %s in region %s..."; - private static final String CREATE_RESOURCE_GROUP_DONE = "Successfully created resource group %s."; - private static final String CREATE_NEW_FUNCTION_APP = "isCreateNewFunctionApp"; - private static final String CREATE_NEW_APP_SERVICE_PLAN = "createNewAppServicePlan"; - private static final String CREATE_NEW_RESOURCE_GROUP = "createNewResourceGroup"; - private static final String UPDATE_FUNCTION_APP = "Updating target Function App %s..."; - private static final String UPDATE_FUNCTION_DONE = "Successfully updated Function App %s."; private static final String NO_ARTIFACT_FOUNDED = "Failed to find function artifact '%s.jar' in folder '%s', please re-package the project and try again."; private static final String LOCAL_SETTINGS_FILE = "local.settings.json"; private static final int LIST_TRIGGERS_MAX_RETRY = 5; @@ -151,16 +94,12 @@ public class DeployMojo extends AbstractFunctionMojo { "please refer to https://aka.ms/maven_function_configuration#supported-regions for valid values"; private static final String EXPANDABLE_JAVA_VERSION_WARNING = "'%s' may not be a valid java version, recommended values are `Java 8` and `Java 11`"; - private AzureAppService az; - @Override protected void doExecute() throws AzureExecutionException { doValidate(); - processAppSettingsWithDefaultValue(); - - az = getOrCreateAzureAppServiceClient(); - final IFunctionAppBase target = createOrUpdateResource(); + getOrCreateAzureAppServiceClient(); + final IFunctionAppBase target = createOrUpdateResource(getParser().parseConfig()); deployArtifact(target); if (target instanceof IFunctionApp) { @@ -228,174 +167,8 @@ protected void validateParameters() { } } - protected IFunctionAppBase createOrUpdateResource() throws AzureExecutionException { - final String deploymentSlotName = Optional.ofNullable(deploymentSlotSetting) - .map(DeploymentSlotSetting::getName).orElse(null); - final IFunctionApp functionApp = az.functionApp(getResourceGroup(), getAppName()); - if (StringUtils.isEmpty(deploymentSlotName)) { - return functionApp.exists() ? updateFunctionApp(functionApp) : createFunctionApp(functionApp); - } else { - final IFunctionAppDeploymentSlot slot = functionApp.deploymentSlot(deploymentSlotName); - return slot.exists() ? updateDeploymentSlot(slot) : createDeploymentSlot(slot); - } - } - - protected IFunctionApp createFunctionApp(final IFunctionApp functionApp) throws AzureExecutionException { - getTelemetryProxy().addDefaultProperty(CREATE_NEW_FUNCTION_APP, String.valueOf(true)); - final ResourceGroup resourceGroup = getOrCreateResourceGroup(); - final IAppServicePlan appServicePlan = getOrCreateAppServicePlan(); - AzureMessager.getMessager().info(String.format(CREATE_FUNCTION_APP, getAppName())); - final Runtime runtime = getRuntimeOrDefault(); - final Map appSettings = getAppSettings(); - // get/create ai instances only if user didn't specify ai connection string in app settings - bindApplicationInsights(appSettings, true); - final IFunctionApp result = functionApp.create().withName(getAppName()) - .withResourceGroup(resourceGroup.getName()) - .withPlan(appServicePlan.id()) - .withRuntime(runtime) - .withDockerConfiguration(getDockerConfiguration()) - .withAppSettings(appSettings) - .commit(); - AzureMessager.getMessager().info(String.format(CREATE_FUNCTION_APP_DONE, result.name())); - return result; - } - - private IAppServicePlan getOrCreateAppServicePlan() { - final String servicePlanName = StringUtils.isEmpty(getAppServicePlanName()) ? - String.format("asp-%s", getAppName()) : getAppServicePlanName(); - final String servicePlanGroup = getServicePlanResourceGroup(); - final IAppServicePlan appServicePlan = az.appServicePlan(servicePlanGroup, servicePlanName); - if (!appServicePlan.exists()) { - AzureMessager.getMessager().info(CREATE_APP_SERVICE_PLAN); - getTelemetryProxy().addDefaultProperty(CREATE_NEW_APP_SERVICE_PLAN, String.valueOf(true)); - appServicePlan.create() - .withName(servicePlanName) - .withResourceGroup(servicePlanGroup) - .withRegion(getParsedRegion()) - .withPricingTier(getParsedPricingTier()) - .withOperatingSystem(getRuntimeOrDefault().getOperatingSystem()) - .commit(); - AzureMessager.getMessager().info(String.format(CREATE_APP_SERVICE_DONE, appServicePlan.name())); - } - return appServicePlan; - } - - private Region getParsedRegion() { - return Optional.ofNullable(region).map(Region::fromName).orElse(Region.US_WEST); - } - - private PricingTier getParsedPricingTier() { - if (StringUtils.isEmpty(pricingTier)) { - return PricingTier.CONSUMPTION; - } - return Optional.ofNullable(PricingTier.fromString(pricingTier)) - .orElseThrow(() -> new AzureToolkitRuntimeException(String.format("Invalid pricing tier %s", pricingTier))); - } - - private ResourceGroup getOrCreateResourceGroup() { - try { - return Azure.az(AzureGroup.class).getByName(getResourceGroup()); - } catch (ManagementException e) { - AzureMessager.getMessager().info(String.format(CREATE_RESOURCE_GROUP, getResourceGroup(), getRegion())); - getTelemetryProxy().addDefaultProperty(CREATE_NEW_RESOURCE_GROUP, String.valueOf(true)); - final ResourceGroup result = Azure.az(AzureGroup.class).create(getResourceGroup(), getRegion()); - AzureMessager.getMessager().info(String.format(CREATE_RESOURCE_GROUP_DONE, result.getName())); - return result; - } - } - - private Runtime getRuntimeOrDefault() { - final OperatingSystem os = Optional.ofNullable(runtime.getOs()).map(OperatingSystem::fromString).orElse(OperatingSystem.WINDOWS); - final JavaVersion javaVersion = Optional.ofNullable(runtime.getJavaVersion()).map(JavaVersion::fromString).orElse(JavaVersion.JAVA_8); - return Runtime.getRuntime(os, WebContainer.JAVA_OFF, javaVersion); - } - - private Runtime getRuntime() { - if (StringUtils.isEmpty(runtime.getOs()) && StringUtils.isEmpty(runtime.getJavaVersion())) { - return null; - } - final OperatingSystem os = OperatingSystem.fromString(runtime.getOs()); - final JavaVersion javaVersion = JavaVersion.fromString(runtime.getJavaVersion()); - return Runtime.getRuntime(os, WebContainer.JAVA_OFF, javaVersion); - } - - private DockerConfiguration getDockerConfiguration() throws AzureExecutionException { - final OperatingSystem os = Optional.ofNullable(runtime.getOs()).map(OperatingSystem::fromString).orElse(null); - if (os != OperatingSystem.DOCKER) { - return null; - } - final MavenDockerCredentialProvider credentialProvider = MavenDockerCredentialProvider.fromMavenSettings(getSettings(), runtime.getServerId()); - return DockerConfiguration.builder() - .registryUrl(runtime.getRegistryUrl()) - .image(runtime.getImage()) - .userName(credentialProvider.getUsername()) - .password(credentialProvider.getPassword()).build(); - } - - protected IFunctionApp updateFunctionApp(final IFunctionApp functionApp) throws AzureExecutionException { - // update app service plan - AzureMessager.getMessager().info(String.format(UPDATE_FUNCTION_APP, functionApp.name())); - final IAppServicePlan currentPlan = functionApp.plan(); - IAppServicePlan targetServicePlan = StringUtils.isEmpty(appServicePlanName) ? currentPlan : - az.appServicePlan(getServicePlanResourceGroup(), appServicePlanName); - if (!targetServicePlan.exists()) { - targetServicePlan = getOrCreateAppServicePlan(); - } else { - if (region != null && !Objects.equals(Region.fromName(region), Region.fromName(targetServicePlan.entity().getRegion()))) { - AzureMessager.getMessager().warning(String.format("Skip region update for existing service plan '%s' since it is not allowed.", - targetServicePlan.name())); - } - if (StringUtils.isNotEmpty(pricingTier)) { - targetServicePlan.update().withPricingTier(getParsedPricingTier()).commit(); - } - } - // update app settings - final Map appSettings = getAppSettings(); - final IAppServiceUpdater update = functionApp.update(); - if (isDisableAppInsights()) { - update.withoutAppSettings(APPINSIGHTS_INSTRUMENTATION_KEY); - } else { - bindApplicationInsights(appSettings, false); - } - final IFunctionApp result = update.withPlan(targetServicePlan.id()) - .withRuntime(getRuntime()) - .withDockerConfiguration(getDockerConfiguration()) - .withAppSettings(appSettings) - .commit(); - AzureMessager.getMessager().info(String.format(UPDATE_FUNCTION_DONE, functionApp.name())); - return result; - } - - private String getServicePlanResourceGroup() { - return StringUtils.isEmpty(getAppServicePlanResourceGroup()) ? getResourceGroup() : getAppServicePlanResourceGroup(); - } - - protected IFunctionAppDeploymentSlot createDeploymentSlot(final IFunctionAppDeploymentSlot deploymentSlot) - throws AzureExecutionException { - AzureMessager.getMessager().info(FUNCTION_SLOT_CREATE_START); - final DeploymentSlotSetting slotSetting = getDeploymentSlotSetting(); - final Map appSettings = getAppSettings(); - bindApplicationInsights(appSettings, false); - final IFunctionAppDeploymentSlot result = deploymentSlot.create().withAppSettings(appSettings) - .withConfigurationSource(slotSetting.getConfigurationSource()) - .withName(slotSetting.getName()).commit(); - AzureMessager.getMessager().info(String.format(FUNCTION_SLOT_CREATED, result.name())); - return result; - } - - protected IFunctionAppDeploymentSlot updateDeploymentSlot(final IFunctionAppDeploymentSlot deploymentSlot) throws AzureExecutionException { - AzureMessager.getMessager().info(FUNCTION_SLOT_UPDATE); - final Map appSettings = getAppSettings(); - final IFunctionAppDeploymentSlot.Updater update = deploymentSlot.update(); - // todo: remove duplicate codes with update function - if (isDisableAppInsights()) { - update.withoutAppSettings(APPINSIGHTS_INSTRUMENTATION_KEY); - } else { - bindApplicationInsights(appSettings, false); - } - final IFunctionAppDeploymentSlot result = update.withAppSettings(appSettings).commit(); - AzureMessager.getMessager().info(String.format(FUNCTION_SLOT_UPDATE_DONE, result.name())); - return deploymentSlot; + protected IFunctionAppBase createOrUpdateResource(final FunctionAppConfig config) { + return new CreateOrUpdateFunctionAppTask(config).execute(); } private void deployArtifact(IFunctionAppBase target) throws AzureExecutionException { @@ -464,20 +237,21 @@ private List listFunctions(final IFunctionApp functionApp) { .filter(CollectionUtils::isNotEmpty) .orElseThrow(() -> new AzureToolkitRuntimeException(NO_TRIGGERS_FOUNDED)); }).subscribeOn(Schedulers.boundedElastic()) - .retryWhen(Retry.fixedDelay(LIST_TRIGGERS_MAX_RETRY - 1, Duration.ofSeconds(LIST_TRIGGERS_RETRY_PERIOD_IN_SECONDS))).block(); + .retryWhen(Retry.fixedDelay(LIST_TRIGGERS_MAX_RETRY - 1, Duration.ofSeconds(LIST_TRIGGERS_RETRY_PERIOD_IN_SECONDS))).block(); } protected void validateArtifactCompileVersion() throws AzureExecutionException { - final Runtime runtime = getRuntimeOrDefault(); - if (runtime.isDocker()) { + final RuntimeConfig runtimeConfig = getParser().getRuntimeConfig(); + if (runtimeConfig.os() == OperatingSystem.DOCKER) { return; } - final ComparableVersion runtimeVersion = new ComparableVersion(runtime.getJavaVersion().getValue()); + final JavaVersion javaVersion = Optional.ofNullable(runtimeConfig.javaVersion()).orElse(CreateOrUpdateFunctionAppTask.DEFAULT_FUNCTION_JAVA_VERSION); + final ComparableVersion runtimeVersion = new ComparableVersion(javaVersion.getValue()); final ComparableVersion artifactVersion = new ComparableVersion(Utils.getArtifactCompileVersion(getArtifactToDeploy())); if (runtimeVersion.compareTo(artifactVersion) >= 0) { return; } - if (runtime.getJavaVersion().isExpandedValue()) { + if (javaVersion.isExpandedValue()) { AzureMessager.getMessager().warning(AzureString.format(ARTIFACT_INCOMPATIBLE_WARNING, artifactVersion.toString(), runtimeVersion.toString())); } else { final String errorMessage = AzureString.format(ARTIFACT_INCOMPATIBLE_ERROR, artifactVersion.toString(), runtimeVersion.toString()).toString(); @@ -485,30 +259,6 @@ protected void validateArtifactCompileVersion() throws AzureExecutionException { } } - public void processAppSettingsWithDefaultValue() { - if (appSettings == null) { - appSettings = new Properties(); - } - setDefaultAppSetting(appSettings, FUNCTIONS_WORKER_RUNTIME_NAME, SET_FUNCTIONS_WORKER_RUNTIME, - FUNCTIONS_WORKER_RUNTIME_VALUE, CUSTOMIZED_FUNCTIONS_WORKER_RUNTIME_WARNING); - setDefaultAppSetting(appSettings, FUNCTIONS_EXTENSION_VERSION_NAME, SET_FUNCTIONS_EXTENSION_VERSION, - FUNCTIONS_EXTENSION_VERSION_VALUE, null); - } - - private void setDefaultAppSetting(Map result, String settingName, String settingIsEmptyMessage, - String defaultValue, String warningMessage) { - final String setting = (String) result.get(settingName); - if (StringUtils.isEmpty(setting)) { - AzureMessager.getMessager().info(settingIsEmptyMessage); - result.put(settingName, defaultValue); - return; - } - // Show warning message when user set a different value - if (!StringUtils.equalsIgnoreCase(setting, defaultValue) && StringUtils.isNotEmpty(warningMessage)) { - AzureMessager.getMessager().warning(warningMessage); - } - } - private File getArtifactToDeploy() throws AzureExecutionException { final File stagingFolder = new File(getDeploymentStagingDirectoryPath()); return Arrays.stream(Optional.ofNullable(stagingFolder.listFiles()).orElse(new File[0])) @@ -517,73 +267,9 @@ private File getArtifactToDeploy() throws AzureExecutionException { .orElseThrow(() -> new AzureExecutionException(String.format(NO_ARTIFACT_FOUNDED, this.getFinalName(), stagingFolder))); } - /** - * Binding Function App with Application Insights - * Will follow the below sequence appInsightsKey -> appInsightsInstance -> Create New AI Instance (Function creation only) - * - * @param appSettings App settings map - * @param isCreation Define the stage of function app, as we only create ai instance by default when create new function apps - * @throws AzureExecutionException When there are conflicts in configuration or meet errors while finding/creating application insights instance - */ - private void bindApplicationInsights(Map appSettings, boolean isCreation) throws AzureExecutionException { - // Skip app insights creation when user specify ai connection string in app settings - if (appSettings.containsKey(APPINSIGHTS_INSTRUMENTATION_KEY)) { - return; - } - final String instrumentationKey; - if (StringUtils.isNotEmpty(getAppInsightsKey())) { - instrumentationKey = getAppInsightsKey(); - if (!Utils.isGUID(instrumentationKey)) { - throw new AzureExecutionException(INSTRUMENTATION_KEY_IS_NOT_VALID); - } - } else { - final ApplicationInsightsEntity applicationInsightsComponent = getOrCreateApplicationInsights(isCreation); - instrumentationKey = applicationInsightsComponent == null ? null : applicationInsightsComponent.getInstrumentationKey(); - } - if (StringUtils.isNotEmpty(instrumentationKey)) { - appSettings.put(APPINSIGHTS_INSTRUMENTATION_KEY, instrumentationKey); - } - } - private void validateApplicationInsightsConfiguration() throws AzureExecutionException { if (isDisableAppInsights() && (StringUtils.isNotEmpty(getAppInsightsKey()) || StringUtils.isNotEmpty(getAppInsightsInstance()))) { throw new AzureExecutionException(APPLICATION_INSIGHTS_CONFIGURATION_CONFLICT); } } - - private ApplicationInsightsEntity getOrCreateApplicationInsights(boolean enableCreation) { - return StringUtils.isNotEmpty(getAppInsightsInstance()) ? getApplicationInsights(getAppInsightsInstance()) : - enableCreation ? createApplicationInsights(getAppName()) : null; - } - - private ApplicationInsightsEntity getApplicationInsights(String appInsightsInstance) { - ApplicationInsightsEntity resource; - try { - resource = Azure.az(ApplicationInsights.class).get(getResourceGroup(), appInsightsInstance); - } catch (ManagementException e) { - resource = null; - } - if (resource == null) { - AzureMessager.getMessager().warning(String.format(FAILED_TO_GET_APPLICATION_INSIGHTS, appInsightsInstance, getResourceGroup())); - return createApplicationInsights(appInsightsInstance); - } - return resource; - } - - private ApplicationInsightsEntity createApplicationInsights(String name) { - if (isDisableAppInsights()) { - AzureMessager.getMessager().info(SKIP_CREATING_APPLICATION_INSIGHTS); - return null; - } - try { - AzureMessager.getMessager().info(APPLICATION_INSIGHTS_CREATE_START); - final AzureEnvironment environment = Azure.az(AzureAccount.class).account().getEnvironment(); - final ApplicationInsightsEntity resource = Azure.az(ApplicationInsights.class).create(getResourceGroup(), Region.fromName(getRegion()), name); - AzureMessager.getMessager().info(String.format(APPLICATION_INSIGHTS_CREATED, resource.getName(), getPortalUrl(environment), resource.getId())); - return resource; - } catch (Exception e) { - AzureMessager.getMessager().warning(String.format(APPLICATION_INSIGHTS_CREATE_FAILED, e.getMessage())); - return null; - } - } } diff --git a/azure-maven-plugin-lib/src/main/java/com/microsoft/azure/maven/AbstractAppServiceMojo.java b/azure-maven-plugin-lib/src/main/java/com/microsoft/azure/maven/AbstractAppServiceMojo.java index f89b1244af..01e8f1cccf 100644 --- a/azure-maven-plugin-lib/src/main/java/com/microsoft/azure/maven/AbstractAppServiceMojo.java +++ b/azure-maven-plugin-lib/src/main/java/com/microsoft/azure/maven/AbstractAppServiceMojo.java @@ -192,6 +192,7 @@ protected AzureAppService getOrCreateAzureAppServiceClient() { com.microsoft.azure.toolkit.lib.Azure.az(AzureAccount.class).account().selectSubscription(Collections.singletonList(targetSubscriptionId)); appServiceClient = Azure.az(AzureAppService.class).subscription(targetSubscriptionId); printCurrentSubscription(appServiceClient); + this.subscriptionId = targetSubscriptionId; } catch (AzureLoginException | AzureExecutionException | IOException e) { throw new AzureToolkitRuntimeException(String.format("Cannot authenticate due to error %s", e.getMessage()), e); } From b05d74d1e01657ee76f78fbf10d935a1af80efe5 Mon Sep 17 00:00:00 2001 From: andxu Date: Sat, 18 Sep 2021 12:45:24 +0800 Subject: [PATCH 069/126] Add default value for region, pricing tier, os, webContainer and javaVersion --- .../appservice/config/AppServiceConfig.java | 5 +- .../service/impl/AppServiceUtils.java | 3 + .../CreateOrUpdateAppServicePlanTask.java | 21 +++- .../task/CreateOrUpdateWebAppTask.java | 103 ++++++++++++------ .../appservice/CreateAppServicePlan.json | 15 --- .../resources/schema/appservice/Runtime.json | 40 ------- .../azure/maven/webapp/DeployMojo.java | 36 +++++- 7 files changed, 126 insertions(+), 97 deletions(-) delete mode 100644 azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/resources/schema/appservice/CreateAppServicePlan.json diff --git a/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/config/AppServiceConfig.java b/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/config/AppServiceConfig.java index 84b02d7244..06e9551ce4 100644 --- a/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/config/AppServiceConfig.java +++ b/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/config/AppServiceConfig.java @@ -10,6 +10,7 @@ import lombok.Getter; import lombok.Setter; import lombok.experimental.Accessors; +import org.apache.commons.lang3.StringUtils; import java.util.Map; @@ -43,8 +44,8 @@ public class AppServiceConfig { public AppServicePlanConfig getServicePlanConfig() { return new AppServicePlanConfig() .subscriptionId(subscriptionId()) - .servicePlanResourceGroup(servicePlanResourceGroup()) - .servicePlanName(servicePlanName()) + .servicePlanResourceGroup(StringUtils.firstNonBlank(servicePlanResourceGroup(), resourceGroup)) + .servicePlanName(StringUtils.firstNonBlank(servicePlanName(), String.format("asp-%s", appName))) .region(region()) .os(runtime() == null ? null : runtime().os()) .pricingTier(pricingTier()); diff --git a/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/service/impl/AppServiceUtils.java b/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/service/impl/AppServiceUtils.java index dddf1a054f..ceae28619c 100644 --- a/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/service/impl/AppServiceUtils.java +++ b/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/service/impl/AppServiceUtils.java @@ -100,6 +100,9 @@ static RuntimeStack toRuntimeStack(Runtime runtime) { return new RuntimeStack("JAVA", getJavaVersionValueForJavaSERuntimeStack(runtime.getJavaVersion())); } final String[] containerInfo = runtime.getWebContainer().getValue().split(" "); + if (containerInfo.length != 2) { + throw new AzureToolkitRuntimeException(String.format("Invalid webContainer '%s'.", runtime.getWebContainer())); + } final String stack = containerInfo[0]; final String stackVersion = containerInfo[1]; final String javaVersion = getJavaVersionValueForContainerRuntimeStack(runtime.getJavaVersion()); diff --git a/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/task/CreateOrUpdateAppServicePlanTask.java b/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/task/CreateOrUpdateAppServicePlanTask.java index ac2429cf7f..cae81fbd51 100644 --- a/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/task/CreateOrUpdateAppServicePlanTask.java +++ b/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/task/CreateOrUpdateAppServicePlanTask.java @@ -9,14 +9,19 @@ import com.microsoft.azure.toolkit.lib.appservice.AzureAppService; import com.microsoft.azure.toolkit.lib.appservice.config.AppServicePlanConfig; import com.microsoft.azure.toolkit.lib.appservice.service.IAppServicePlan; +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.operation.AzureOperation; import com.microsoft.azure.toolkit.lib.common.task.AzureTask; import com.microsoft.azure.toolkit.lib.common.telemetry.AzureTelemetry; import com.microsoft.azure.toolkit.lib.common.validator.SchemaValidator; +import com.microsoft.azure.toolkit.lib.resource.task.CreateResourceGroupTask; import lombok.AllArgsConstructor; +import org.apache.commons.lang3.ObjectUtils; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; import java.util.Objects; @AllArgsConstructor @@ -24,7 +29,10 @@ public class CreateOrUpdateAppServicePlanTask extends AzureTask private static final String CREATE_APP_SERVICE_PLAN = "Creating app service plan %s..."; private static final String CREATE_APP_SERVICE_PLAN_DONE = "Successfully created app service plan %s."; private static final String CREATE_NEW_APP_SERVICE_PLAN = "createNewAppServicePlan"; + @Nonnull private AppServicePlanConfig config; + @Nullable + private AppServicePlanConfig defaultConfig; @AzureOperation(name = "appservice|plan.create_update", params = {"this.config.servicePlanName()"}, type = AzureOperation.Type.SERVICE) public IAppServicePlan execute() { @@ -33,16 +41,19 @@ public IAppServicePlan execute() { final IAppServicePlan appServicePlan = az.appServicePlan(config.servicePlanResourceGroup(), config.servicePlanName()); final String servicePlanName = config.servicePlanName(); if (!appServicePlan.exists()) { - SchemaValidator.getInstance().validateAndThrow("appservice/CreateAppServicePlan", config); AzureMessager.getMessager().info(String.format(CREATE_APP_SERVICE_PLAN, servicePlanName)); AzureTelemetry.getActionContext().setProperty(CREATE_NEW_APP_SERVICE_PLAN, String.valueOf(true)); - + if (this.defaultConfig == null) { + throw new AzureToolkitRuntimeException("Cannot create service without default config."); + } + final Region regionOrDefault = ObjectUtils.firstNonNull(this.config.region(), this.defaultConfig.region()); + new CreateResourceGroupTask(this.config.subscriptionId(), config.servicePlanResourceGroup(), regionOrDefault).execute(); appServicePlan.create() .withName(servicePlanName) .withResourceGroup(config.servicePlanResourceGroup()) - .withPricingTier(config.pricingTier()) - .withRegion(config.region()) - .withOperatingSystem(config.os()) + .withPricingTier(ObjectUtils.firstNonNull(config.pricingTier(), defaultConfig.pricingTier())) + .withRegion(regionOrDefault) + .withOperatingSystem(ObjectUtils.firstNonNull(config.os(), defaultConfig.os())) .commit(); AzureMessager.getMessager().info(String.format(CREATE_APP_SERVICE_PLAN_DONE, appServicePlan.name())); } else { diff --git a/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/task/CreateOrUpdateWebAppTask.java b/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/task/CreateOrUpdateWebAppTask.java index d4a1784daf..7c955a5f9d 100644 --- a/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/task/CreateOrUpdateWebAppTask.java +++ b/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/task/CreateOrUpdateWebAppTask.java @@ -13,6 +13,7 @@ import com.microsoft.azure.toolkit.lib.appservice.model.DockerConfiguration; 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.PricingTier; import com.microsoft.azure.toolkit.lib.appservice.model.Runtime; import com.microsoft.azure.toolkit.lib.appservice.model.WebContainer; import com.microsoft.azure.toolkit.lib.appservice.service.IAppServicePlan; @@ -21,6 +22,8 @@ import com.microsoft.azure.toolkit.lib.common.entity.CheckNameAvailabilityResultEntity; 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.model.ResourceGroup; import com.microsoft.azure.toolkit.lib.common.operation.AzureOperation; import com.microsoft.azure.toolkit.lib.common.operation.AzureOperation.Type; import com.microsoft.azure.toolkit.lib.common.task.AzureTask; @@ -43,20 +46,17 @@ public class CreateOrUpdateWebAppTask extends AzureTask { private static final String UPDATE_WEBAPP_DONE = "Successfully updated Web App %s."; private final AppServiceConfig config; + private final AppServiceConfig defaultConfig; private final List> subTasks; - public CreateOrUpdateWebAppTask(AppServiceConfig config) { + public CreateOrUpdateWebAppTask(AppServiceConfig config, AppServiceConfig defaultConfig) { this.config = config; + this.defaultConfig = defaultConfig; this.subTasks = this.initTasks(); } private List> initTasks() { final List> tasks = new ArrayList<>(); - tasks.add(new CreateResourceGroupTask(this.config.subscriptionId(), this.config.resourceGroup(), this.config.region())); - if (StringUtils.isNotBlank(this.config.servicePlanResourceGroup()) - && !StringUtils.equalsIgnoreCase(this.config.servicePlanResourceGroup(), this.config.resourceGroup())) { - tasks.add(new CreateResourceGroupTask(this.config.subscriptionId(), this.config.servicePlanResourceGroup(), this.config.region())); - } final AzureString title = AzureString.format("Create new web app({0})", this.config.appName()); AzureAppService az = Azure.az(AzureAppService.class); tasks.add(new AzureTask<>(title, () -> { @@ -70,7 +70,6 @@ private List> initTasks() { result.getUnavailabilityReason()).getString()); } return create(); - } return update(target); })); @@ -81,22 +80,24 @@ private List> initTasks() { private IWebApp create() { AzureTelemetry.getActionContext().setProperty(CREATE_NEW_WEB_APP, String.valueOf(true)); AzureMessager.getMessager().info(String.format(CREATE_WEBAPP, config.appName())); + + // handle default region for resource group + final Region region = ObjectUtils.firstNonNull(this.config.region(), this.defaultConfig.region()); + final ResourceGroup resourceGroup = new CreateResourceGroupTask(this.config.subscriptionId(), this.config.resourceGroup(), region).execute(); + final AzureAppService az = Azure.az(AzureAppService.class).subscription(config.subscriptionId()); final IWebApp webapp = az.webapp(config.resourceGroup(), config.appName()); final AppServicePlanConfig servicePlanConfig = config.getServicePlanConfig(); - // initialize default value for service plan creation - if (StringUtils.isBlank(servicePlanConfig.servicePlanResourceGroup())) { - servicePlanConfig.servicePlanResourceGroup(config.resourceGroup()); - } - if (StringUtils.isBlank(servicePlanConfig.servicePlanName())) { - servicePlanConfig.servicePlanName(String.format("asp-%s", config.appName())); - } - final IAppServicePlan appServicePlan = new CreateOrUpdateAppServicePlanTask(servicePlanConfig).execute(); + final RuntimeConfig runtimeConfigOrDefault = getRuntimeConfigOrDefault(config.runtime(), defaultConfig.runtime()); + final Runtime runtime = getRuntime(runtimeConfigOrDefault); + final IAppServicePlan appServicePlan = new CreateOrUpdateAppServicePlanTask(servicePlanConfig, + buildDefaultAppServicePlanConfig(Region.fromName(resourceGroup.getRegion()), runtime)).execute(); + final IWebApp result = webapp.create().withName(config.appName()) .withResourceGroup(config.resourceGroup()) .withPlan(appServicePlan.id()) - .withRuntime(getRuntime(config.runtime())) - .withDockerConfiguration(getDockerConfiguration(config.runtime())) + .withRuntime(runtime) + .withDockerConfiguration(getDockerConfiguration(runtimeConfigOrDefault)) .withAppSettings(config.appSettings()) .commit(); AzureMessager.getMessager().info(String.format(CREATE_WEB_APP_DONE, result.name())); @@ -109,28 +110,21 @@ private IWebApp update(final IWebApp webApp) { final IAppServicePlan currentPlan = webApp.plan(); final AppServicePlanConfig servicePlanConfig = config.getServicePlanConfig(); - if (StringUtils.isAllBlank(servicePlanConfig.servicePlanResourceGroup(), servicePlanConfig.servicePlanName())) { + if (StringUtils.isAllBlank(config.servicePlanResourceGroup(), config.servicePlanName())) { // initialize service plan creation from exising webapp if user doesn't specify it in config servicePlanConfig.servicePlanResourceGroup(currentPlan.resourceGroup()); servicePlanConfig.servicePlanName(currentPlan.name()); - } else if (StringUtils.isAnyBlank(servicePlanConfig.servicePlanResourceGroup(), servicePlanConfig.servicePlanName())) { - if (StringUtils.isBlank(servicePlanConfig.servicePlanResourceGroup())) { - if (StringUtils.equalsIgnoreCase(servicePlanConfig.servicePlanName(), currentPlan.name())) { - servicePlanConfig.servicePlanResourceGroup(currentPlan.resourceGroup()); - } else { - servicePlanConfig.servicePlanResourceGroup(config.resourceGroup()); - } - } else if (StringUtils.isBlank(servicePlanConfig.servicePlanName())) { - if (StringUtils.equalsIgnoreCase(servicePlanConfig.servicePlanResourceGroup(), currentPlan.resourceGroup())) { - servicePlanConfig.servicePlanName(currentPlan.name()); - } else { - servicePlanConfig.servicePlanName(String.format("asp-%s", config.appName())); - } - } + } else if (StringUtils.equalsIgnoreCase(config.servicePlanName(), currentPlan.name()) && StringUtils.isBlank(config.servicePlanResourceGroup())) { + servicePlanConfig.servicePlanResourceGroup(currentPlan.resourceGroup()); + } else if (StringUtils.equalsIgnoreCase(servicePlanConfig.servicePlanResourceGroup(), currentPlan.resourceGroup()) && + StringUtils.isBlank(config.servicePlanName())) { + servicePlanConfig.servicePlanName(currentPlan.name()); } - final IAppServicePlan appServicePlan = new CreateOrUpdateAppServicePlanTask(servicePlanConfig).execute(); + final Runtime runtime = getRuntime(config.runtime(), webApp.entity().getRuntime()); + final IAppServicePlan appServicePlan = new CreateOrUpdateAppServicePlanTask(servicePlanConfig, + buildDefaultAppServicePlanConfig(webApp.entity().getRegion(), ObjectUtils.firstNonNull(runtime, webApp.entity().getRuntime()))).execute(); final IWebApp result = webApp.update().withPlan(appServicePlan.id()) - .withRuntime(getRuntime(config.runtime())) + .withRuntime(runtime) .withDockerConfiguration(getDockerConfiguration(config.runtime())) .withAppSettings(ObjectUtils.firstNonNull(config.appSettings(), new HashMap<>())) .commit(); @@ -138,6 +132,30 @@ private IWebApp update(final IWebApp webApp) { return result; } + private Runtime getRuntime(RuntimeConfig runtime, Runtime remote) { + if (runtime == null) { + return null; + } + if (runtime.os() == null) { + runtime.os(remote.getOperatingSystem()); + } + if (OperatingSystem.DOCKER == runtime.os()) { + return Runtime.getRuntime(OperatingSystem.DOCKER, WebContainer.JAVA_OFF, JavaVersion.OFF); + } else { + return Runtime.getRuntime(runtime.os(), + ObjectUtils.firstNonNull(runtime.webContainer(), remote.getWebContainer()), + ObjectUtils.firstNonNull(runtime.javaVersion(), remote.getJavaVersion())); + } + } + + private AppServicePlanConfig buildDefaultAppServicePlanConfig(Region region, Runtime runtime) { + final AppServicePlanConfig defaultServicePlanConfig = new AppServicePlanConfig(); + defaultServicePlanConfig.region(region); + defaultServicePlanConfig.os(OperatingSystem.LINUX); + defaultServicePlanConfig.pricingTier(runtime.getWebContainer().equals(WebContainer.JBOSS_7) ? PricingTier.PREMIUM_P1V3 : PricingTier.PREMIUM_P1V2); + return defaultServicePlanConfig; + } + private DockerConfiguration getDockerConfiguration(RuntimeConfig runtime) { if (runtime != null && OperatingSystem.DOCKER == runtime.os()) { return DockerConfiguration.builder() @@ -152,6 +170,23 @@ private DockerConfiguration getDockerConfiguration(RuntimeConfig runtime) { } + private RuntimeConfig getRuntimeConfigOrDefault(RuntimeConfig runtime, RuntimeConfig defaultRuntime) { + if (runtime == null) { + return defaultRuntime; + } + + final RuntimeConfig result = new RuntimeConfig(); + result.os(ObjectUtils.firstNonNull(runtime.os(), defaultRuntime.os())); + result.image(ObjectUtils.firstNonNull(runtime.image(), defaultRuntime.image())); + result.username(ObjectUtils.firstNonNull(runtime.username(), defaultRuntime.username())); + result.password(ObjectUtils.firstNonNull(runtime.password(), defaultRuntime.password())); + result.startUpCommand(ObjectUtils.firstNonNull(runtime.startUpCommand(), defaultRuntime.startUpCommand())); + result.registryUrl(ObjectUtils.firstNonNull(runtime.registryUrl(), defaultRuntime.registryUrl())); + result.javaVersion(ObjectUtils.firstNonNull(runtime.javaVersion(), defaultRuntime.javaVersion())); + result.webContainer(ObjectUtils.firstNonNull(runtime.webContainer(), defaultRuntime.webContainer())); + return result; + } + private Runtime getRuntime(RuntimeConfig runtime) { if (runtime != null && OperatingSystem.DOCKER != runtime.os()) { return Runtime.getRuntime(runtime.os(), diff --git a/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/resources/schema/appservice/CreateAppServicePlan.json b/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/resources/schema/appservice/CreateAppServicePlan.json deleted file mode 100644 index 43b98bf4ca..0000000000 --- a/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/resources/schema/appservice/CreateAppServicePlan.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "App Service Plan - Update", - "description": "Schema for AppServicePlanConfig when update existing service plan", - "allOf": [ - { - "$ref": "classpath:///schema/appservice/AppServicePlan.json" - } - ], - "required": [ - "os", - "region", - "pricingTier" - ] -} diff --git a/azure-toolkit-libs/azure-toolkit-common-lib/src/main/resources/schema/appservice/Runtime.json b/azure-toolkit-libs/azure-toolkit-common-lib/src/main/resources/schema/appservice/Runtime.json index d869b6ef55..4d9db6abe8 100644 --- a/azure-toolkit-libs/azure-toolkit-common-lib/src/main/resources/schema/appservice/Runtime.json +++ b/azure-toolkit-libs/azure-toolkit-common-lib/src/main/resources/schema/appservice/Runtime.json @@ -32,46 +32,6 @@ "image" ] }, - "required": [ - "os" - ], - "allOf": [ - { - "if": { - "properties": { - "os": { - "pattern": "(?i)^(windows|linux)$" - } - }, - "required": [ - "os" - ] - }, - "then": { - "required": [ - "javaVersion", - "webContainer" - ] - } - }, - { - "if": { - "properties": { - "os": { - "pattern": "(?i)^(docker)$" - } - }, - "required": [ - "os" - ] - }, - "then": { - "required": [ - "image" - ] - } - } - ], "definitions": { "os": { "description": "The operating system for app service", diff --git a/azure-webapp-maven-plugin/src/main/java/com/microsoft/azure/maven/webapp/DeployMojo.java b/azure-webapp-maven-plugin/src/main/java/com/microsoft/azure/maven/webapp/DeployMojo.java index b93874bd87..7d34fc11f1 100644 --- a/azure-webapp-maven-plugin/src/main/java/com/microsoft/azure/maven/webapp/DeployMojo.java +++ b/azure-webapp-maven-plugin/src/main/java/com/microsoft/azure/maven/webapp/DeployMojo.java @@ -8,15 +8,27 @@ import com.microsoft.azure.maven.model.DeploymentResource; import com.microsoft.azure.maven.webapp.configuration.DeploymentSlotConfig; import com.microsoft.azure.maven.webapp.task.DeployExternalResourcesTask; +import com.microsoft.azure.toolkit.lib.Azure; +import com.microsoft.azure.toolkit.lib.appservice.config.AppServiceConfig; +import com.microsoft.azure.toolkit.lib.appservice.config.RuntimeConfig; +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.PricingTier; import com.microsoft.azure.toolkit.lib.appservice.model.WebAppArtifact; +import com.microsoft.azure.toolkit.lib.appservice.model.WebContainer; import com.microsoft.azure.toolkit.lib.appservice.service.IWebApp; import com.microsoft.azure.toolkit.lib.appservice.service.IWebAppBase; import com.microsoft.azure.toolkit.lib.appservice.service.IWebAppDeploymentSlot; import com.microsoft.azure.toolkit.lib.appservice.task.CreateOrUpdateWebAppTask; import com.microsoft.azure.toolkit.lib.appservice.task.DeployWebAppTask; +import com.microsoft.azure.toolkit.lib.auth.AzureAccount; import com.microsoft.azure.toolkit.lib.common.bundle.AzureString; import com.microsoft.azure.toolkit.lib.common.exception.AzureExecutionException; +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 org.apache.commons.lang3.StringUtils; +import org.apache.maven.artifact.versioning.ComparableVersion; import org.apache.maven.plugins.annotations.LifecyclePhase; import org.apache.maven.plugins.annotations.Mojo; @@ -45,7 +57,8 @@ protected void doExecute() throws AzureExecutionException { private IWebAppBase createOrUpdateResource() throws AzureExecutionException { if (!isDeployToDeploymentSlot()) { - return new CreateOrUpdateWebAppTask(getConfigParser().getAppServiceConfig()).execute(); + final AppServiceConfig appServiceConfig = getConfigParser().getAppServiceConfig(); + return new CreateOrUpdateWebAppTask(appServiceConfig, buildDefaultConfig(appServiceConfig.subscriptionId())).execute(); } else { // todo: New CreateOrUpdateDeploymentSlotTask final DeploymentSlotConfig config = getConfigParser().getDeploymentSlotConfig(); @@ -54,6 +67,27 @@ private IWebAppBase createOrUpdateResource() throws AzureExecutionException { } } + private AppServiceConfig buildDefaultConfig(String subscriptionId) { + final ComparableVersion javaVersionForProject = new ComparableVersion(System.getProperty("java.version")); + // get java version according to project java version + JavaVersion javaVersion = javaVersionForProject.compareTo(new ComparableVersion("9")) < 0 ? JavaVersion.JAVA_8 : JavaVersion.JAVA_11; + RuntimeConfig runtimeConfig = new RuntimeConfig().os(OperatingSystem.LINUX).webContainer(StringUtils.equalsIgnoreCase(this.project.getPackaging(), "jar") ? + WebContainer.JAVA_SE : (StringUtils.equalsIgnoreCase(this.project.getPackaging(), "ear") ? WebContainer.JBOSS_7 : WebContainer.TOMCAT_85)) + .javaVersion(javaVersion); + AppServiceConfig appServiceConfig = new AppServiceConfig(); + appServiceConfig.region(getRegionOrDefault(Azure.az(AzureAccount.class).listRegions(subscriptionId))); + appServiceConfig.runtime(runtimeConfig); + appServiceConfig.pricingTier(runtimeConfig.webContainer() == WebContainer.JBOSS_7 ? PricingTier.PREMIUM_P1V3 : PricingTier.PREMIUM_P1V2); + return appServiceConfig; + } + + private static Region getRegionOrDefault(List regions) { + if (regions.isEmpty()) { + throw new AzureToolkitRuntimeException("No region is available."); + } + return regions.contains(Region.US_CENTRAL) ? Region.US_CENTRAL : regions.get(0); + } + private IWebAppDeploymentSlot getDeploymentSlot(final DeploymentSlotConfig config) throws AzureExecutionException { final IWebApp webApp = az.webapp(config.getResourceGroup(), config.getAppName()); if (!webApp.exists()) { From 59270d9b7f4da54682a3271420a8aa64f535101d Mon Sep 17 00:00:00 2001 From: andxu Date: Mon, 20 Sep 2021 19:52:47 +0800 Subject: [PATCH 070/126] Build default config or get from existing app --- .../azure/maven/AbstractAppServiceMojo.java | 38 +++++++++ .../appservice/config/AppServiceConfig.java | 7 +- .../CreateOrUpdateAppServicePlanTask.java | 21 ++--- .../task/CreateOrUpdateWebAppTask.java | 85 ++++--------------- .../azure/maven/webapp/DeployMojo.java | 63 +++++++++++++- .../maven/webapp/WebAppConfiguration.java | 2 +- .../maven/webapp/parser/ConfigParser.java | 2 +- 7 files changed, 124 insertions(+), 94 deletions(-) diff --git a/azure-maven-plugin-lib/src/main/java/com/microsoft/azure/maven/AbstractAppServiceMojo.java b/azure-maven-plugin-lib/src/main/java/com/microsoft/azure/maven/AbstractAppServiceMojo.java index 01e8f1cccf..b5bebe3776 100644 --- a/azure-maven-plugin-lib/src/main/java/com/microsoft/azure/maven/AbstractAppServiceMojo.java +++ b/azure-maven-plugin-lib/src/main/java/com/microsoft/azure/maven/AbstractAppServiceMojo.java @@ -11,6 +11,8 @@ import com.microsoft.azure.maven.model.DeploymentResource; import com.microsoft.azure.toolkit.lib.Azure; import com.microsoft.azure.toolkit.lib.appservice.AzureAppService; +import com.microsoft.azure.toolkit.lib.appservice.config.AppServiceConfig; +import com.microsoft.azure.toolkit.lib.appservice.config.RuntimeConfig; import com.microsoft.azure.toolkit.lib.auth.Account; import com.microsoft.azure.toolkit.lib.auth.AzureAccount; import com.microsoft.azure.toolkit.lib.auth.exception.AzureLoginException; @@ -21,6 +23,7 @@ import com.microsoft.azure.toolkit.lib.common.utils.TextUtils; import com.microsoft.azure.toolkit.lib.legacy.appservice.DeploymentSlotSetting; import com.microsoft.azure.toolkit.lib.legacy.appservice.DeploymentType; +import org.apache.commons.lang3.ObjectUtils; import org.apache.maven.plugins.annotations.Parameter; import java.io.IOException; @@ -210,4 +213,39 @@ protected void printCurrentSubscription(AzureAppService appServiceClient) { Log.info(String.format(SUBSCRIPTION_TEMPLATE, TextUtils.cyan(subscription.getName()), TextUtils.cyan(subscription.getId()))); } } + + protected void mergeConfig(AppServiceConfig config1, AppServiceConfig config2) { + if (config1.region() == null) { + config1.region(config2.region()); + } + + if (config1.servicePlanResourceGroup() == null) { + config1.servicePlanResourceGroup(config2.servicePlanResourceGroup()); + } + + if (config1.servicePlanName() == null) { + config1.servicePlanName(config2.servicePlanName()); + } + + if (config1.runtime() == null) { + config1.runtime(config2.runtime()); + } else { + mergeRuntime(config1.runtime(), config2.runtime()); + } + + if (config1.pricingTier() == null) { + config1.pricingTier(config2.pricingTier()); + } + } + + private void mergeRuntime(RuntimeConfig runtime1, RuntimeConfig runtime2) { + runtime1.os(ObjectUtils.firstNonNull(runtime1.os(), runtime2.os())); + runtime1.image(ObjectUtils.firstNonNull(runtime1.image(), runtime2.image())); + runtime1.username(ObjectUtils.firstNonNull(runtime1.username(), runtime2.username())); + runtime1.password(ObjectUtils.firstNonNull(runtime1.password(), runtime2.password())); + runtime1.startUpCommand(ObjectUtils.firstNonNull(runtime1.startUpCommand(), runtime2.startUpCommand())); + runtime1.registryUrl(ObjectUtils.firstNonNull(runtime1.registryUrl(), runtime2.registryUrl())); + runtime1.javaVersion(ObjectUtils.firstNonNull(runtime1.javaVersion(), runtime2.javaVersion())); + runtime1.webContainer(ObjectUtils.firstNonNull(runtime1.webContainer(), runtime2.webContainer())); + } } diff --git a/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/config/AppServiceConfig.java b/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/config/AppServiceConfig.java index 06e9551ce4..a85a115337 100644 --- a/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/config/AppServiceConfig.java +++ b/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/config/AppServiceConfig.java @@ -10,7 +10,6 @@ import lombok.Getter; import lombok.Setter; import lombok.experimental.Accessors; -import org.apache.commons.lang3.StringUtils; import java.util.Map; @@ -44,10 +43,10 @@ public class AppServiceConfig { public AppServicePlanConfig getServicePlanConfig() { return new AppServicePlanConfig() .subscriptionId(subscriptionId()) - .servicePlanResourceGroup(StringUtils.firstNonBlank(servicePlanResourceGroup(), resourceGroup)) - .servicePlanName(StringUtils.firstNonBlank(servicePlanName(), String.format("asp-%s", appName))) + .servicePlanResourceGroup(servicePlanResourceGroup()) + .servicePlanName(servicePlanName()) .region(region()) - .os(runtime() == null ? null : runtime().os()) + .os(runtime().os()) .pricingTier(pricingTier()); } } diff --git a/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/task/CreateOrUpdateAppServicePlanTask.java b/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/task/CreateOrUpdateAppServicePlanTask.java index cae81fbd51..31ec99b073 100644 --- a/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/task/CreateOrUpdateAppServicePlanTask.java +++ b/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/task/CreateOrUpdateAppServicePlanTask.java @@ -9,7 +9,6 @@ import com.microsoft.azure.toolkit.lib.appservice.AzureAppService; import com.microsoft.azure.toolkit.lib.appservice.config.AppServicePlanConfig; import com.microsoft.azure.toolkit.lib.appservice.service.IAppServicePlan; -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.operation.AzureOperation; @@ -18,10 +17,7 @@ import com.microsoft.azure.toolkit.lib.common.validator.SchemaValidator; import com.microsoft.azure.toolkit.lib.resource.task.CreateResourceGroupTask; import lombok.AllArgsConstructor; -import org.apache.commons.lang3.ObjectUtils; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; import java.util.Objects; @AllArgsConstructor @@ -29,10 +25,7 @@ public class CreateOrUpdateAppServicePlanTask extends AzureTask private static final String CREATE_APP_SERVICE_PLAN = "Creating app service plan %s..."; private static final String CREATE_APP_SERVICE_PLAN_DONE = "Successfully created app service plan %s."; private static final String CREATE_NEW_APP_SERVICE_PLAN = "createNewAppServicePlan"; - @Nonnull private AppServicePlanConfig config; - @Nullable - private AppServicePlanConfig defaultConfig; @AzureOperation(name = "appservice|plan.create_update", params = {"this.config.servicePlanName()"}, type = AzureOperation.Type.SERVICE) public IAppServicePlan execute() { @@ -43,17 +36,13 @@ public IAppServicePlan execute() { if (!appServicePlan.exists()) { AzureMessager.getMessager().info(String.format(CREATE_APP_SERVICE_PLAN, servicePlanName)); AzureTelemetry.getActionContext().setProperty(CREATE_NEW_APP_SERVICE_PLAN, String.valueOf(true)); - if (this.defaultConfig == null) { - throw new AzureToolkitRuntimeException("Cannot create service without default config."); - } - final Region regionOrDefault = ObjectUtils.firstNonNull(this.config.region(), this.defaultConfig.region()); - new CreateResourceGroupTask(this.config.subscriptionId(), config.servicePlanResourceGroup(), regionOrDefault).execute(); + new CreateResourceGroupTask(this.config.subscriptionId(), config.servicePlanResourceGroup(), config.region()).execute(); appServicePlan.create() .withName(servicePlanName) .withResourceGroup(config.servicePlanResourceGroup()) - .withPricingTier(ObjectUtils.firstNonNull(config.pricingTier(), defaultConfig.pricingTier())) - .withRegion(regionOrDefault) - .withOperatingSystem(ObjectUtils.firstNonNull(config.os(), defaultConfig.os())) + .withPricingTier(config.pricingTier()) + .withRegion(config.region()) + .withOperatingSystem(config.os()) .commit(); AzureMessager.getMessager().info(String.format(CREATE_APP_SERVICE_PLAN_DONE, appServicePlan.name())); } else { @@ -61,7 +50,7 @@ public IAppServicePlan execute() { AzureMessager.getMessager().warning(String.format("Skip region update for existing service plan '%s' since it is not allowed.", appServicePlan.name())); } - if (config.pricingTier() != null) { + if (config.pricingTier() != null && !Objects.equals(config.pricingTier(), appServicePlan.entity().getPricingTier())) { // apply pricing tier to service plan appServicePlan.update().withPricingTier(config.pricingTier()).commit(); } diff --git a/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/task/CreateOrUpdateWebAppTask.java b/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/task/CreateOrUpdateWebAppTask.java index 7c955a5f9d..ae6dbc6d4f 100644 --- a/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/task/CreateOrUpdateWebAppTask.java +++ b/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/task/CreateOrUpdateWebAppTask.java @@ -13,17 +13,16 @@ import com.microsoft.azure.toolkit.lib.appservice.model.DockerConfiguration; 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.PricingTier; import com.microsoft.azure.toolkit.lib.appservice.model.Runtime; import com.microsoft.azure.toolkit.lib.appservice.model.WebContainer; import com.microsoft.azure.toolkit.lib.appservice.service.IAppServicePlan; +import com.microsoft.azure.toolkit.lib.appservice.service.IAppServiceUpdater; import com.microsoft.azure.toolkit.lib.appservice.service.IWebApp; import com.microsoft.azure.toolkit.lib.common.bundle.AzureString; import com.microsoft.azure.toolkit.lib.common.entity.CheckNameAvailabilityResultEntity; 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.model.ResourceGroup; import com.microsoft.azure.toolkit.lib.common.operation.AzureOperation; import com.microsoft.azure.toolkit.lib.common.operation.AzureOperation.Type; import com.microsoft.azure.toolkit.lib.common.task.AzureTask; @@ -46,12 +45,10 @@ public class CreateOrUpdateWebAppTask extends AzureTask { private static final String UPDATE_WEBAPP_DONE = "Successfully updated Web App %s."; private final AppServiceConfig config; - private final AppServiceConfig defaultConfig; private final List> subTasks; - public CreateOrUpdateWebAppTask(AppServiceConfig config, AppServiceConfig defaultConfig) { + public CreateOrUpdateWebAppTask(AppServiceConfig config) { this.config = config; - this.defaultConfig = defaultConfig; this.subTasks = this.initTasks(); } @@ -82,22 +79,18 @@ private IWebApp create() { AzureMessager.getMessager().info(String.format(CREATE_WEBAPP, config.appName())); // handle default region for resource group - final Region region = ObjectUtils.firstNonNull(this.config.region(), this.defaultConfig.region()); - final ResourceGroup resourceGroup = new CreateResourceGroupTask(this.config.subscriptionId(), this.config.resourceGroup(), region).execute(); - + final Region region = this.config.region(); + new CreateResourceGroupTask(this.config.subscriptionId(), this.config.resourceGroup(), region).execute(); final AzureAppService az = Azure.az(AzureAppService.class).subscription(config.subscriptionId()); final IWebApp webapp = az.webapp(config.resourceGroup(), config.appName()); final AppServicePlanConfig servicePlanConfig = config.getServicePlanConfig(); - final RuntimeConfig runtimeConfigOrDefault = getRuntimeConfigOrDefault(config.runtime(), defaultConfig.runtime()); - final Runtime runtime = getRuntime(runtimeConfigOrDefault); - final IAppServicePlan appServicePlan = new CreateOrUpdateAppServicePlanTask(servicePlanConfig, - buildDefaultAppServicePlanConfig(Region.fromName(resourceGroup.getRegion()), runtime)).execute(); + final IAppServicePlan appServicePlan = new CreateOrUpdateAppServicePlanTask(servicePlanConfig).execute(); final IWebApp result = webapp.create().withName(config.appName()) .withResourceGroup(config.resourceGroup()) .withPlan(appServicePlan.id()) - .withRuntime(runtime) - .withDockerConfiguration(getDockerConfiguration(runtimeConfigOrDefault)) + .withRuntime(getRuntime(config.runtime())) + .withDockerConfiguration(getDockerConfiguration(config.runtime())) .withAppSettings(config.appSettings()) .commit(); AzureMessager.getMessager().info(String.format(CREATE_WEB_APP_DONE, result.name())); @@ -110,21 +103,16 @@ private IWebApp update(final IWebApp webApp) { final IAppServicePlan currentPlan = webApp.plan(); final AppServicePlanConfig servicePlanConfig = config.getServicePlanConfig(); - if (StringUtils.isAllBlank(config.servicePlanResourceGroup(), config.servicePlanName())) { - // initialize service plan creation from exising webapp if user doesn't specify it in config - servicePlanConfig.servicePlanResourceGroup(currentPlan.resourceGroup()); - servicePlanConfig.servicePlanName(currentPlan.name()); - } else if (StringUtils.equalsIgnoreCase(config.servicePlanName(), currentPlan.name()) && StringUtils.isBlank(config.servicePlanResourceGroup())) { - servicePlanConfig.servicePlanResourceGroup(currentPlan.resourceGroup()); - } else if (StringUtils.equalsIgnoreCase(servicePlanConfig.servicePlanResourceGroup(), currentPlan.resourceGroup()) && - StringUtils.isBlank(config.servicePlanName())) { - servicePlanConfig.servicePlanName(currentPlan.name()); + final Runtime runtime = getRuntime(config.runtime()); + final IAppServicePlan appServicePlan = new CreateOrUpdateAppServicePlanTask(servicePlanConfig).execute(); + final IAppServiceUpdater draft = webApp.update(); + if (!StringUtils.equalsIgnoreCase(config.servicePlanName(), currentPlan.name())) { + draft.withPlan(appServicePlan.id()); + } + if (!webApp.getRuntime().equals(runtime)) { + draft.withRuntime(runtime); } - final Runtime runtime = getRuntime(config.runtime(), webApp.entity().getRuntime()); - final IAppServicePlan appServicePlan = new CreateOrUpdateAppServicePlanTask(servicePlanConfig, - buildDefaultAppServicePlanConfig(webApp.entity().getRegion(), ObjectUtils.firstNonNull(runtime, webApp.entity().getRuntime()))).execute(); - final IWebApp result = webApp.update().withPlan(appServicePlan.id()) - .withRuntime(runtime) + final IWebApp result = draft .withDockerConfiguration(getDockerConfiguration(config.runtime())) .withAppSettings(ObjectUtils.firstNonNull(config.appSettings(), new HashMap<>())) .commit(); @@ -132,30 +120,6 @@ private IWebApp update(final IWebApp webApp) { return result; } - private Runtime getRuntime(RuntimeConfig runtime, Runtime remote) { - if (runtime == null) { - return null; - } - if (runtime.os() == null) { - runtime.os(remote.getOperatingSystem()); - } - if (OperatingSystem.DOCKER == runtime.os()) { - return Runtime.getRuntime(OperatingSystem.DOCKER, WebContainer.JAVA_OFF, JavaVersion.OFF); - } else { - return Runtime.getRuntime(runtime.os(), - ObjectUtils.firstNonNull(runtime.webContainer(), remote.getWebContainer()), - ObjectUtils.firstNonNull(runtime.javaVersion(), remote.getJavaVersion())); - } - } - - private AppServicePlanConfig buildDefaultAppServicePlanConfig(Region region, Runtime runtime) { - final AppServicePlanConfig defaultServicePlanConfig = new AppServicePlanConfig(); - defaultServicePlanConfig.region(region); - defaultServicePlanConfig.os(OperatingSystem.LINUX); - defaultServicePlanConfig.pricingTier(runtime.getWebContainer().equals(WebContainer.JBOSS_7) ? PricingTier.PREMIUM_P1V3 : PricingTier.PREMIUM_P1V2); - return defaultServicePlanConfig; - } - private DockerConfiguration getDockerConfiguration(RuntimeConfig runtime) { if (runtime != null && OperatingSystem.DOCKER == runtime.os()) { return DockerConfiguration.builder() @@ -170,23 +134,6 @@ private DockerConfiguration getDockerConfiguration(RuntimeConfig runtime) { } - private RuntimeConfig getRuntimeConfigOrDefault(RuntimeConfig runtime, RuntimeConfig defaultRuntime) { - if (runtime == null) { - return defaultRuntime; - } - - final RuntimeConfig result = new RuntimeConfig(); - result.os(ObjectUtils.firstNonNull(runtime.os(), defaultRuntime.os())); - result.image(ObjectUtils.firstNonNull(runtime.image(), defaultRuntime.image())); - result.username(ObjectUtils.firstNonNull(runtime.username(), defaultRuntime.username())); - result.password(ObjectUtils.firstNonNull(runtime.password(), defaultRuntime.password())); - result.startUpCommand(ObjectUtils.firstNonNull(runtime.startUpCommand(), defaultRuntime.startUpCommand())); - result.registryUrl(ObjectUtils.firstNonNull(runtime.registryUrl(), defaultRuntime.registryUrl())); - result.javaVersion(ObjectUtils.firstNonNull(runtime.javaVersion(), defaultRuntime.javaVersion())); - result.webContainer(ObjectUtils.firstNonNull(runtime.webContainer(), defaultRuntime.webContainer())); - return result; - } - private Runtime getRuntime(RuntimeConfig runtime) { if (runtime != null && OperatingSystem.DOCKER != runtime.os()) { return Runtime.getRuntime(runtime.os(), diff --git a/azure-webapp-maven-plugin/src/main/java/com/microsoft/azure/maven/webapp/DeployMojo.java b/azure-webapp-maven-plugin/src/main/java/com/microsoft/azure/maven/webapp/DeployMojo.java index 7d34fc11f1..4d86063107 100644 --- a/azure-webapp-maven-plugin/src/main/java/com/microsoft/azure/maven/webapp/DeployMojo.java +++ b/azure-webapp-maven-plugin/src/main/java/com/microsoft/azure/maven/webapp/DeployMojo.java @@ -9,6 +9,7 @@ import com.microsoft.azure.maven.webapp.configuration.DeploymentSlotConfig; import com.microsoft.azure.maven.webapp.task.DeployExternalResourcesTask; import com.microsoft.azure.toolkit.lib.Azure; +import com.microsoft.azure.toolkit.lib.appservice.AzureAppService; import com.microsoft.azure.toolkit.lib.appservice.config.AppServiceConfig; import com.microsoft.azure.toolkit.lib.appservice.config.RuntimeConfig; import com.microsoft.azure.toolkit.lib.appservice.model.JavaVersion; @@ -16,6 +17,7 @@ import com.microsoft.azure.toolkit.lib.appservice.model.PricingTier; import com.microsoft.azure.toolkit.lib.appservice.model.WebAppArtifact; import com.microsoft.azure.toolkit.lib.appservice.model.WebContainer; +import com.microsoft.azure.toolkit.lib.appservice.service.IAppServicePlan; import com.microsoft.azure.toolkit.lib.appservice.service.IWebApp; import com.microsoft.azure.toolkit.lib.appservice.service.IWebAppBase; import com.microsoft.azure.toolkit.lib.appservice.service.IWebAppDeploymentSlot; @@ -27,12 +29,15 @@ 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.utils.Utils; +import com.microsoft.azure.toolkit.lib.legacy.appservice.AppServiceUtils; import org.apache.commons.lang3.StringUtils; import org.apache.maven.artifact.versioning.ComparableVersion; import org.apache.maven.plugins.annotations.LifecyclePhase; import org.apache.maven.plugins.annotations.Mojo; import java.util.List; +import java.util.Map; /** * Deploy an Azure Web App, either Windows-based or Linux-based. @@ -44,6 +49,9 @@ public class DeployMojo extends AbstractWebAppMojo { private static final String CREATE_DEPLOYMENT_SLOT = "Creating deployment slot %s in web app %s"; private static final String CREATE_DEPLOYMENT_SLOT_DONE = "Successfully created the Deployment Slot."; private static final String CREATE_NEW_DEPLOYMENT_SLOT = "createNewDeploymentSlot"; + private static final String SETTING_DOCKER_IMAGE = "DOCKER_CUSTOM_IMAGE_NAME"; + private static final String SETTING_REGISTRY_SERVER = "DOCKER_REGISTRY_SERVER_URL"; + private static final String SETTING_REGISTRY_USERNAME = "DOCKER_REGISTRY_SERVER_USERNAME"; @Override protected void doExecute() throws AzureExecutionException { @@ -58,7 +66,14 @@ protected void doExecute() throws AzureExecutionException { private IWebAppBase createOrUpdateResource() throws AzureExecutionException { if (!isDeployToDeploymentSlot()) { final AppServiceConfig appServiceConfig = getConfigParser().getAppServiceConfig(); - return new CreateOrUpdateWebAppTask(appServiceConfig, buildDefaultConfig(appServiceConfig.subscriptionId())).execute(); + IWebApp app = Azure.az(AzureAppService.class).webapp(appServiceConfig.resourceGroup(), appServiceConfig.appName()); + AppServiceConfig defaultConfig = app.exists() ? getAppServiceConfigFromExisting(app) : buildDefaultConfig(appServiceConfig.subscriptionId(), + appServiceConfig.resourceGroup(), appServiceConfig.appName()); + mergeConfig(appServiceConfig, defaultConfig); + if (appServiceConfig.pricingTier() == null) { + appServiceConfig.pricingTier(appServiceConfig.runtime().webContainer() == WebContainer.JBOSS_7 ? PricingTier.PREMIUM_P1V3 : PricingTier.PREMIUM_P1V2); + } + return new CreateOrUpdateWebAppTask(appServiceConfig).execute(); } else { // todo: New CreateOrUpdateDeploymentSlotTask final DeploymentSlotConfig config = getConfigParser().getDeploymentSlotConfig(); @@ -67,7 +82,45 @@ private IWebAppBase createOrUpdateResource() throws AzureExecutionException { } } - private AppServiceConfig buildDefaultConfig(String subscriptionId) { + static AppServiceConfig getAppServiceConfigFromExisting(IWebApp webapp) { + IAppServicePlan servicePlan = webapp.plan(); + AppServiceConfig config = new AppServiceConfig(); + config.appName(webapp.name()); + + config.resourceGroup(webapp.entity().getResourceGroup()); + config.subscriptionId(Utils.getSubscriptionId(webapp.id())); + config.region(webapp.entity().getRegion()); + config.pricingTier(servicePlan.entity().getPricingTier()); + RuntimeConfig runtimeConfig = new RuntimeConfig(); + if (AppServiceUtils.isDockerAppService(webapp)) { + runtimeConfig.os(OperatingSystem.DOCKER); + final Map settings = webapp.entity().getAppSettings(); + + final String imageSetting = settings.get(SETTING_DOCKER_IMAGE); + if (StringUtils.isNotBlank(imageSetting)) { + runtimeConfig.image(imageSetting); + } else { + runtimeConfig.image(webapp.entity().getDockerImageName()); + } + final String registryServerSetting = settings.get(SETTING_REGISTRY_SERVER); + if (StringUtils.isNotBlank(registryServerSetting)) { + runtimeConfig.registryUrl(registryServerSetting); + } + } else { + runtimeConfig.os(webapp.getRuntime().getOperatingSystem()); + runtimeConfig.webContainer(webapp.getRuntime().getWebContainer()); + runtimeConfig.javaVersion(webapp.getRuntime().getJavaVersion()); + } + config.runtime(runtimeConfig); + if (servicePlan.entity() != null) { + config.pricingTier(servicePlan.entity().getPricingTier()); + config.servicePlanName(servicePlan.name()); + config.servicePlanResourceGroup(servicePlan.entity().getResourceGroup()); + } + return config; + } + + private AppServiceConfig buildDefaultConfig(String subscriptionId, String resourceGroup, String appName) { final ComparableVersion javaVersionForProject = new ComparableVersion(System.getProperty("java.version")); // get java version according to project java version JavaVersion javaVersion = javaVersionForProject.compareTo(new ComparableVersion("9")) < 0 ? JavaVersion.JAVA_8 : JavaVersion.JAVA_11; @@ -75,9 +128,13 @@ private AppServiceConfig buildDefaultConfig(String subscriptionId) { WebContainer.JAVA_SE : (StringUtils.equalsIgnoreCase(this.project.getPackaging(), "ear") ? WebContainer.JBOSS_7 : WebContainer.TOMCAT_85)) .javaVersion(javaVersion); AppServiceConfig appServiceConfig = new AppServiceConfig(); + //TODO: use listSupportedRegions appServiceConfig.region(getRegionOrDefault(Azure.az(AzureAccount.class).listRegions(subscriptionId))); appServiceConfig.runtime(runtimeConfig); - appServiceConfig.pricingTier(runtimeConfig.webContainer() == WebContainer.JBOSS_7 ? PricingTier.PREMIUM_P1V3 : PricingTier.PREMIUM_P1V2); + appServiceConfig.resourceGroup(resourceGroup); + appServiceConfig.appName(appName); + appServiceConfig.servicePlanResourceGroup(resourceGroup); + appServiceConfig.servicePlanName(String.format("asp-%s", appName)); return appServiceConfig; } diff --git a/azure-webapp-maven-plugin/src/main/java/com/microsoft/azure/maven/webapp/WebAppConfiguration.java b/azure-webapp-maven-plugin/src/main/java/com/microsoft/azure/maven/webapp/WebAppConfiguration.java index 26270d2833..7c30333126 100644 --- a/azure-webapp-maven-plugin/src/main/java/com/microsoft/azure/maven/webapp/WebAppConfiguration.java +++ b/azure-webapp-maven-plugin/src/main/java/com/microsoft/azure/maven/webapp/WebAppConfiguration.java @@ -29,7 +29,7 @@ @SuperBuilder(toBuilder = true) public class WebAppConfiguration { public static final PricingTier DEFAULT_JBOSS_PRICING_TIER = PricingTier.PREMIUM_P1V3; - public static final Region DEFAULT_REGION = Region.EUROPE_WEST; + public static final Region DEFAULT_REGION = Region.US_CENTRAL; public static final PricingTier DEFAULT_PRICINGTIER = PricingTier.PREMIUM_P1V2; public static final JavaVersion DEFAULT_JAVA_VERSION = JavaVersion.JAVA_8; public static final WebContainer DEFAULT_CONTAINER = WebContainer.TOMCAT_85; diff --git a/azure-webapp-maven-plugin/src/main/java/com/microsoft/azure/maven/webapp/parser/ConfigParser.java b/azure-webapp-maven-plugin/src/main/java/com/microsoft/azure/maven/webapp/parser/ConfigParser.java index 2941818614..01b47131bd 100644 --- a/azure-webapp-maven-plugin/src/main/java/com/microsoft/azure/maven/webapp/parser/ConfigParser.java +++ b/azure-webapp-maven-plugin/src/main/java/com/microsoft/azure/maven/webapp/parser/ConfigParser.java @@ -99,7 +99,7 @@ public WebAppConfiguration getWebAppConfiguration() { return builder.appName(getAppName()) .resourceGroup(getResourceGroup()) .region(getRegion()) - .pricingTier(getPricingTier().getSize()) + .pricingTier(Optional.ofNullable(getPricingTier()).map(PricingTier::getSize).orElse(null)) .servicePlanName(mojo.getAppServicePlanName()) .servicePlanResourceGroup(mojo.getAppServicePlanResourceGroup()) .deploymentSlotSetting(mojo.getDeploymentSlotSetting()) From 9a4962a0ce6b6d97aca83abcf0a8803378cdccca Mon Sep 17 00:00:00 2001 From: andxu Date: Mon, 20 Sep 2021 20:27:15 +0800 Subject: [PATCH 071/126] extract common logic to base class --- .../CreateOrUpdateAppServicePlanTask.java | 1 + .../appservice/CreateAppServicePlan.json | 10 ++++ .../maven/webapp/AbstractWebAppMojo.java | 49 +++++++++++++++-- .../azure/maven/webapp/ConfigMojo.java | 53 ++++++------------- .../azure/maven/webapp/DeployMojo.java | 45 ---------------- 5 files changed, 73 insertions(+), 85 deletions(-) create mode 100644 azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/resources/schema/appservice/CreateAppServicePlan.json diff --git a/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/task/CreateOrUpdateAppServicePlanTask.java b/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/task/CreateOrUpdateAppServicePlanTask.java index 31ec99b073..ac97851494 100644 --- a/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/task/CreateOrUpdateAppServicePlanTask.java +++ b/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/task/CreateOrUpdateAppServicePlanTask.java @@ -34,6 +34,7 @@ public IAppServicePlan execute() { final IAppServicePlan appServicePlan = az.appServicePlan(config.servicePlanResourceGroup(), config.servicePlanName()); final String servicePlanName = config.servicePlanName(); if (!appServicePlan.exists()) { + SchemaValidator.getInstance().validateAndThrow("appservice/CreateAppServicePlan", config); AzureMessager.getMessager().info(String.format(CREATE_APP_SERVICE_PLAN, servicePlanName)); AzureTelemetry.getActionContext().setProperty(CREATE_NEW_APP_SERVICE_PLAN, String.valueOf(true)); new CreateResourceGroupTask(this.config.subscriptionId(), config.servicePlanResourceGroup(), config.region()).execute(); diff --git a/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/resources/schema/appservice/CreateAppServicePlan.json b/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/resources/schema/appservice/CreateAppServicePlan.json new file mode 100644 index 0000000000..9671330f7f --- /dev/null +++ b/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/resources/schema/appservice/CreateAppServicePlan.json @@ -0,0 +1,10 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "App Service Plan - Update", + "description": "Schema for AppServicePlanConfig when update existing service plan", + "allOf": [ + { + "$ref": "classpath:///schema/appservice/AppServicePlan.json" + } + ] +} diff --git a/azure-webapp-maven-plugin/src/main/java/com/microsoft/azure/maven/webapp/AbstractWebAppMojo.java b/azure-webapp-maven-plugin/src/main/java/com/microsoft/azure/maven/webapp/AbstractWebAppMojo.java index 0e994c5878..8637bf9f9d 100644 --- a/azure-webapp-maven-plugin/src/main/java/com/microsoft/azure/maven/webapp/AbstractWebAppMojo.java +++ b/azure-webapp-maven-plugin/src/main/java/com/microsoft/azure/maven/webapp/AbstractWebAppMojo.java @@ -13,9 +13,14 @@ import com.microsoft.azure.maven.webapp.configuration.MavenRuntimeConfig; import com.microsoft.azure.maven.webapp.parser.ConfigParser; import com.microsoft.azure.toolkit.lib.appservice.AzureAppService; +import com.microsoft.azure.toolkit.lib.appservice.config.AppServiceConfig; +import com.microsoft.azure.toolkit.lib.appservice.config.RuntimeConfig; import com.microsoft.azure.toolkit.lib.appservice.model.OperatingSystem; +import com.microsoft.azure.toolkit.lib.appservice.service.IAppServicePlan; +import com.microsoft.azure.toolkit.lib.appservice.service.IWebApp; import com.microsoft.azure.toolkit.lib.common.exception.AzureExecutionException; import com.microsoft.azure.toolkit.lib.common.exception.AzureToolkitRuntimeException; +import com.microsoft.azure.toolkit.lib.common.utils.Utils; import com.microsoft.azure.toolkit.lib.common.validator.SchemaValidator; import com.microsoft.azure.toolkit.lib.common.validator.ValidationMessage; import com.microsoft.azure.toolkit.lib.legacy.appservice.AppServiceUtils; @@ -44,11 +49,11 @@ public abstract class AbstractWebAppMojo extends AbstractAppServiceMojo { public static final String DOCKER_IMAGE_TYPE_KEY = "dockerImageType"; public static final String DEPLOYMENT_TYPE_KEY = "deploymentType"; public static final String OS_KEY = "os"; - public static final String INVALID_CONFIG_KEY = "invalidConfiguration"; public static final String SCHEMA_VERSION_KEY = "schemaVersion"; public static final String DEPLOY_TO_SLOT_KEY = "isDeployToSlot"; - private static final String INVALID_PARAMETER_ERROR_MESSAGE = "Invalid values found in configuration, please correct the value with messages below:"; - + public static final String INVALID_PARAMETER_ERROR_MESSAGE = "Invalid values found in configuration, please correct the value with messages below:"; + public static final String SETTING_DOCKER_IMAGE = "DOCKER_CUSTOM_IMAGE_NAME"; + public static final String SETTING_REGISTRY_SERVER = "DOCKER_REGISTRY_SERVER_URL"; //region Properties /** @@ -239,6 +244,44 @@ protected void validateConfiguration(Consumer validationMessa } } + protected AppServiceConfig getAppServiceConfigFromExisting(IWebApp webapp) { + IAppServicePlan servicePlan = webapp.plan(); + AppServiceConfig config = new AppServiceConfig(); + config.appName(webapp.name()); + + config.resourceGroup(webapp.entity().getResourceGroup()); + config.subscriptionId(Utils.getSubscriptionId(webapp.id())); + config.region(webapp.entity().getRegion()); + config.pricingTier(servicePlan.entity().getPricingTier()); + RuntimeConfig runtimeConfig = new RuntimeConfig(); + if (AppServiceUtils.isDockerAppService(webapp)) { + runtimeConfig.os(OperatingSystem.DOCKER); + final Map settings = webapp.entity().getAppSettings(); + + final String imageSetting = settings.get(SETTING_DOCKER_IMAGE); + if (StringUtils.isNotBlank(imageSetting)) { + runtimeConfig.image(imageSetting); + } else { + runtimeConfig.image(webapp.entity().getDockerImageName()); + } + final String registryServerSetting = settings.get(SETTING_REGISTRY_SERVER); + if (StringUtils.isNotBlank(registryServerSetting)) { + runtimeConfig.registryUrl(registryServerSetting); + } + } else { + runtimeConfig.os(webapp.getRuntime().getOperatingSystem()); + runtimeConfig.webContainer(webapp.getRuntime().getWebContainer()); + runtimeConfig.javaVersion(webapp.getRuntime().getJavaVersion()); + } + config.runtime(runtimeConfig); + if (servicePlan.entity() != null) { + config.pricingTier(servicePlan.entity().getPricingTier()); + config.servicePlanName(servicePlan.name()); + config.servicePlanResourceGroup(servicePlan.entity().getResourceGroup()); + } + return config; + } + @Override public String getSubscriptionId() { return appServiceClient == null ? this.subscriptionId : appServiceClient.getDefaultSubscription().getId(); diff --git a/azure-webapp-maven-plugin/src/main/java/com/microsoft/azure/maven/webapp/ConfigMojo.java b/azure-webapp-maven-plugin/src/main/java/com/microsoft/azure/maven/webapp/ConfigMojo.java index 6a49a97a54..f0dbbe5f3d 100644 --- a/azure-webapp-maven-plugin/src/main/java/com/microsoft/azure/maven/webapp/ConfigMojo.java +++ b/azure-webapp-maven-plugin/src/main/java/com/microsoft/azure/maven/webapp/ConfigMojo.java @@ -16,12 +16,12 @@ import com.microsoft.azure.maven.webapp.models.WebAppOption; import com.microsoft.azure.toolkit.lib.Azure; import com.microsoft.azure.toolkit.lib.appservice.AzureAppService; +import com.microsoft.azure.toolkit.lib.appservice.config.AppServiceConfig; 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.PricingTier; import com.microsoft.azure.toolkit.lib.appservice.model.Runtime; import com.microsoft.azure.toolkit.lib.appservice.model.WebContainer; -import com.microsoft.azure.toolkit.lib.appservice.service.IAppServicePlan; import com.microsoft.azure.toolkit.lib.appservice.service.IWebApp; import com.microsoft.azure.toolkit.lib.auth.exception.AzureToolkitAuthenticationException; import com.microsoft.azure.toolkit.lib.common.exception.AzureExecutionException; @@ -51,7 +51,6 @@ import java.util.List; import java.util.Map; import java.util.Objects; -import java.util.Optional; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -83,8 +82,6 @@ public class ConfigMojo extends AbstractWebAppMojo { private static final String NO_JAVA_WEB_APPS = "There are no Java Web Apps in current subscription, please follow the following steps to create a new one."; private static final String LONG_LOADING_HINT = "It may take a few minutes to load all Java Web Apps, please be patient."; private static final String[] configTypes = {"Application", "Runtime", "DeploymentSlot"}; - private static final String SETTING_DOCKER_IMAGE = "DOCKER_CUSTOM_IMAGE_NAME"; - private static final String SETTING_REGISTRY_SERVER = "DOCKER_REGISTRY_SERVER_URL"; private static final String SETTING_REGISTRY_USERNAME = "DOCKER_REGISTRY_SERVER_USERNAME"; private static final String SERVER_ID_TEMPLATE = "Please add a server in Maven settings.xml related to username: %s and put the serverId here"; @@ -500,17 +497,12 @@ private WebAppConfiguration chooseExistingWebappForConfiguration() } final IWebApp webapp = az.webapp(selectedApp.getId()); - final String serverPlanId = selectedApp.getServicePlanId(); - IAppServicePlan servicePlan = null; - if (StringUtils.isNotBlank(serverPlanId)) { - servicePlan = az.appServicePlan(serverPlanId); - } final WebAppConfiguration.WebAppConfigurationBuilder builder = WebAppConfiguration.builder(); if (!AppServiceUtils.isDockerAppService(webapp)) { builder.resources(Deployment.getDefaultDeploymentConfiguration(getProject().getPackaging()).getResources()); } - return getConfigurationFromExisting(webapp, servicePlan, builder); + return getConfigurationFromExisting(webapp, builder); } catch (AzureToolkitAuthenticationException ex) { // if is valid for config goal to have error in authentication getLog().warn(String.format("Cannot authenticate due to error: %s, select existing webapp is skipped.", ex.getMessage())); @@ -533,43 +525,30 @@ private static WebAppOption selectAzureWebApp(TextIO textIO, List .read(String.format("%s Web Apps in subscription %s:", webAppType, TextUtils.blue(targetSubscription.getName()))); } - private static WebAppConfiguration getConfigurationFromExisting(IWebApp webapp, IAppServicePlan servicePlan, + private WebAppConfiguration getConfigurationFromExisting(IWebApp webapp, WebAppConfiguration.WebAppConfigurationBuilder builder) { + final AppServiceConfig appServiceConfig = getAppServiceConfigFromExisting(webapp); // common configuration - builder.appName(webapp.name()) - .resourceGroup(webapp.entity().getResourceGroup()) - .subscriptionId(Utils.getSubscriptionId(webapp.id())) - .region(webapp.entity().getRegion()); - + builder.appName(appServiceConfig.appName()) + .resourceGroup(appServiceConfig.resourceGroup()) + .subscriptionId(appServiceConfig.subscriptionId()) + .region(appServiceConfig.region()); + builder.os(appServiceConfig.runtime().os()); if (AppServiceUtils.isDockerAppService(webapp)) { - builder.os(OperatingSystem.DOCKER); final Map settings = webapp.entity().getAppSettings(); - - final String imageSetting = settings.get(SETTING_DOCKER_IMAGE); - if (StringUtils.isNotBlank(imageSetting)) { - builder.image(imageSetting); - } else { - builder.image(webapp.entity().getDockerImageName()); - } - final String registryServerSetting = settings.get(SETTING_REGISTRY_SERVER); - if (StringUtils.isNotBlank(registryServerSetting)) { - builder.registryUrl(registryServerSetting); - } - + builder.image(appServiceConfig.runtime().image()); + builder.registryUrl(appServiceConfig.runtime().registryUrl()); final String dockerUsernameSetting = settings.get(SETTING_REGISTRY_USERNAME); if (StringUtils.isNotBlank(dockerUsernameSetting)) { builder.serverId(String.format(SERVER_ID_TEMPLATE, dockerUsernameSetting)); } } else { - builder.os(webapp.getRuntime().getOperatingSystem()); - builder.webContainer(Objects.toString(webapp.getRuntime().getWebContainer())); - builder.javaVersion(Objects.toString(webapp.getRuntime().getJavaVersion())); - } - if (servicePlan != null && servicePlan.entity() != null) { - builder.pricingTier(Optional.ofNullable(servicePlan.entity().getPricingTier()).map(Object::toString).orElse(null)); - builder.servicePlanName(servicePlan.name()); - builder.servicePlanResourceGroup(servicePlan.entity().getResourceGroup()); + builder.webContainer(Objects.toString(appServiceConfig.runtime().webContainer())); + builder.javaVersion(Objects.toString(appServiceConfig.runtime().javaVersion())); } + builder.servicePlanName(appServiceConfig.servicePlanName()); + builder.servicePlanResourceGroup(appServiceConfig.servicePlanResourceGroup()); + builder.pricingTier(Objects.toString(appServiceConfig.pricingTier())); return builder.build(); } diff --git a/azure-webapp-maven-plugin/src/main/java/com/microsoft/azure/maven/webapp/DeployMojo.java b/azure-webapp-maven-plugin/src/main/java/com/microsoft/azure/maven/webapp/DeployMojo.java index 4d86063107..71e67dd116 100644 --- a/azure-webapp-maven-plugin/src/main/java/com/microsoft/azure/maven/webapp/DeployMojo.java +++ b/azure-webapp-maven-plugin/src/main/java/com/microsoft/azure/maven/webapp/DeployMojo.java @@ -17,7 +17,6 @@ import com.microsoft.azure.toolkit.lib.appservice.model.PricingTier; import com.microsoft.azure.toolkit.lib.appservice.model.WebAppArtifact; import com.microsoft.azure.toolkit.lib.appservice.model.WebContainer; -import com.microsoft.azure.toolkit.lib.appservice.service.IAppServicePlan; import com.microsoft.azure.toolkit.lib.appservice.service.IWebApp; import com.microsoft.azure.toolkit.lib.appservice.service.IWebAppBase; import com.microsoft.azure.toolkit.lib.appservice.service.IWebAppDeploymentSlot; @@ -29,15 +28,12 @@ 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.utils.Utils; -import com.microsoft.azure.toolkit.lib.legacy.appservice.AppServiceUtils; import org.apache.commons.lang3.StringUtils; import org.apache.maven.artifact.versioning.ComparableVersion; import org.apache.maven.plugins.annotations.LifecyclePhase; import org.apache.maven.plugins.annotations.Mojo; import java.util.List; -import java.util.Map; /** * Deploy an Azure Web App, either Windows-based or Linux-based. @@ -49,9 +45,6 @@ public class DeployMojo extends AbstractWebAppMojo { private static final String CREATE_DEPLOYMENT_SLOT = "Creating deployment slot %s in web app %s"; private static final String CREATE_DEPLOYMENT_SLOT_DONE = "Successfully created the Deployment Slot."; private static final String CREATE_NEW_DEPLOYMENT_SLOT = "createNewDeploymentSlot"; - private static final String SETTING_DOCKER_IMAGE = "DOCKER_CUSTOM_IMAGE_NAME"; - private static final String SETTING_REGISTRY_SERVER = "DOCKER_REGISTRY_SERVER_URL"; - private static final String SETTING_REGISTRY_USERNAME = "DOCKER_REGISTRY_SERVER_USERNAME"; @Override protected void doExecute() throws AzureExecutionException { @@ -82,44 +75,6 @@ private IWebAppBase createOrUpdateResource() throws AzureExecutionException { } } - static AppServiceConfig getAppServiceConfigFromExisting(IWebApp webapp) { - IAppServicePlan servicePlan = webapp.plan(); - AppServiceConfig config = new AppServiceConfig(); - config.appName(webapp.name()); - - config.resourceGroup(webapp.entity().getResourceGroup()); - config.subscriptionId(Utils.getSubscriptionId(webapp.id())); - config.region(webapp.entity().getRegion()); - config.pricingTier(servicePlan.entity().getPricingTier()); - RuntimeConfig runtimeConfig = new RuntimeConfig(); - if (AppServiceUtils.isDockerAppService(webapp)) { - runtimeConfig.os(OperatingSystem.DOCKER); - final Map settings = webapp.entity().getAppSettings(); - - final String imageSetting = settings.get(SETTING_DOCKER_IMAGE); - if (StringUtils.isNotBlank(imageSetting)) { - runtimeConfig.image(imageSetting); - } else { - runtimeConfig.image(webapp.entity().getDockerImageName()); - } - final String registryServerSetting = settings.get(SETTING_REGISTRY_SERVER); - if (StringUtils.isNotBlank(registryServerSetting)) { - runtimeConfig.registryUrl(registryServerSetting); - } - } else { - runtimeConfig.os(webapp.getRuntime().getOperatingSystem()); - runtimeConfig.webContainer(webapp.getRuntime().getWebContainer()); - runtimeConfig.javaVersion(webapp.getRuntime().getJavaVersion()); - } - config.runtime(runtimeConfig); - if (servicePlan.entity() != null) { - config.pricingTier(servicePlan.entity().getPricingTier()); - config.servicePlanName(servicePlan.name()); - config.servicePlanResourceGroup(servicePlan.entity().getResourceGroup()); - } - return config; - } - private AppServiceConfig buildDefaultConfig(String subscriptionId, String resourceGroup, String appName) { final ComparableVersion javaVersionForProject = new ComparableVersion(System.getProperty("java.version")); // get java version according to project java version From 44d742e9f594cef859741cd4e87cb44bd0cf6bd4 Mon Sep 17 00:00:00 2001 From: andxu Date: Tue, 21 Sep 2021 08:56:20 +0800 Subject: [PATCH 072/126] Move code to appservice-lib to allow share code with gradle plugins --- .../azure/maven/AbstractAppServiceMojo.java | 38 ------ .../lib/appservice/AzureAppService.java | 4 + .../appservice/config/AppServiceConfig.java | 19 +++ .../utils/AppServiceConfigUtils.java | 108 ++++++++++++++++++ .../toolkit/lib/appservice/utils/Utils.java | 7 ++ .../maven/webapp/AbstractWebAppMojo.java | 45 -------- .../azure/maven/webapp/ConfigMojo.java | 1 + .../azure/maven/webapp/DeployMojo.java | 35 ++---- 8 files changed, 147 insertions(+), 110 deletions(-) create mode 100644 azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/utils/AppServiceConfigUtils.java diff --git a/azure-maven-plugin-lib/src/main/java/com/microsoft/azure/maven/AbstractAppServiceMojo.java b/azure-maven-plugin-lib/src/main/java/com/microsoft/azure/maven/AbstractAppServiceMojo.java index b5bebe3776..01e8f1cccf 100644 --- a/azure-maven-plugin-lib/src/main/java/com/microsoft/azure/maven/AbstractAppServiceMojo.java +++ b/azure-maven-plugin-lib/src/main/java/com/microsoft/azure/maven/AbstractAppServiceMojo.java @@ -11,8 +11,6 @@ import com.microsoft.azure.maven.model.DeploymentResource; import com.microsoft.azure.toolkit.lib.Azure; import com.microsoft.azure.toolkit.lib.appservice.AzureAppService; -import com.microsoft.azure.toolkit.lib.appservice.config.AppServiceConfig; -import com.microsoft.azure.toolkit.lib.appservice.config.RuntimeConfig; import com.microsoft.azure.toolkit.lib.auth.Account; import com.microsoft.azure.toolkit.lib.auth.AzureAccount; import com.microsoft.azure.toolkit.lib.auth.exception.AzureLoginException; @@ -23,7 +21,6 @@ import com.microsoft.azure.toolkit.lib.common.utils.TextUtils; import com.microsoft.azure.toolkit.lib.legacy.appservice.DeploymentSlotSetting; import com.microsoft.azure.toolkit.lib.legacy.appservice.DeploymentType; -import org.apache.commons.lang3.ObjectUtils; import org.apache.maven.plugins.annotations.Parameter; import java.io.IOException; @@ -213,39 +210,4 @@ protected void printCurrentSubscription(AzureAppService appServiceClient) { Log.info(String.format(SUBSCRIPTION_TEMPLATE, TextUtils.cyan(subscription.getName()), TextUtils.cyan(subscription.getId()))); } } - - protected void mergeConfig(AppServiceConfig config1, AppServiceConfig config2) { - if (config1.region() == null) { - config1.region(config2.region()); - } - - if (config1.servicePlanResourceGroup() == null) { - config1.servicePlanResourceGroup(config2.servicePlanResourceGroup()); - } - - if (config1.servicePlanName() == null) { - config1.servicePlanName(config2.servicePlanName()); - } - - if (config1.runtime() == null) { - config1.runtime(config2.runtime()); - } else { - mergeRuntime(config1.runtime(), config2.runtime()); - } - - if (config1.pricingTier() == null) { - config1.pricingTier(config2.pricingTier()); - } - } - - private void mergeRuntime(RuntimeConfig runtime1, RuntimeConfig runtime2) { - runtime1.os(ObjectUtils.firstNonNull(runtime1.os(), runtime2.os())); - runtime1.image(ObjectUtils.firstNonNull(runtime1.image(), runtime2.image())); - runtime1.username(ObjectUtils.firstNonNull(runtime1.username(), runtime2.username())); - runtime1.password(ObjectUtils.firstNonNull(runtime1.password(), runtime2.password())); - runtime1.startUpCommand(ObjectUtils.firstNonNull(runtime1.startUpCommand(), runtime2.startUpCommand())); - runtime1.registryUrl(ObjectUtils.firstNonNull(runtime1.registryUrl(), runtime2.registryUrl())); - runtime1.javaVersion(ObjectUtils.firstNonNull(runtime1.javaVersion(), runtime2.javaVersion())); - runtime1.webContainer(ObjectUtils.firstNonNull(runtime1.webContainer(), runtime2.webContainer())); - } } diff --git a/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/AzureAppService.java b/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/AzureAppService.java index 2787ef964b..7e7f9b27c0 100644 --- a/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/AzureAppService.java +++ b/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/AzureAppService.java @@ -226,4 +226,8 @@ private HttpPipelinePolicy getUserAgentPolicy(String userAgent) { return httpPipelineNextPolicy.process(); }; } + + public String name() { + return "Microsoft.Web/sites"; + } } diff --git a/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/config/AppServiceConfig.java b/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/config/AppServiceConfig.java index a85a115337..6634cfbade 100644 --- a/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/config/AppServiceConfig.java +++ b/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/config/AppServiceConfig.java @@ -5,11 +5,15 @@ package com.microsoft.azure.toolkit.lib.appservice.config; +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.PricingTier; +import com.microsoft.azure.toolkit.lib.appservice.model.WebContainer; import com.microsoft.azure.toolkit.lib.common.model.Region; import lombok.Getter; import lombok.Setter; import lombok.experimental.Accessors; +import org.apache.commons.lang3.StringUtils; import java.util.Map; @@ -49,4 +53,19 @@ public AppServicePlanConfig getServicePlanConfig() { .os(runtime().os()) .pricingTier(pricingTier()); } + + public static AppServiceConfig buildDefaultConfig(String resourceGroup, String appName, String packaging, JavaVersion javaVersion) { + RuntimeConfig runtimeConfig = new RuntimeConfig().os(OperatingSystem.LINUX).webContainer(StringUtils.equalsIgnoreCase(packaging, "war") ? + WebContainer.TOMCAT_85 : (StringUtils.equalsIgnoreCase(packaging, "ear") ? WebContainer.JBOSS_7 : WebContainer.JAVA_SE)) + .javaVersion(javaVersion); + AppServiceConfig appServiceConfig = new AppServiceConfig(); + //TODO: use listSupportedRegions + appServiceConfig.region(Region.US_CENTRAL); + appServiceConfig.runtime(runtimeConfig); + appServiceConfig.resourceGroup(resourceGroup); + appServiceConfig.appName(appName); + appServiceConfig.servicePlanResourceGroup(resourceGroup); + appServiceConfig.servicePlanName(String.format("asp-%s", appName)); + return appServiceConfig; + } } diff --git a/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/utils/AppServiceConfigUtils.java b/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/utils/AppServiceConfigUtils.java new file mode 100644 index 0000000000..24c8387dbc --- /dev/null +++ b/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/utils/AppServiceConfigUtils.java @@ -0,0 +1,108 @@ +/* + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + */ + +package com.microsoft.azure.toolkit.lib.appservice.utils; + +import com.microsoft.azure.toolkit.lib.Azure; +import com.microsoft.azure.toolkit.lib.appservice.AzureAppService; +import com.microsoft.azure.toolkit.lib.appservice.config.AppServiceConfig; +import com.microsoft.azure.toolkit.lib.appservice.config.RuntimeConfig; +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.service.IAppServicePlan; +import com.microsoft.azure.toolkit.lib.appservice.service.IWebApp; +import com.microsoft.azure.toolkit.lib.common.model.Region; +import com.microsoft.azure.toolkit.lib.legacy.appservice.AppServiceUtils; +import org.apache.commons.lang3.ObjectUtils; +import org.apache.commons.lang3.StringUtils; + +import java.util.List; +import java.util.Map; + +public class AppServiceConfigUtils { + private static final String SETTING_DOCKER_IMAGE = "DOCKER_CUSTOM_IMAGE_NAME"; + private static final String SETTING_REGISTRY_SERVER = "DOCKER_REGISTRY_SERVER_URL"; + + public static AppServiceConfig getAppServiceConfigFromExisting(IWebApp webapp) { + IAppServicePlan servicePlan = webapp.plan(); + AppServiceConfig config = new AppServiceConfig(); + config.appName(webapp.name()); + + config.resourceGroup(webapp.entity().getResourceGroup()); + config.subscriptionId(Utils.getSubscriptionId(webapp.id())); + config.region(webapp.entity().getRegion()); + config.pricingTier(servicePlan.entity().getPricingTier()); + RuntimeConfig runtimeConfig = new RuntimeConfig(); + if (AppServiceUtils.isDockerAppService(webapp)) { + runtimeConfig.os(OperatingSystem.DOCKER); + final Map settings = webapp.entity().getAppSettings(); + + final String imageSetting = settings.get(SETTING_DOCKER_IMAGE); + if (StringUtils.isNotBlank(imageSetting)) { + runtimeConfig.image(imageSetting); + } else { + runtimeConfig.image(webapp.entity().getDockerImageName()); + } + final String registryServerSetting = settings.get(SETTING_REGISTRY_SERVER); + if (StringUtils.isNotBlank(registryServerSetting)) { + runtimeConfig.registryUrl(registryServerSetting); + } + } else { + runtimeConfig.os(webapp.getRuntime().getOperatingSystem()); + runtimeConfig.webContainer(webapp.getRuntime().getWebContainer()); + runtimeConfig.javaVersion(webapp.getRuntime().getJavaVersion()); + } + config.runtime(runtimeConfig); + if (servicePlan.entity() != null) { + config.pricingTier(servicePlan.entity().getPricingTier()); + config.servicePlanName(servicePlan.name()); + config.servicePlanResourceGroup(servicePlan.entity().getResourceGroup()); + } + return config; + } + + public static AppServiceConfig buildDefaultConfig(String subscriptionId, String resourceGroup, String appName, String packaging, JavaVersion javaVersion) { + final AppServiceConfig appServiceConfig = AppServiceConfig.buildDefaultConfig(resourceGroup, appName, packaging, javaVersion); + final List regions = Azure.az(AzureAppService.class).listSupportedRegions(subscriptionId); + // replace with first region when the default region is not present + appServiceConfig.region(Utils.selectFirstOptionIfCurrentInvalid("region", regions, appServiceConfig.region())); + return appServiceConfig; + } + + public static void mergeAppServiceConfig(AppServiceConfig config1, AppServiceConfig config2) { + if (config1.region() == null) { + config1.region(config2.region()); + } + + if (config1.servicePlanResourceGroup() == null) { + config1.servicePlanResourceGroup(config2.servicePlanResourceGroup()); + } + + if (config1.servicePlanName() == null) { + config1.servicePlanName(config2.servicePlanName()); + } + + if (config1.runtime() == null) { + config1.runtime(config2.runtime()); + } else { + mergeRuntime(config1.runtime(), config2.runtime()); + } + + if (config1.pricingTier() == null) { + config1.pricingTier(config2.pricingTier()); + } + } + + private static void mergeRuntime(RuntimeConfig runtime1, RuntimeConfig runtime2) { + runtime1.os(ObjectUtils.firstNonNull(runtime1.os(), runtime2.os())); + runtime1.image(ObjectUtils.firstNonNull(runtime1.image(), runtime2.image())); + runtime1.username(ObjectUtils.firstNonNull(runtime1.username(), runtime2.username())); + runtime1.password(ObjectUtils.firstNonNull(runtime1.password(), runtime2.password())); + runtime1.startUpCommand(ObjectUtils.firstNonNull(runtime1.startUpCommand(), runtime2.startUpCommand())); + runtime1.registryUrl(ObjectUtils.firstNonNull(runtime1.registryUrl(), runtime2.registryUrl())); + runtime1.javaVersion(ObjectUtils.firstNonNull(runtime1.javaVersion(), runtime2.javaVersion())); + runtime1.webContainer(ObjectUtils.firstNonNull(runtime1.webContainer(), runtime2.webContainer())); + } +} diff --git a/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/utils/Utils.java b/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/utils/Utils.java index ff69c3ed06..8a30408615 100644 --- a/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/utils/Utils.java +++ b/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/utils/Utils.java @@ -60,4 +60,11 @@ public static DeployType getDeployTypeByFileExtension(File file) { throw new AzureToolkitRuntimeException("Unsupported file type, please set the deploy type."); } } + + public static T selectFirstOptionIfCurrentInvalid(String name, List options, T value) { + if (options.isEmpty()) { + throw new AzureToolkitRuntimeException(String.format("No %s is available.", name)); + } + return options.contains(value) ? value : options.get(0); + } } diff --git a/azure-webapp-maven-plugin/src/main/java/com/microsoft/azure/maven/webapp/AbstractWebAppMojo.java b/azure-webapp-maven-plugin/src/main/java/com/microsoft/azure/maven/webapp/AbstractWebAppMojo.java index 8637bf9f9d..bb6a68c429 100644 --- a/azure-webapp-maven-plugin/src/main/java/com/microsoft/azure/maven/webapp/AbstractWebAppMojo.java +++ b/azure-webapp-maven-plugin/src/main/java/com/microsoft/azure/maven/webapp/AbstractWebAppMojo.java @@ -13,14 +13,9 @@ import com.microsoft.azure.maven.webapp.configuration.MavenRuntimeConfig; import com.microsoft.azure.maven.webapp.parser.ConfigParser; import com.microsoft.azure.toolkit.lib.appservice.AzureAppService; -import com.microsoft.azure.toolkit.lib.appservice.config.AppServiceConfig; -import com.microsoft.azure.toolkit.lib.appservice.config.RuntimeConfig; import com.microsoft.azure.toolkit.lib.appservice.model.OperatingSystem; -import com.microsoft.azure.toolkit.lib.appservice.service.IAppServicePlan; -import com.microsoft.azure.toolkit.lib.appservice.service.IWebApp; import com.microsoft.azure.toolkit.lib.common.exception.AzureExecutionException; import com.microsoft.azure.toolkit.lib.common.exception.AzureToolkitRuntimeException; -import com.microsoft.azure.toolkit.lib.common.utils.Utils; import com.microsoft.azure.toolkit.lib.common.validator.SchemaValidator; import com.microsoft.azure.toolkit.lib.common.validator.ValidationMessage; import com.microsoft.azure.toolkit.lib.legacy.appservice.AppServiceUtils; @@ -52,8 +47,6 @@ public abstract class AbstractWebAppMojo extends AbstractAppServiceMojo { public static final String SCHEMA_VERSION_KEY = "schemaVersion"; public static final String DEPLOY_TO_SLOT_KEY = "isDeployToSlot"; public static final String INVALID_PARAMETER_ERROR_MESSAGE = "Invalid values found in configuration, please correct the value with messages below:"; - public static final String SETTING_DOCKER_IMAGE = "DOCKER_CUSTOM_IMAGE_NAME"; - public static final String SETTING_REGISTRY_SERVER = "DOCKER_REGISTRY_SERVER_URL"; //region Properties /** @@ -244,44 +237,6 @@ protected void validateConfiguration(Consumer validationMessa } } - protected AppServiceConfig getAppServiceConfigFromExisting(IWebApp webapp) { - IAppServicePlan servicePlan = webapp.plan(); - AppServiceConfig config = new AppServiceConfig(); - config.appName(webapp.name()); - - config.resourceGroup(webapp.entity().getResourceGroup()); - config.subscriptionId(Utils.getSubscriptionId(webapp.id())); - config.region(webapp.entity().getRegion()); - config.pricingTier(servicePlan.entity().getPricingTier()); - RuntimeConfig runtimeConfig = new RuntimeConfig(); - if (AppServiceUtils.isDockerAppService(webapp)) { - runtimeConfig.os(OperatingSystem.DOCKER); - final Map settings = webapp.entity().getAppSettings(); - - final String imageSetting = settings.get(SETTING_DOCKER_IMAGE); - if (StringUtils.isNotBlank(imageSetting)) { - runtimeConfig.image(imageSetting); - } else { - runtimeConfig.image(webapp.entity().getDockerImageName()); - } - final String registryServerSetting = settings.get(SETTING_REGISTRY_SERVER); - if (StringUtils.isNotBlank(registryServerSetting)) { - runtimeConfig.registryUrl(registryServerSetting); - } - } else { - runtimeConfig.os(webapp.getRuntime().getOperatingSystem()); - runtimeConfig.webContainer(webapp.getRuntime().getWebContainer()); - runtimeConfig.javaVersion(webapp.getRuntime().getJavaVersion()); - } - config.runtime(runtimeConfig); - if (servicePlan.entity() != null) { - config.pricingTier(servicePlan.entity().getPricingTier()); - config.servicePlanName(servicePlan.name()); - config.servicePlanResourceGroup(servicePlan.entity().getResourceGroup()); - } - return config; - } - @Override public String getSubscriptionId() { return appServiceClient == null ? this.subscriptionId : appServiceClient.getDefaultSubscription().getId(); diff --git a/azure-webapp-maven-plugin/src/main/java/com/microsoft/azure/maven/webapp/ConfigMojo.java b/azure-webapp-maven-plugin/src/main/java/com/microsoft/azure/maven/webapp/ConfigMojo.java index f0dbbe5f3d..f309c1c792 100644 --- a/azure-webapp-maven-plugin/src/main/java/com/microsoft/azure/maven/webapp/ConfigMojo.java +++ b/azure-webapp-maven-plugin/src/main/java/com/microsoft/azure/maven/webapp/ConfigMojo.java @@ -55,6 +55,7 @@ import java.util.stream.Stream; import static com.microsoft.azure.maven.webapp.utils.Utils.findStringInCollectionIgnoreCase; +import static com.microsoft.azure.toolkit.lib.appservice.utils.AppServiceConfigUtils.getAppServiceConfigFromExisting; /** * Init or edit the configuration of azure webapp maven plugin. diff --git a/azure-webapp-maven-plugin/src/main/java/com/microsoft/azure/maven/webapp/DeployMojo.java b/azure-webapp-maven-plugin/src/main/java/com/microsoft/azure/maven/webapp/DeployMojo.java index 71e67dd116..d217a1718e 100644 --- a/azure-webapp-maven-plugin/src/main/java/com/microsoft/azure/maven/webapp/DeployMojo.java +++ b/azure-webapp-maven-plugin/src/main/java/com/microsoft/azure/maven/webapp/DeployMojo.java @@ -11,9 +11,7 @@ import com.microsoft.azure.toolkit.lib.Azure; import com.microsoft.azure.toolkit.lib.appservice.AzureAppService; import com.microsoft.azure.toolkit.lib.appservice.config.AppServiceConfig; -import com.microsoft.azure.toolkit.lib.appservice.config.RuntimeConfig; 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.PricingTier; import com.microsoft.azure.toolkit.lib.appservice.model.WebAppArtifact; import com.microsoft.azure.toolkit.lib.appservice.model.WebContainer; @@ -22,19 +20,19 @@ import com.microsoft.azure.toolkit.lib.appservice.service.IWebAppDeploymentSlot; import com.microsoft.azure.toolkit.lib.appservice.task.CreateOrUpdateWebAppTask; import com.microsoft.azure.toolkit.lib.appservice.task.DeployWebAppTask; -import com.microsoft.azure.toolkit.lib.auth.AzureAccount; +import com.microsoft.azure.toolkit.lib.appservice.utils.AppServiceConfigUtils; import com.microsoft.azure.toolkit.lib.common.bundle.AzureString; import com.microsoft.azure.toolkit.lib.common.exception.AzureExecutionException; -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 org.apache.commons.lang3.StringUtils; import org.apache.maven.artifact.versioning.ComparableVersion; import org.apache.maven.plugins.annotations.LifecyclePhase; import org.apache.maven.plugins.annotations.Mojo; import java.util.List; +import static com.microsoft.azure.toolkit.lib.appservice.utils.AppServiceConfigUtils.getAppServiceConfigFromExisting; +import static com.microsoft.azure.toolkit.lib.appservice.utils.AppServiceConfigUtils.mergeAppServiceConfig; + /** * Deploy an Azure Web App, either Windows-based or Linux-based. */ @@ -60,9 +58,10 @@ private IWebAppBase createOrUpdateResource() throws AzureExecutionException { if (!isDeployToDeploymentSlot()) { final AppServiceConfig appServiceConfig = getConfigParser().getAppServiceConfig(); IWebApp app = Azure.az(AzureAppService.class).webapp(appServiceConfig.resourceGroup(), appServiceConfig.appName()); - AppServiceConfig defaultConfig = app.exists() ? getAppServiceConfigFromExisting(app) : buildDefaultConfig(appServiceConfig.subscriptionId(), + final boolean newWebApp = !app.exists(); + AppServiceConfig defaultConfig = !newWebApp ? getAppServiceConfigFromExisting(app) : buildDefaultConfig(appServiceConfig.subscriptionId(), appServiceConfig.resourceGroup(), appServiceConfig.appName()); - mergeConfig(appServiceConfig, defaultConfig); + mergeAppServiceConfig(appServiceConfig, defaultConfig); if (appServiceConfig.pricingTier() == null) { appServiceConfig.pricingTier(appServiceConfig.runtime().webContainer() == WebContainer.JBOSS_7 ? PricingTier.PREMIUM_P1V3 : PricingTier.PREMIUM_P1V2); } @@ -79,25 +78,7 @@ private AppServiceConfig buildDefaultConfig(String subscriptionId, String resour final ComparableVersion javaVersionForProject = new ComparableVersion(System.getProperty("java.version")); // get java version according to project java version JavaVersion javaVersion = javaVersionForProject.compareTo(new ComparableVersion("9")) < 0 ? JavaVersion.JAVA_8 : JavaVersion.JAVA_11; - RuntimeConfig runtimeConfig = new RuntimeConfig().os(OperatingSystem.LINUX).webContainer(StringUtils.equalsIgnoreCase(this.project.getPackaging(), "jar") ? - WebContainer.JAVA_SE : (StringUtils.equalsIgnoreCase(this.project.getPackaging(), "ear") ? WebContainer.JBOSS_7 : WebContainer.TOMCAT_85)) - .javaVersion(javaVersion); - AppServiceConfig appServiceConfig = new AppServiceConfig(); - //TODO: use listSupportedRegions - appServiceConfig.region(getRegionOrDefault(Azure.az(AzureAccount.class).listRegions(subscriptionId))); - appServiceConfig.runtime(runtimeConfig); - appServiceConfig.resourceGroup(resourceGroup); - appServiceConfig.appName(appName); - appServiceConfig.servicePlanResourceGroup(resourceGroup); - appServiceConfig.servicePlanName(String.format("asp-%s", appName)); - return appServiceConfig; - } - - private static Region getRegionOrDefault(List regions) { - if (regions.isEmpty()) { - throw new AzureToolkitRuntimeException("No region is available."); - } - return regions.contains(Region.US_CENTRAL) ? Region.US_CENTRAL : regions.get(0); + return AppServiceConfigUtils.buildDefaultConfig(subscriptionId, resourceGroup, appName, this.project.getPackaging(), javaVersion); } private IWebAppDeploymentSlot getDeploymentSlot(final DeploymentSlotConfig config) throws AzureExecutionException { From 04ef224cdfa48a64d94063678b14a4527881f3ae Mon Sep 17 00:00:00 2001 From: andxu Date: Tue, 21 Sep 2021 09:05:43 +0800 Subject: [PATCH 073/126] detect service plan change by resource group and name --- .../azure/toolkit/lib/appservice/config/AppServiceConfig.java | 1 - .../toolkit/lib/appservice/task/CreateOrUpdateWebAppTask.java | 4 ++-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/config/AppServiceConfig.java b/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/config/AppServiceConfig.java index 6634cfbade..85ed7473e0 100644 --- a/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/config/AppServiceConfig.java +++ b/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/config/AppServiceConfig.java @@ -59,7 +59,6 @@ public static AppServiceConfig buildDefaultConfig(String resourceGroup, String a WebContainer.TOMCAT_85 : (StringUtils.equalsIgnoreCase(packaging, "ear") ? WebContainer.JBOSS_7 : WebContainer.JAVA_SE)) .javaVersion(javaVersion); AppServiceConfig appServiceConfig = new AppServiceConfig(); - //TODO: use listSupportedRegions appServiceConfig.region(Region.US_CENTRAL); appServiceConfig.runtime(runtimeConfig); appServiceConfig.resourceGroup(resourceGroup); diff --git a/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/task/CreateOrUpdateWebAppTask.java b/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/task/CreateOrUpdateWebAppTask.java index ae6dbc6d4f..946594be9c 100644 --- a/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/task/CreateOrUpdateWebAppTask.java +++ b/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/task/CreateOrUpdateWebAppTask.java @@ -78,7 +78,6 @@ private IWebApp create() { AzureTelemetry.getActionContext().setProperty(CREATE_NEW_WEB_APP, String.valueOf(true)); AzureMessager.getMessager().info(String.format(CREATE_WEBAPP, config.appName())); - // handle default region for resource group final Region region = this.config.region(); new CreateResourceGroupTask(this.config.subscriptionId(), this.config.resourceGroup(), region).execute(); final AzureAppService az = Azure.az(AzureAppService.class).subscription(config.subscriptionId()); @@ -106,7 +105,8 @@ private IWebApp update(final IWebApp webApp) { final Runtime runtime = getRuntime(config.runtime()); final IAppServicePlan appServicePlan = new CreateOrUpdateAppServicePlanTask(servicePlanConfig).execute(); final IAppServiceUpdater draft = webApp.update(); - if (!StringUtils.equalsIgnoreCase(config.servicePlanName(), currentPlan.name())) { + if (!(StringUtils.equalsIgnoreCase(config.servicePlanResourceGroup(), currentPlan.resourceGroup()) && + StringUtils.equalsIgnoreCase(config.servicePlanName(), currentPlan.name()))) { draft.withPlan(appServicePlan.id()); } if (!webApp.getRuntime().equals(runtime)) { From 8740573d235440349d68d502cb8fa0f784a1190f Mon Sep 17 00:00:00 2001 From: Hanxiao Liu Date: Sat, 18 Sep 2021 17:21:15 +0800 Subject: [PATCH 074/126] Add deploy task for azure functions --- .../task/DeployFunctionAppTask.java | 174 ++++++++++++++++++ 1 file changed, 174 insertions(+) create mode 100644 azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/task/DeployFunctionAppTask.java diff --git a/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/task/DeployFunctionAppTask.java b/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/task/DeployFunctionAppTask.java new file mode 100644 index 0000000000..2375015aed --- /dev/null +++ b/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/task/DeployFunctionAppTask.java @@ -0,0 +1,174 @@ +/* + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + */ +package com.microsoft.azure.toolkit.lib.appservice.task; + +import com.azure.core.management.exception.ManagementException; +import com.microsoft.azure.functions.annotation.AuthorizationLevel; +import com.microsoft.azure.toolkit.lib.Azure; +import com.microsoft.azure.toolkit.lib.appservice.AzureAppService; +import com.microsoft.azure.toolkit.lib.appservice.entity.FunctionEntity; +import com.microsoft.azure.toolkit.lib.appservice.model.FunctionDeployType; +import com.microsoft.azure.toolkit.lib.appservice.service.IFunctionApp; +import com.microsoft.azure.toolkit.lib.appservice.service.IFunctionAppBase; +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.task.AzureTask; +import com.microsoft.azure.toolkit.lib.common.telemetry.AzureTelemetry; +import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.lang3.StringUtils; +import org.zeroturnaround.zip.ZipUtil; +import reactor.core.publisher.Mono; +import reactor.core.scheduler.Schedulers; +import reactor.util.retry.Retry; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.time.Duration; +import java.util.List; +import java.util.Optional; +import java.util.stream.Collectors; + +public class DeployFunctionAppTask extends AzureTask> { + + private static final int SYNC_FUNCTION_MAX_ATTEMPTS = 5; + private static final int SYNC_FUNCTION_DELAY = 1; + private static final int LIST_TRIGGERS_MAX_RETRY = 5; + private static final int LIST_TRIGGERS_RETRY_PERIOD_IN_SECONDS = 10; + private static final String RUNNING = "Running"; + private static final String AUTH_LEVEL = "authLevel"; + private static final String HTTP_TRIGGER = "httpTrigger"; + private static final String LOCAL_SETTINGS_FILE = "local.settings.json"; + private static final String DEPLOY_START = "Starting deployment..."; + private static final String DEPLOY_FINISH = "Deployment done, you may access your resource through %s"; + private static final String HTTP_TRIGGER_URLS = "HTTP Trigger Urls:"; + private static final String NO_ANONYMOUS_HTTP_TRIGGER = "No anonymous HTTP Triggers found in deployed function app, skip list triggers."; + private static final String NO_TRIGGERS_FOUNDED = "No triggers found in deployed function app, " + + "please try recompile the project by `mvn clean package` and deploy again."; + private static final String UNABLE_TO_LIST_NONE_ANONYMOUS_HTTP_TRIGGERS = "Some http trigger urls cannot be displayed " + + "because they are non-anonymous. To access the non-anonymous triggers, please refer to https://aka.ms/azure-functions-key."; + private static final String SKIP_DEPLOYMENT_FOR_DOCKER_APP_SERVICE = "Skip deployment for docker app service"; + private static final String FAILED_TO_LIST_TRIGGERS = "Deployment succeeded, but failed to list http trigger urls."; + private static final String SYNC_TRIGGERS = "Syncing triggers and fetching function information"; + private static final String LIST_TRIGGERS = "Querying triggers..."; + private static final String LIST_TRIGGERS_WITH_RETRY = "Querying triggers (Attempt {0}/{1})..."; + + private final IFunctionAppBase target; + private final File stagingDirectory; + private final FunctionDeployType deployType; + + public DeployFunctionAppTask(@Nonnull IFunctionAppBase target, @Nonnull File stagingFolder, @Nullable FunctionDeployType deployType) { + this.target = target; + this.stagingDirectory = stagingFolder; + this.deployType = deployType; + } + + @Override + public AzureString getTitle() { + return AzureString.format("Deploy artifact to function app %s", target.name()); + } + + @Override + public IFunctionAppBase execute() { + if (target.getRuntime().isDocker()) { + AzureMessager.getMessager().info(SKIP_DEPLOYMENT_FOR_DOCKER_APP_SERVICE); + return target; + } + deployArtifact(); + if (target instanceof IFunctionApp) { + listHTTPTriggerUrls((IFunctionApp) target); + } + return target; + } + + private void deployArtifact() { + AzureMessager.getMessager().info(DEPLOY_START); + // For ftp deploy, we need to upload entire staging directory not the zipped package + final File file = deployType == FunctionDeployType.FTP ? stagingDirectory : packageStagingDirectory(); + final long startTime = System.currentTimeMillis(); + if (deployType == null) { + target.deploy(file); + } else { + target.deploy(file, deployType); + } + AzureTelemetry.getActionContext().setProperty("deploy-cost", String.valueOf(System.currentTimeMillis() - startTime)); + if (!StringUtils.equalsIgnoreCase(target.state(), RUNNING)) { + target.start(); + } + AzureMessager.getMessager().info(String.format(DEPLOY_FINISH, target.hostName())); + } + + private File packageStagingDirectory() { + try { + final File zipFile = Files.createTempFile("azure-functions", ".zip").toFile(); + ZipUtil.pack(stagingDirectory, zipFile); + ZipUtil.removeEntry(zipFile, LOCAL_SETTINGS_FILE); + return zipFile; + } catch (IOException e) { + throw new AzureToolkitRuntimeException("Failed to package function to deploy", e); + } + } + + private void listHTTPTriggerUrls(IFunctionApp target) { + try { + syncTriggers(target); + final List triggers = listFunctions(target); + final List httpFunction = triggers.stream() + .filter(function -> function.getTrigger() != null && + StringUtils.equalsIgnoreCase(function.getTrigger().getType(), HTTP_TRIGGER)) + .collect(Collectors.toList()); + final List anonymousTriggers = httpFunction.stream() + .filter(bindingResource -> bindingResource.getTrigger() != null && + StringUtils.equalsIgnoreCase(bindingResource.getTrigger().getProperty(AUTH_LEVEL), AuthorizationLevel.ANONYMOUS.toString())) + .collect(Collectors.toList()); + if (CollectionUtils.isEmpty(httpFunction) || CollectionUtils.isEmpty(anonymousTriggers)) { + AzureMessager.getMessager().info(NO_ANONYMOUS_HTTP_TRIGGER); + return; + } + AzureMessager.getMessager().info(HTTP_TRIGGER_URLS); + anonymousTriggers.forEach(trigger -> AzureMessager.getMessager().info(String.format("\t %s : %s", trigger.getName(), trigger.getTriggerUrl()))); + if (anonymousTriggers.size() < httpFunction.size()) { + AzureMessager.getMessager().info(UNABLE_TO_LIST_NONE_ANONYMOUS_HTTP_TRIGGERS); + } + } catch (final RuntimeException | InterruptedException e) { + // show warning instead of exception for list triggers + AzureMessager.getMessager().warning(FAILED_TO_LIST_TRIGGERS); + } + } + + // todo: move to app service library + // Refers https://github.com/Azure/azure-functions-core-tools/blob/3.0.3568/src/Azure.Functions.Cli/Actions/AzureActions/PublishFunctionAppAction.cs#L452 + private void syncTriggers(final IFunctionApp functionApp) throws InterruptedException { + AzureMessager.getMessager().info(SYNC_TRIGGERS); + Thread.sleep(5 * 1000); + Mono.fromRunnable(() -> { + try { + Azure.az(AzureAppService.class).getAppServiceManager(functionApp.subscriptionId()) + .functionApps().manager().serviceClient().getWebApps().syncFunctions(functionApp.resourceGroup(), functionApp.name()); + } catch (ManagementException e) { + if (e.getResponse().getStatusCode() == 200) { + // Java SDK throw exception with 200 response, swallow exception in this case + } + } + }).subscribeOn(Schedulers.boundedElastic()) + .retryWhen(Retry.fixedDelay(SYNC_FUNCTION_MAX_ATTEMPTS - 1, Duration.ofSeconds(SYNC_FUNCTION_DELAY))).block(); + } + + private List listFunctions(final IFunctionApp functionApp) { + final int[] count = {0}; + return Mono.fromCallable(() -> { + final AzureString message = count[0]++ == 0 ? + AzureString.fromString(LIST_TRIGGERS) : AzureString.format(LIST_TRIGGERS_WITH_RETRY, count[0], LIST_TRIGGERS_MAX_RETRY); + AzureMessager.getMessager().info(message); + return Optional.ofNullable(functionApp.listFunctions(true)) + .filter(CollectionUtils::isNotEmpty) + .orElseThrow(() -> new AzureToolkitRuntimeException(NO_TRIGGERS_FOUNDED)); + }).subscribeOn(Schedulers.boundedElastic()) + .retryWhen(Retry.fixedDelay(LIST_TRIGGERS_MAX_RETRY - 1, Duration.ofSeconds(LIST_TRIGGERS_RETRY_PERIOD_IN_SECONDS))).block(); + } +} From ad6842a116910851c8f774a2b2955d85ced84089 Mon Sep 17 00:00:00 2001 From: Hanxiao Liu Date: Mon, 20 Sep 2021 16:08:16 +0800 Subject: [PATCH 075/126] Migrate to function deployment task in app service library --- .../maven/function/AbstractFunctionMojo.java | 5 - .../azure/maven/function/DeployMojo.java | 106 +----------------- .../azure/maven/function/DeployMojoTest.java | 14 --- 3 files changed, 5 insertions(+), 120 deletions(-) diff --git a/azure-functions-maven-plugin/src/main/java/com/microsoft/azure/maven/function/AbstractFunctionMojo.java b/azure-functions-maven-plugin/src/main/java/com/microsoft/azure/maven/function/AbstractFunctionMojo.java index be0f618780..52e39be377 100644 --- a/azure-functions-maven-plugin/src/main/java/com/microsoft/azure/maven/function/AbstractFunctionMojo.java +++ b/azure-functions-maven-plugin/src/main/java/com/microsoft/azure/maven/function/AbstractFunctionMojo.java @@ -6,7 +6,6 @@ package com.microsoft.azure.maven.function; import com.microsoft.azure.maven.AbstractAppServiceMojo; -import com.microsoft.azure.toolkit.lib.appservice.service.IFunctionApp; import com.microsoft.azure.toolkit.lib.common.exception.AzureToolkitRuntimeException; import com.microsoft.azure.toolkit.lib.legacy.function.configurations.RuntimeConfiguration; import lombok.Getter; @@ -113,10 +112,6 @@ public boolean isDisableAppInsights() { return disableAppInsights; } - public IFunctionApp getFunctionApp() { - return getOrCreateAzureAppServiceClient().functionApp(getResourceGroup(), getAppName()); - } - public RuntimeConfiguration getRuntimeConfiguration() { return runtime; } diff --git a/azure-functions-maven-plugin/src/main/java/com/microsoft/azure/maven/function/DeployMojo.java b/azure-functions-maven-plugin/src/main/java/com/microsoft/azure/maven/function/DeployMojo.java index b6d73698d9..7f1d3baf5d 100644 --- a/azure-functions-maven-plugin/src/main/java/com/microsoft/azure/maven/function/DeployMojo.java +++ b/azure-functions-maven-plugin/src/main/java/com/microsoft/azure/maven/function/DeployMojo.java @@ -5,71 +5,44 @@ package com.microsoft.azure.maven.function; -import com.microsoft.azure.functions.annotation.AuthorizationLevel; import com.microsoft.azure.toolkit.lib.appservice.config.FunctionAppConfig; import com.microsoft.azure.toolkit.lib.appservice.config.RuntimeConfig; -import com.microsoft.azure.toolkit.lib.appservice.entity.AppServiceBaseEntity; -import com.microsoft.azure.toolkit.lib.appservice.entity.FunctionEntity; 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.OperatingSystem; import com.microsoft.azure.toolkit.lib.appservice.model.PricingTier; -import com.microsoft.azure.toolkit.lib.appservice.service.IFunctionApp; import com.microsoft.azure.toolkit.lib.appservice.service.IFunctionAppBase; import com.microsoft.azure.toolkit.lib.appservice.task.CreateOrUpdateFunctionAppTask; +import com.microsoft.azure.toolkit.lib.appservice.task.DeployFunctionAppTask; import com.microsoft.azure.toolkit.lib.common.bundle.AzureString; import com.microsoft.azure.toolkit.lib.common.exception.AzureExecutionException; 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.utils.Utils; -import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.io.FilenameUtils; import org.apache.commons.lang3.StringUtils; import org.apache.maven.artifact.versioning.ComparableVersion; import org.apache.maven.plugins.annotations.LifecyclePhase; import org.apache.maven.plugins.annotations.Mojo; -import org.zeroturnaround.zip.ZipUtil; -import reactor.core.publisher.Mono; -import reactor.core.scheduler.Schedulers; -import reactor.util.retry.Retry; import java.io.File; -import java.time.Duration; import java.util.Arrays; -import java.util.List; import java.util.Optional; -import java.util.stream.Collectors; /** * Deploy artifacts to target Azure Functions in Azure. If target Azure Functions doesn't exist, it will be created. */ @Mojo(name = "deploy", defaultPhase = LifecyclePhase.DEPLOY) public class DeployMojo extends AbstractFunctionMojo { - private static final String DEPLOY_START = "Starting deployment..."; - private static final String DEPLOY_FINISH = "Deployment done, you may access your resource through %s"; private static final String APPLICATION_INSIGHTS_CONFIGURATION_CONFLICT = "Contradictory configurations for application insights," + " specify 'appInsightsKey' or 'appInsightsInstance' if you want to enable it, and specify " + "'disableAppInsights=true' if you want to disable it."; - private static final String UNABLE_TO_LIST_NONE_ANONYMOUS_HTTP_TRIGGERS = "Some http trigger urls cannot be displayed " + - "because they are non-anonymous. To access the non-anonymous triggers, please refer to https://aka.ms/azure-functions-key."; - private static final String HTTP_TRIGGER_URLS = "HTTP Trigger Urls:"; - private static final String NO_ANONYMOUS_HTTP_TRIGGER = "No anonymous HTTP Triggers found in deployed function app, skip list triggers."; - private static final String AUTH_LEVEL = "authLevel"; - private static final String HTTP_TRIGGER = "httpTrigger"; private static final String ARTIFACT_INCOMPATIBLE_WARNING = "Your function app artifact compile version {0} may not compatible with java version {1} in " + "configuration."; private static final String ARTIFACT_INCOMPATIBLE_ERROR = "Your function app artifact compile version {0} is not compatible with java version {1} in " + "configuration, please downgrade the project compile version and try again."; - private static final String RUNNING = "Running"; private static final String NO_ARTIFACT_FOUNDED = "Failed to find function artifact '%s.jar' in folder '%s', please re-package the project and try again."; - private static final String LOCAL_SETTINGS_FILE = "local.settings.json"; - private static final int LIST_TRIGGERS_MAX_RETRY = 5; - private static final int LIST_TRIGGERS_RETRY_PERIOD_IN_SECONDS = 10; - private static final String SYNCING_TRIGGERS = "Syncing triggers and fetching function information"; - private static final String SYNCING_TRIGGERS_WITH_RETRY = "Syncing triggers and fetching function information (Attempt {0}/{1})..."; - private static final String NO_TRIGGERS_FOUNDED = "No triggers found in deployed function app, " + - "please try recompile the project by `mvn clean package` and deploy again."; private static final String APP_NAME_PATTERN = "[a-zA-Z0-9\\-]{2,60}"; private static final String RESOURCE_GROUP_PATTERN = "[a-zA-Z0-9._\\-()]{1,90}"; private static final String SLOT_NAME_PATTERN = "[A-Za-z0-9-]{1,60}"; @@ -86,8 +59,6 @@ public class DeployMojo extends AbstractFunctionMojo { private static final String INVALID_SLOT_NAME = "Invalid value of inside in pom.xml, it needs to match the pattern '%s'"; private static final String EMPTY_IMAGE_NAME = "Please config the of in pom.xml."; private static final String INVALID_OS = "The value of is not correct, supported values are: windows, linux and docker."; - private static final String FAILED_TO_LIST_TRIGGERS = "Deployment succeeded, but failed to list http trigger urls."; - private static final String SKIP_DEPLOYMENT_FOR_DOCKER_APP_SERVICE = "Skip deployment for docker app service"; private static final String EXPANDABLE_PRICING_TIER_WARNING = "'%s' may not be a valid pricing tier, " + "please refer to https://aka.ms/maven_function_configuration#supported-pricing-tiers for valid values"; private static final String EXPANDABLE_REGION_WARNING = "'%s' may not be a valid region, " + @@ -101,10 +72,6 @@ protected void doExecute() throws AzureExecutionException { final IFunctionAppBase target = createOrUpdateResource(getParser().parseConfig()); deployArtifact(target); - - if (target instanceof IFunctionApp) { - listHTTPTriggerUrls((IFunctionApp) target); - } } protected void doValidate() throws AzureExecutionException { @@ -171,73 +138,10 @@ protected IFunctionAppBase createOrUpdateResource(final FunctionAppConfig con return new CreateOrUpdateFunctionAppTask(config).execute(); } - private void deployArtifact(IFunctionAppBase target) throws AzureExecutionException { - if (target.getRuntime().isDocker()) { - AzureMessager.getMessager().info(SKIP_DEPLOYMENT_FOR_DOCKER_APP_SERVICE); - return; - } - AzureMessager.getMessager().info(DEPLOY_START); - final FunctionDeployType deployType = StringUtils.isEmpty(deploymentType) ? null : FunctionDeployType.fromString(deploymentType); - // For ftp deploy, we need to upload entire staging directory not the zipped package - final File file = deployType == FunctionDeployType.FTP ? new File(getDeploymentStagingDirectoryPath()) : packageStagingDirectory(); - final RunnableWithException deployRunnable = deployType == null ? () -> target.deploy(file) : () -> target.deploy(file, deployType); - executeWithTimeRecorder(deployRunnable, DEPLOY); - // todo: check function status after deployment - if (!StringUtils.equalsIgnoreCase(target.state(), RUNNING)) { - target.start(); - } - AzureMessager.getMessager().info(String.format(DEPLOY_FINISH, getResourcePortalUrl(target.id()))); - } - - private File packageStagingDirectory() { - final File zipFile = new File(getDeploymentStagingDirectoryPath() + ".zip"); - final File stagingDirectory = new File(getDeploymentStagingDirectoryPath()); - - ZipUtil.pack(stagingDirectory, zipFile); - ZipUtil.removeEntry(zipFile, LOCAL_SETTINGS_FILE); - return zipFile; - } - - /** - * List anonymous HTTP Triggers url after deployment - */ - protected void listHTTPTriggerUrls(IFunctionApp target) { - try { - final List triggers = listFunctions(target); - final List httpFunction = triggers.stream() - .filter(function -> function.getTrigger() != null && - StringUtils.equalsIgnoreCase(function.getTrigger().getType(), HTTP_TRIGGER)) - .collect(Collectors.toList()); - final List anonymousTriggers = httpFunction.stream() - .filter(bindingResource -> bindingResource.getTrigger() != null && - StringUtils.equalsIgnoreCase(bindingResource.getTrigger().getProperty(AUTH_LEVEL), AuthorizationLevel.ANONYMOUS.toString())) - .collect(Collectors.toList()); - if (CollectionUtils.isEmpty(httpFunction) || CollectionUtils.isEmpty(anonymousTriggers)) { - AzureMessager.getMessager().info(NO_ANONYMOUS_HTTP_TRIGGER); - return; - } - AzureMessager.getMessager().info(HTTP_TRIGGER_URLS); - anonymousTriggers.forEach(trigger -> AzureMessager.getMessager().info(String.format("\t %s : %s", trigger.getName(), trigger.getTriggerUrl()))); - if (anonymousTriggers.size() < httpFunction.size()) { - AzureMessager.getMessager().info(UNABLE_TO_LIST_NONE_ANONYMOUS_HTTP_TRIGGERS); - } - } catch (RuntimeException e) { - // show warning instead of exception for list triggers - AzureMessager.getMessager().warning(FAILED_TO_LIST_TRIGGERS); - } - } - - private List listFunctions(final IFunctionApp functionApp) { - final int[] count = {0}; - return Mono.fromCallable(() -> { - final AzureString message = count[0]++ == 0 ? - AzureString.fromString(SYNCING_TRIGGERS) : AzureString.format(SYNCING_TRIGGERS_WITH_RETRY, count[0], LIST_TRIGGERS_MAX_RETRY); - AzureMessager.getMessager().info(message); - return Optional.ofNullable(functionApp.listFunctions(true)) - .filter(CollectionUtils::isNotEmpty) - .orElseThrow(() -> new AzureToolkitRuntimeException(NO_TRIGGERS_FOUNDED)); - }).subscribeOn(Schedulers.boundedElastic()) - .retryWhen(Retry.fixedDelay(LIST_TRIGGERS_MAX_RETRY - 1, Duration.ofSeconds(LIST_TRIGGERS_RETRY_PERIOD_IN_SECONDS))).block(); + private void deployArtifact(final IFunctionAppBase target) { + final File file = new File(getDeploymentStagingDirectoryPath()); + final FunctionDeployType type = StringUtils.isEmpty(deploymentType) ? null : FunctionDeployType.fromString(deploymentType); + new DeployFunctionAppTask(target, file, type).execute(); } protected void validateArtifactCompileVersion() throws AzureExecutionException { diff --git a/azure-functions-maven-plugin/src/test/java/com/microsoft/azure/maven/function/DeployMojoTest.java b/azure-functions-maven-plugin/src/test/java/com/microsoft/azure/maven/function/DeployMojoTest.java index 82fb86a4e9..d27035cd66 100644 --- a/azure-functions-maven-plugin/src/test/java/com/microsoft/azure/maven/function/DeployMojoTest.java +++ b/azure-functions-maven-plugin/src/test/java/com/microsoft/azure/maven/function/DeployMojoTest.java @@ -5,17 +5,13 @@ package com.microsoft.azure.maven.function; -import com.microsoft.azure.toolkit.lib.common.exception.AzureExecutionException; -import com.microsoft.azure.toolkit.lib.legacy.appservice.DeploymentSlotSetting; import org.junit.Before; -import org.junit.Ignore; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.junit.MockitoJUnitRunner; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; -import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.spy; @RunWith(MockitoJUnitRunner.class) @@ -38,16 +34,6 @@ public void getConfiguration() { assertEquals("westeurope", mojo.getRegion()); } - @Ignore - @Test(expected = AzureExecutionException.class) - public void testDeploymentSlotThrowExceptionIfFunctionNotExists() throws AzureExecutionException { - final DeploymentSlotSetting slotSetting = new DeploymentSlotSetting(); - slotSetting.setName("Exception"); - doReturn(slotSetting).when(mojoSpy).getDeploymentSlotSetting(); - doReturn(null).when(mojoSpy).getFunctionApp(); - mojoSpy.doExecute(); - } - private DeployMojo getMojoFromPom() throws Exception { final DeployMojo mojoFromPom = (DeployMojo) getMojoFromPom("/pom.xml", "deploy"); assertNotNull(mojoFromPom); From b3a8d87c3cb018ad5aec08cf13e324386b30b33d Mon Sep 17 00:00:00 2001 From: andxu Date: Tue, 21 Sep 2021 14:06:20 +0800 Subject: [PATCH 076/126] Normalize web and function to share code --- .../appservice/config/AppServiceConfig.java | 21 +++++++++++++++++-- .../utils/AppServiceConfigUtils.java | 7 +++---- .../legacy/appservice/AppServiceUtils.java | 6 +++--- .../azure/maven/webapp/ConfigMojo.java | 2 +- .../azure/maven/webapp/DeployMojo.java | 2 +- 5 files changed, 27 insertions(+), 11 deletions(-) diff --git a/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/config/AppServiceConfig.java b/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/config/AppServiceConfig.java index 85ed7473e0..f3893e5201 100644 --- a/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/config/AppServiceConfig.java +++ b/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/config/AppServiceConfig.java @@ -15,6 +15,7 @@ import lombok.experimental.Accessors; import org.apache.commons.lang3.StringUtils; +import javax.annotation.Nonnull; import java.util.Map; @Getter @@ -54,13 +55,29 @@ public AppServicePlanConfig getServicePlanConfig() { .pricingTier(pricingTier()); } - public static AppServiceConfig buildDefaultConfig(String resourceGroup, String appName, String packaging, JavaVersion javaVersion) { + public static AppServiceConfig buildDefaultWebAppConfig(String resourceGroup, String appName, String packaging, JavaVersion javaVersion) { RuntimeConfig runtimeConfig = new RuntimeConfig().os(OperatingSystem.LINUX).webContainer(StringUtils.equalsIgnoreCase(packaging, "war") ? WebContainer.TOMCAT_85 : (StringUtils.equalsIgnoreCase(packaging, "ear") ? WebContainer.JBOSS_7 : WebContainer.JAVA_SE)) .javaVersion(javaVersion); + AppServiceConfig appServiceConfig = buildCommonAppServiceConfig(resourceGroup, appName); + appServiceConfig.runtime(runtimeConfig); + return appServiceConfig; + } + + public static AppServiceConfig buildDefaultFunctionConfig(String resourceGroup, String appName, JavaVersion javaVersion) { + RuntimeConfig runtimeConfig = new RuntimeConfig().os(OperatingSystem.WINDOWS).webContainer(WebContainer.JAVA_OFF) + .javaVersion(javaVersion); + AppServiceConfig appServiceConfig = buildCommonAppServiceConfig(resourceGroup, appName); + appServiceConfig.runtime(runtimeConfig); + appServiceConfig.pricingTier(PricingTier.CONSUMPTION); + return appServiceConfig; + } + + @Nonnull + private static AppServiceConfig buildCommonAppServiceConfig(String resourceGroup, String appName) { AppServiceConfig appServiceConfig = new AppServiceConfig(); appServiceConfig.region(Region.US_CENTRAL); - appServiceConfig.runtime(runtimeConfig); + appServiceConfig.resourceGroup(resourceGroup); appServiceConfig.appName(appName); appServiceConfig.servicePlanResourceGroup(resourceGroup); diff --git a/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/utils/AppServiceConfigUtils.java b/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/utils/AppServiceConfigUtils.java index 24c8387dbc..455eef299b 100644 --- a/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/utils/AppServiceConfigUtils.java +++ b/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/utils/AppServiceConfigUtils.java @@ -11,8 +11,8 @@ import com.microsoft.azure.toolkit.lib.appservice.config.RuntimeConfig; 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.service.IAppService; import com.microsoft.azure.toolkit.lib.appservice.service.IAppServicePlan; -import com.microsoft.azure.toolkit.lib.appservice.service.IWebApp; import com.microsoft.azure.toolkit.lib.common.model.Region; import com.microsoft.azure.toolkit.lib.legacy.appservice.AppServiceUtils; import org.apache.commons.lang3.ObjectUtils; @@ -25,8 +25,7 @@ public class AppServiceConfigUtils { private static final String SETTING_DOCKER_IMAGE = "DOCKER_CUSTOM_IMAGE_NAME"; private static final String SETTING_REGISTRY_SERVER = "DOCKER_REGISTRY_SERVER_URL"; - public static AppServiceConfig getAppServiceConfigFromExisting(IWebApp webapp) { - IAppServicePlan servicePlan = webapp.plan(); + public static AppServiceConfig getAppServiceConfigFromExisting(IAppService webapp, IAppServicePlan servicePlan) { AppServiceConfig config = new AppServiceConfig(); config.appName(webapp.name()); @@ -64,7 +63,7 @@ public static AppServiceConfig getAppServiceConfigFromExisting(IWebApp webapp) { } public static AppServiceConfig buildDefaultConfig(String subscriptionId, String resourceGroup, String appName, String packaging, JavaVersion javaVersion) { - final AppServiceConfig appServiceConfig = AppServiceConfig.buildDefaultConfig(resourceGroup, appName, packaging, javaVersion); + final AppServiceConfig appServiceConfig = AppServiceConfig.buildDefaultWebAppConfig(resourceGroup, appName, packaging, javaVersion); final List regions = Azure.az(AzureAppService.class).listSupportedRegions(subscriptionId); // replace with first region when the default region is not present appServiceConfig.region(Utils.selectFirstOptionIfCurrentInvalid("region", regions, appServiceConfig.region())); diff --git a/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/legacy/appservice/AppServiceUtils.java b/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/legacy/appservice/AppServiceUtils.java index a766fe6c1e..0914599bad 100644 --- a/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/legacy/appservice/AppServiceUtils.java +++ b/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/legacy/appservice/AppServiceUtils.java @@ -7,7 +7,7 @@ import com.microsoft.azure.toolkit.lib.appservice.model.OperatingSystem; import com.microsoft.azure.toolkit.lib.appservice.model.PricingTier; -import com.microsoft.azure.toolkit.lib.appservice.service.IWebApp; +import com.microsoft.azure.toolkit.lib.appservice.service.IAppService; import org.apache.commons.lang3.StringUtils; import java.util.ArrayList; @@ -41,8 +41,8 @@ public static DockerImageType getDockerImageType(final String imageName, final b } } - public static boolean isDockerAppService(IWebApp webapp) { - return webapp != null && webapp.getRuntime() != null && webapp.getRuntime().isDocker(); + public static boolean isDockerAppService(IAppService appService) { + return appService != null && appService.getRuntime() != null && appService.getRuntime().isDocker(); } } diff --git a/azure-webapp-maven-plugin/src/main/java/com/microsoft/azure/maven/webapp/ConfigMojo.java b/azure-webapp-maven-plugin/src/main/java/com/microsoft/azure/maven/webapp/ConfigMojo.java index f309c1c792..df2844815c 100644 --- a/azure-webapp-maven-plugin/src/main/java/com/microsoft/azure/maven/webapp/ConfigMojo.java +++ b/azure-webapp-maven-plugin/src/main/java/com/microsoft/azure/maven/webapp/ConfigMojo.java @@ -528,7 +528,7 @@ private static WebAppOption selectAzureWebApp(TextIO textIO, List private WebAppConfiguration getConfigurationFromExisting(IWebApp webapp, WebAppConfiguration.WebAppConfigurationBuilder builder) { - final AppServiceConfig appServiceConfig = getAppServiceConfigFromExisting(webapp); + final AppServiceConfig appServiceConfig = getAppServiceConfigFromExisting(webapp, webapp.plan()); // common configuration builder.appName(appServiceConfig.appName()) .resourceGroup(appServiceConfig.resourceGroup()) diff --git a/azure-webapp-maven-plugin/src/main/java/com/microsoft/azure/maven/webapp/DeployMojo.java b/azure-webapp-maven-plugin/src/main/java/com/microsoft/azure/maven/webapp/DeployMojo.java index d217a1718e..c52b96b044 100644 --- a/azure-webapp-maven-plugin/src/main/java/com/microsoft/azure/maven/webapp/DeployMojo.java +++ b/azure-webapp-maven-plugin/src/main/java/com/microsoft/azure/maven/webapp/DeployMojo.java @@ -59,7 +59,7 @@ private IWebAppBase createOrUpdateResource() throws AzureExecutionException { final AppServiceConfig appServiceConfig = getConfigParser().getAppServiceConfig(); IWebApp app = Azure.az(AzureAppService.class).webapp(appServiceConfig.resourceGroup(), appServiceConfig.appName()); final boolean newWebApp = !app.exists(); - AppServiceConfig defaultConfig = !newWebApp ? getAppServiceConfigFromExisting(app) : buildDefaultConfig(appServiceConfig.subscriptionId(), + AppServiceConfig defaultConfig = !newWebApp ? getAppServiceConfigFromExisting(app, app.plan()) : buildDefaultConfig(appServiceConfig.subscriptionId(), appServiceConfig.resourceGroup(), appServiceConfig.appName()); mergeAppServiceConfig(appServiceConfig, defaultConfig); if (appServiceConfig.pricingTier() == null) { From 20a7935ddda10276bcfebfa7fe1c458381c9f430 Mon Sep 17 00:00:00 2001 From: andxu Date: Wed, 22 Sep 2021 09:46:34 +0800 Subject: [PATCH 077/126] address code review comments. --- azure-webapp-maven-plugin/README.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/azure-webapp-maven-plugin/README.md b/azure-webapp-maven-plugin/README.md index 73e85b25f6..1a9fc727da 100644 --- a/azure-webapp-maven-plugin/README.md +++ b/azure-webapp-maven-plugin/README.md @@ -73,11 +73,11 @@ Property | Required | Description `` | true | Azure Resource Group for your Web App. | `` | true | The name of your Web App. | ``| false | The pricing tier for your Web App. The default value is **P1V2**(**P1v3** for JBoss).| -``| false | Specifies the region where your Web App will be hosted; the default value is **westeurope**(or the first region available in your subscription). All valid regions at [Supported Regions](#region) section. | -``| false | Specifies the os, supported values are *Linux*, *Windows* and *Docker*. The default value is **linux**| -``| false | Specifies the runtime stack, values for Linux are: *Tomcat 8.5*, *Tomcat 9.0*, *Java SE*, *JbossEAP 7.2*, The default value would be **Tomcat 8.5** or **Java SE** according to your project type | -``| false | Specifies the java version, values are: *Java 8* or *Java 11*. The default value is **Java 11**| -``| false | Specifies the target file to be deployed. If it is not specified, a default webapp is created. | +``| false | Specifies the region where your Web App will be hosted; the default value is **centralus**(or the first region if centralus is not available in your subscription). All valid regions at [Supported Regions](#region) section. | + ``| false | Specifies the os, supported values are *Linux*, *Windows* and *Docker*. The default value is **linux**| +``| false | Specifies the runtime stack, values for Linux are: *Tomcat 8.5*, *Tomcat 9.0*, *Java SE*, *JBossEAP 7*, The default value would be **Tomcat 8.5** or **Java SE** or **JBossEAP 7** according to your project type | +``| false | Specifies the java version, values are: *Java 8* or *Java 11*. The default value is your project compiler level| +``| false | Specifies the target file to be deployed. If it is not specified, a default webapp is created without any deployments. | ## Feedback and Questions To report bugs or request new features, file issues on [Issues](https://github.com/microsoft/azure-maven-plugins/issues). Or, ask questions on [Stack Overflow with tag azure-java-tools](https://stackoverflow.com/questions/tagged/azure-java-tools). From eca29133cda3e80a987e1ccf7acfd4c4b74275ad Mon Sep 17 00:00:00 2001 From: andxu Date: Wed, 22 Sep 2021 12:29:33 +0800 Subject: [PATCH 078/126] 1. rename some methods for a better name. 2. use reflection api to merge objects. --- .../appservice/config/AppServiceConfig.java | 6 +-- .../utils/AppServiceConfigUtils.java | 53 +++++++++---------- .../azure/maven/webapp/ConfigMojo.java | 4 +- .../azure/maven/webapp/DeployMojo.java | 4 +- 4 files changed, 33 insertions(+), 34 deletions(-) diff --git a/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/config/AppServiceConfig.java b/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/config/AppServiceConfig.java index f3893e5201..6a677558b4 100644 --- a/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/config/AppServiceConfig.java +++ b/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/config/AppServiceConfig.java @@ -59,7 +59,7 @@ public static AppServiceConfig buildDefaultWebAppConfig(String resourceGroup, St RuntimeConfig runtimeConfig = new RuntimeConfig().os(OperatingSystem.LINUX).webContainer(StringUtils.equalsIgnoreCase(packaging, "war") ? WebContainer.TOMCAT_85 : (StringUtils.equalsIgnoreCase(packaging, "ear") ? WebContainer.JBOSS_7 : WebContainer.JAVA_SE)) .javaVersion(javaVersion); - AppServiceConfig appServiceConfig = buildCommonAppServiceConfig(resourceGroup, appName); + AppServiceConfig appServiceConfig = buildDefaultAppServiceConfig(resourceGroup, appName); appServiceConfig.runtime(runtimeConfig); return appServiceConfig; } @@ -67,14 +67,14 @@ public static AppServiceConfig buildDefaultWebAppConfig(String resourceGroup, St public static AppServiceConfig buildDefaultFunctionConfig(String resourceGroup, String appName, JavaVersion javaVersion) { RuntimeConfig runtimeConfig = new RuntimeConfig().os(OperatingSystem.WINDOWS).webContainer(WebContainer.JAVA_OFF) .javaVersion(javaVersion); - AppServiceConfig appServiceConfig = buildCommonAppServiceConfig(resourceGroup, appName); + AppServiceConfig appServiceConfig = buildDefaultAppServiceConfig(resourceGroup, appName); appServiceConfig.runtime(runtimeConfig); appServiceConfig.pricingTier(PricingTier.CONSUMPTION); return appServiceConfig; } @Nonnull - private static AppServiceConfig buildCommonAppServiceConfig(String resourceGroup, String appName) { + private static AppServiceConfig buildDefaultAppServiceConfig(String resourceGroup, String appName) { AppServiceConfig appServiceConfig = new AppServiceConfig(); appServiceConfig.region(Region.US_CENTRAL); diff --git a/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/utils/AppServiceConfigUtils.java b/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/utils/AppServiceConfigUtils.java index 455eef299b..917f7e45c6 100644 --- a/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/utils/AppServiceConfigUtils.java +++ b/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/utils/AppServiceConfigUtils.java @@ -13,11 +13,13 @@ import com.microsoft.azure.toolkit.lib.appservice.model.OperatingSystem; import com.microsoft.azure.toolkit.lib.appservice.service.IAppService; import com.microsoft.azure.toolkit.lib.appservice.service.IAppServicePlan; +import com.microsoft.azure.toolkit.lib.common.exception.AzureToolkitRuntimeException; import com.microsoft.azure.toolkit.lib.common.model.Region; import com.microsoft.azure.toolkit.lib.legacy.appservice.AppServiceUtils; -import org.apache.commons.lang3.ObjectUtils; import org.apache.commons.lang3.StringUtils; +import org.apache.commons.lang3.reflect.FieldUtils; +import java.lang.reflect.Field; import java.util.List; import java.util.Map; @@ -25,7 +27,7 @@ public class AppServiceConfigUtils { private static final String SETTING_DOCKER_IMAGE = "DOCKER_CUSTOM_IMAGE_NAME"; private static final String SETTING_REGISTRY_SERVER = "DOCKER_REGISTRY_SERVER_URL"; - public static AppServiceConfig getAppServiceConfigFromExisting(IAppService webapp, IAppServicePlan servicePlan) { + public static AppServiceConfig fromAppService(IAppService webapp, IAppServicePlan servicePlan) { AppServiceConfig config = new AppServiceConfig(); config.appName(webapp.name()); @@ -70,38 +72,35 @@ public static AppServiceConfig buildDefaultConfig(String subscriptionId, String return appServiceConfig; } - public static void mergeAppServiceConfig(AppServiceConfig config1, AppServiceConfig config2) { - if (config1.region() == null) { - config1.region(config2.region()); + public static void mergeAppServiceConfig(AppServiceConfig to, AppServiceConfig from) { + try { + mergeObjects(to, from); + } catch (IllegalAccessException e) { + throw new AzureToolkitRuntimeException("Cannot copy object for class AppServiceConfig.", e); } - if (config1.servicePlanResourceGroup() == null) { - config1.servicePlanResourceGroup(config2.servicePlanResourceGroup()); + if (to.runtime() != from.runtime()) { + mergeRuntime(to.runtime(), from.runtime()); } + } - if (config1.servicePlanName() == null) { - config1.servicePlanName(config2.servicePlanName()); + private static void mergeRuntime(RuntimeConfig to, RuntimeConfig from) { + try { + mergeObjects(to, from); + } catch (IllegalAccessException e) { + throw new AzureToolkitRuntimeException("Cannot copy object for class RuntimeConfig.", e); } + } - if (config1.runtime() == null) { - config1.runtime(config2.runtime()); - } else { - mergeRuntime(config1.runtime(), config2.runtime()); - } + private static void mergeObjects(T to, T from) throws IllegalAccessException { + for (Field field : FieldUtils.getAllFields(to.getClass())) { + if (FieldUtils.readField(field, to, true) == null) { + final Object value = FieldUtils.readField(field, from, true); + if (value != null) { + FieldUtils.writeField(field, to, value, true); + } + } - if (config1.pricingTier() == null) { - config1.pricingTier(config2.pricingTier()); } } - - private static void mergeRuntime(RuntimeConfig runtime1, RuntimeConfig runtime2) { - runtime1.os(ObjectUtils.firstNonNull(runtime1.os(), runtime2.os())); - runtime1.image(ObjectUtils.firstNonNull(runtime1.image(), runtime2.image())); - runtime1.username(ObjectUtils.firstNonNull(runtime1.username(), runtime2.username())); - runtime1.password(ObjectUtils.firstNonNull(runtime1.password(), runtime2.password())); - runtime1.startUpCommand(ObjectUtils.firstNonNull(runtime1.startUpCommand(), runtime2.startUpCommand())); - runtime1.registryUrl(ObjectUtils.firstNonNull(runtime1.registryUrl(), runtime2.registryUrl())); - runtime1.javaVersion(ObjectUtils.firstNonNull(runtime1.javaVersion(), runtime2.javaVersion())); - runtime1.webContainer(ObjectUtils.firstNonNull(runtime1.webContainer(), runtime2.webContainer())); - } } diff --git a/azure-webapp-maven-plugin/src/main/java/com/microsoft/azure/maven/webapp/ConfigMojo.java b/azure-webapp-maven-plugin/src/main/java/com/microsoft/azure/maven/webapp/ConfigMojo.java index df2844815c..d3a962ad38 100644 --- a/azure-webapp-maven-plugin/src/main/java/com/microsoft/azure/maven/webapp/ConfigMojo.java +++ b/azure-webapp-maven-plugin/src/main/java/com/microsoft/azure/maven/webapp/ConfigMojo.java @@ -55,7 +55,7 @@ import java.util.stream.Stream; import static com.microsoft.azure.maven.webapp.utils.Utils.findStringInCollectionIgnoreCase; -import static com.microsoft.azure.toolkit.lib.appservice.utils.AppServiceConfigUtils.getAppServiceConfigFromExisting; +import static com.microsoft.azure.toolkit.lib.appservice.utils.AppServiceConfigUtils.fromAppService; /** * Init or edit the configuration of azure webapp maven plugin. @@ -528,7 +528,7 @@ private static WebAppOption selectAzureWebApp(TextIO textIO, List private WebAppConfiguration getConfigurationFromExisting(IWebApp webapp, WebAppConfiguration.WebAppConfigurationBuilder builder) { - final AppServiceConfig appServiceConfig = getAppServiceConfigFromExisting(webapp, webapp.plan()); + final AppServiceConfig appServiceConfig = fromAppService(webapp, webapp.plan()); // common configuration builder.appName(appServiceConfig.appName()) .resourceGroup(appServiceConfig.resourceGroup()) diff --git a/azure-webapp-maven-plugin/src/main/java/com/microsoft/azure/maven/webapp/DeployMojo.java b/azure-webapp-maven-plugin/src/main/java/com/microsoft/azure/maven/webapp/DeployMojo.java index c52b96b044..004c72aad7 100644 --- a/azure-webapp-maven-plugin/src/main/java/com/microsoft/azure/maven/webapp/DeployMojo.java +++ b/azure-webapp-maven-plugin/src/main/java/com/microsoft/azure/maven/webapp/DeployMojo.java @@ -30,7 +30,7 @@ import java.util.List; -import static com.microsoft.azure.toolkit.lib.appservice.utils.AppServiceConfigUtils.getAppServiceConfigFromExisting; +import static com.microsoft.azure.toolkit.lib.appservice.utils.AppServiceConfigUtils.fromAppService; import static com.microsoft.azure.toolkit.lib.appservice.utils.AppServiceConfigUtils.mergeAppServiceConfig; /** @@ -59,7 +59,7 @@ private IWebAppBase createOrUpdateResource() throws AzureExecutionException { final AppServiceConfig appServiceConfig = getConfigParser().getAppServiceConfig(); IWebApp app = Azure.az(AzureAppService.class).webapp(appServiceConfig.resourceGroup(), appServiceConfig.appName()); final boolean newWebApp = !app.exists(); - AppServiceConfig defaultConfig = !newWebApp ? getAppServiceConfigFromExisting(app, app.plan()) : buildDefaultConfig(appServiceConfig.subscriptionId(), + AppServiceConfig defaultConfig = !newWebApp ? fromAppService(app, app.plan()) : buildDefaultConfig(appServiceConfig.subscriptionId(), appServiceConfig.resourceGroup(), appServiceConfig.appName()); mergeAppServiceConfig(appServiceConfig, defaultConfig); if (appServiceConfig.pricingTier() == null) { From 1800194f617061683ec2d2d836ac27958fe82218 Mon Sep 17 00:00:00 2001 From: andxu Date: Wed, 22 Sep 2021 12:54:26 +0800 Subject: [PATCH 079/126] get java version from jar file. --- .../azure/maven/webapp/DeployMojo.java | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/azure-webapp-maven-plugin/src/main/java/com/microsoft/azure/maven/webapp/DeployMojo.java b/azure-webapp-maven-plugin/src/main/java/com/microsoft/azure/maven/webapp/DeployMojo.java index 004c72aad7..787bcb20e0 100644 --- a/azure-webapp-maven-plugin/src/main/java/com/microsoft/azure/maven/webapp/DeployMojo.java +++ b/azure-webapp-maven-plugin/src/main/java/com/microsoft/azure/maven/webapp/DeployMojo.java @@ -24,10 +24,15 @@ import com.microsoft.azure.toolkit.lib.common.bundle.AzureString; import com.microsoft.azure.toolkit.lib.common.exception.AzureExecutionException; import com.microsoft.azure.toolkit.lib.common.messager.AzureMessager; +import com.microsoft.azure.toolkit.lib.common.utils.Utils; +import org.apache.commons.io.FilenameUtils; +import org.apache.commons.lang3.ObjectUtils; +import org.apache.commons.lang3.StringUtils; import org.apache.maven.artifact.versioning.ComparableVersion; import org.apache.maven.plugins.annotations.LifecyclePhase; import org.apache.maven.plugins.annotations.Mojo; +import java.io.File; import java.util.List; import static com.microsoft.azure.toolkit.lib.appservice.utils.AppServiceConfigUtils.fromAppService; @@ -75,7 +80,18 @@ private IWebAppBase createOrUpdateResource() throws AzureExecutionException { } private AppServiceConfig buildDefaultConfig(String subscriptionId, String resourceGroup, String appName) { - final ComparableVersion javaVersionForProject = new ComparableVersion(System.getProperty("java.version")); + ComparableVersion javaVersionForProject = null; + final String outputFileName = project.getBuild().getFinalName() + "." + project.getPackaging(); + File outputFile = new File(project.getBuild().getDirectory(), outputFileName); + if (outputFile.exists() && StringUtils.equalsIgnoreCase("jar", FilenameUtils.getExtension(outputFile.getName()))) { + try { + javaVersionForProject = new ComparableVersion(Utils.getArtifactCompileVersion(outputFile)); + } catch (Exception e) { + // it is acceptable that java version from jar file cannot be retrieved + } + } + + javaVersionForProject = ObjectUtils.firstNonNull(javaVersionForProject, new ComparableVersion(System.getProperty("java.version"))); // get java version according to project java version JavaVersion javaVersion = javaVersionForProject.compareTo(new ComparableVersion("9")) < 0 ? JavaVersion.JAVA_8 : JavaVersion.JAVA_11; return AppServiceConfigUtils.buildDefaultConfig(subscriptionId, resourceGroup, appName, this.project.getPackaging(), javaVersion); From d29f830131703220895e7bb1a68ce930a1da8b10 Mon Sep 17 00:00:00 2001 From: andxu Date: Wed, 22 Sep 2021 13:23:07 +0800 Subject: [PATCH 080/126] rename local variable name --- .../utils/AppServiceConfigUtils.java | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/utils/AppServiceConfigUtils.java b/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/utils/AppServiceConfigUtils.java index 917f7e45c6..e658d384b2 100644 --- a/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/utils/AppServiceConfigUtils.java +++ b/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/utils/AppServiceConfigUtils.java @@ -27,33 +27,33 @@ public class AppServiceConfigUtils { private static final String SETTING_DOCKER_IMAGE = "DOCKER_CUSTOM_IMAGE_NAME"; private static final String SETTING_REGISTRY_SERVER = "DOCKER_REGISTRY_SERVER_URL"; - public static AppServiceConfig fromAppService(IAppService webapp, IAppServicePlan servicePlan) { + public static AppServiceConfig fromAppService(IAppService appService, IAppServicePlan servicePlan) { AppServiceConfig config = new AppServiceConfig(); - config.appName(webapp.name()); + config.appName(appService.name()); - config.resourceGroup(webapp.entity().getResourceGroup()); - config.subscriptionId(Utils.getSubscriptionId(webapp.id())); - config.region(webapp.entity().getRegion()); + config.resourceGroup(appService.entity().getResourceGroup()); + config.subscriptionId(Utils.getSubscriptionId(appService.id())); + config.region(appService.entity().getRegion()); config.pricingTier(servicePlan.entity().getPricingTier()); RuntimeConfig runtimeConfig = new RuntimeConfig(); - if (AppServiceUtils.isDockerAppService(webapp)) { + if (AppServiceUtils.isDockerAppService(appService)) { runtimeConfig.os(OperatingSystem.DOCKER); - final Map settings = webapp.entity().getAppSettings(); + final Map settings = appService.entity().getAppSettings(); final String imageSetting = settings.get(SETTING_DOCKER_IMAGE); if (StringUtils.isNotBlank(imageSetting)) { runtimeConfig.image(imageSetting); } else { - runtimeConfig.image(webapp.entity().getDockerImageName()); + runtimeConfig.image(appService.entity().getDockerImageName()); } final String registryServerSetting = settings.get(SETTING_REGISTRY_SERVER); if (StringUtils.isNotBlank(registryServerSetting)) { runtimeConfig.registryUrl(registryServerSetting); } } else { - runtimeConfig.os(webapp.getRuntime().getOperatingSystem()); - runtimeConfig.webContainer(webapp.getRuntime().getWebContainer()); - runtimeConfig.javaVersion(webapp.getRuntime().getJavaVersion()); + runtimeConfig.os(appService.getRuntime().getOperatingSystem()); + runtimeConfig.webContainer(appService.getRuntime().getWebContainer()); + runtimeConfig.javaVersion(appService.getRuntime().getJavaVersion()); } config.runtime(runtimeConfig); if (servicePlan.entity() != null) { From de3743ff1af436c1a05a58a1231a7ec5644eb581 Mon Sep 17 00:00:00 2001 From: andxu Date: Wed, 22 Sep 2021 13:53:30 +0800 Subject: [PATCH 081/126] address code review comments --- .../main/java/com/microsoft/azure/maven/webapp/DeployMojo.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/azure-webapp-maven-plugin/src/main/java/com/microsoft/azure/maven/webapp/DeployMojo.java b/azure-webapp-maven-plugin/src/main/java/com/microsoft/azure/maven/webapp/DeployMojo.java index 787bcb20e0..3fef713667 100644 --- a/azure-webapp-maven-plugin/src/main/java/com/microsoft/azure/maven/webapp/DeployMojo.java +++ b/azure-webapp-maven-plugin/src/main/java/com/microsoft/azure/maven/webapp/DeployMojo.java @@ -25,7 +25,6 @@ import com.microsoft.azure.toolkit.lib.common.exception.AzureExecutionException; import com.microsoft.azure.toolkit.lib.common.messager.AzureMessager; import com.microsoft.azure.toolkit.lib.common.utils.Utils; -import org.apache.commons.io.FilenameUtils; import org.apache.commons.lang3.ObjectUtils; import org.apache.commons.lang3.StringUtils; import org.apache.maven.artifact.versioning.ComparableVersion; @@ -83,7 +82,7 @@ private AppServiceConfig buildDefaultConfig(String subscriptionId, String resour ComparableVersion javaVersionForProject = null; final String outputFileName = project.getBuild().getFinalName() + "." + project.getPackaging(); File outputFile = new File(project.getBuild().getDirectory(), outputFileName); - if (outputFile.exists() && StringUtils.equalsIgnoreCase("jar", FilenameUtils.getExtension(outputFile.getName()))) { + if (outputFile.exists() && StringUtils.equalsIgnoreCase("jar", project.getPackaging())) { try { javaVersionForProject = new ComparableVersion(Utils.getArtifactCompileVersion(outputFile)); } catch (Exception e) { From 7ca6e1c2e394be2ae43baf9dea424d4d1895efb3 Mon Sep 17 00:00:00 2001 From: andxu Date: Wed, 22 Sep 2021 13:46:57 +0800 Subject: [PATCH 082/126] add default value for functions --- .../azure/maven/function/DeployMojo.java | 45 +++++++++++++++++ .../task/CreateOrUpdateFunctionAppTask.java | 50 +++---------------- .../utils/AppServiceConfigUtils.java | 24 ++++----- .../toolkit/lib/appservice/utils/Utils.java | 13 +++++ .../azure/maven/webapp/DeployMojo.java | 2 +- 5 files changed, 78 insertions(+), 56 deletions(-) diff --git a/azure-functions-maven-plugin/src/main/java/com/microsoft/azure/maven/function/DeployMojo.java b/azure-functions-maven-plugin/src/main/java/com/microsoft/azure/maven/function/DeployMojo.java index 7f1d3baf5d..da4d8d036f 100644 --- a/azure-functions-maven-plugin/src/main/java/com/microsoft/azure/maven/function/DeployMojo.java +++ b/azure-functions-maven-plugin/src/main/java/com/microsoft/azure/maven/function/DeployMojo.java @@ -5,15 +5,20 @@ package com.microsoft.azure.maven.function; +import com.microsoft.azure.toolkit.lib.Azure; +import com.microsoft.azure.toolkit.lib.appservice.AzureAppService; +import com.microsoft.azure.toolkit.lib.appservice.config.AppServiceConfig; import com.microsoft.azure.toolkit.lib.appservice.config.FunctionAppConfig; import com.microsoft.azure.toolkit.lib.appservice.config.RuntimeConfig; 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.OperatingSystem; import com.microsoft.azure.toolkit.lib.appservice.model.PricingTier; +import com.microsoft.azure.toolkit.lib.appservice.service.IFunctionApp; import com.microsoft.azure.toolkit.lib.appservice.service.IFunctionAppBase; import com.microsoft.azure.toolkit.lib.appservice.task.CreateOrUpdateFunctionAppTask; import com.microsoft.azure.toolkit.lib.appservice.task.DeployFunctionAppTask; +import com.microsoft.azure.toolkit.lib.appservice.utils.AppServiceConfigUtils; import com.microsoft.azure.toolkit.lib.common.bundle.AzureString; import com.microsoft.azure.toolkit.lib.common.exception.AzureExecutionException; import com.microsoft.azure.toolkit.lib.common.exception.AzureToolkitRuntimeException; @@ -21,6 +26,7 @@ import com.microsoft.azure.toolkit.lib.common.model.Region; import com.microsoft.azure.toolkit.lib.common.utils.Utils; import org.apache.commons.io.FilenameUtils; +import org.apache.commons.lang3.ObjectUtils; import org.apache.commons.lang3.StringUtils; import org.apache.maven.artifact.versioning.ComparableVersion; import org.apache.maven.plugins.annotations.LifecyclePhase; @@ -30,6 +36,9 @@ import java.util.Arrays; import java.util.Optional; +import static com.microsoft.azure.toolkit.lib.appservice.utils.AppServiceConfigUtils.fromAppService; +import static com.microsoft.azure.toolkit.lib.appservice.utils.AppServiceConfigUtils.mergeAppServiceConfig; + /** * Deploy artifacts to target Azure Functions in Azure. If target Azure Functions doesn't exist, it will be created. */ @@ -135,9 +144,45 @@ protected void validateParameters() { } protected IFunctionAppBase createOrUpdateResource(final FunctionAppConfig config) { + IFunctionApp app = Azure.az(AzureAppService.class).functionApp(config.resourceGroup(), config.appName()); + final boolean newFunctionApp = !app.exists(); + AppServiceConfig defaultConfig = !newFunctionApp ? fromAppService(app, app.plan()) : buildDefaultConfig(config.subscriptionId(), + config.resourceGroup(), config.appName()); + + mergeAppServiceConfig(config, defaultConfig); + if (config.pricingTier() == null) { + config.pricingTier(PricingTier.CONSUMPTION); + } + try { + com.microsoft.azure.toolkit.lib.appservice.utils.Utils.mergeObjects(config, defaultConfig); + } catch (IllegalAccessException e) { + throw new AzureToolkitRuntimeException("Cannot copy object for class AppServiceConfig.", e); + } + if (!newFunctionApp && !config.disableAppInsights()) { + // fill ai key from existing app settings + config.appInsightsKey(app.entity().getAppSettings().get(CreateOrUpdateFunctionAppTask.APPINSIGHTS_INSTRUMENTATION_KEY)); + } return new CreateOrUpdateFunctionAppTask(config).execute(); } + private AppServiceConfig buildDefaultConfig(String subscriptionId, String resourceGroup, String appName) { + ComparableVersion javaVersionForProject = null; + final String outputFileName = project.getBuild().getFinalName() + "." + project.getPackaging(); + File outputFile = new File(project.getBuild().getDirectory(), outputFileName); + if (outputFile.exists() && StringUtils.equalsIgnoreCase("jar", FilenameUtils.getExtension(outputFile.getName()))) { + try { + javaVersionForProject = new ComparableVersion(Utils.getArtifactCompileVersion(outputFile)); + } catch (Exception e) { + // it is acceptable that java version from jar file cannot be retrieved + } + } + + javaVersionForProject = ObjectUtils.firstNonNull(javaVersionForProject, new ComparableVersion(System.getProperty("java.version"))); + // get java version according to project java version + JavaVersion javaVersion = javaVersionForProject.compareTo(new ComparableVersion("9")) < 0 ? JavaVersion.JAVA_8 : JavaVersion.JAVA_11; + return AppServiceConfigUtils.buildDefaultFunctionConfig(subscriptionId, resourceGroup, appName, javaVersion); + } + private void deployArtifact(final IFunctionAppBase target) { final File file = new File(getDeploymentStagingDirectoryPath()); final FunctionDeployType type = StringUtils.isEmpty(deploymentType) ? null : FunctionDeployType.fromString(deploymentType); diff --git a/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/task/CreateOrUpdateFunctionAppTask.java b/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/task/CreateOrUpdateFunctionAppTask.java index 269ef08cea..c883c4b117 100644 --- a/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/task/CreateOrUpdateFunctionAppTask.java +++ b/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/task/CreateOrUpdateFunctionAppTask.java @@ -9,13 +9,11 @@ import com.microsoft.azure.toolkit.lib.applicationinsights.ApplicationInsightsEntity; import com.microsoft.azure.toolkit.lib.applicationinsights.task.GetOrCreateApplicationInsightsTask; import com.microsoft.azure.toolkit.lib.appservice.AzureAppService; -import com.microsoft.azure.toolkit.lib.appservice.config.AppServicePlanConfig; import com.microsoft.azure.toolkit.lib.appservice.config.FunctionAppConfig; import com.microsoft.azure.toolkit.lib.appservice.config.RuntimeConfig; import com.microsoft.azure.toolkit.lib.appservice.model.DockerConfiguration; 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.PricingTier; import com.microsoft.azure.toolkit.lib.appservice.model.Runtime; import com.microsoft.azure.toolkit.lib.appservice.model.WebContainer; import com.microsoft.azure.toolkit.lib.appservice.service.IAppServicePlan; @@ -26,7 +24,6 @@ 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.Region; import com.microsoft.azure.toolkit.lib.common.model.ResourceGroup; import com.microsoft.azure.toolkit.lib.common.task.AzureTask; import com.microsoft.azure.toolkit.lib.common.telemetry.AzureTelemetry; @@ -41,7 +38,7 @@ import java.util.function.Consumer; public class CreateOrUpdateFunctionAppTask extends AzureTask> { - private static final String APPINSIGHTS_INSTRUMENTATION_KEY = "APPINSIGHTS_INSTRUMENTATIONKEY"; + public static final String APPINSIGHTS_INSTRUMENTATION_KEY = "APPINSIGHTS_INSTRUMENTATIONKEY"; private static final String APPLICATION_INSIGHTS_CREATE_FAILED = "Unable to create the Application Insights " + "for the Function App due to error %s. Please use the Azure Portal to manually create and configure the " + "Application Insights if needed."; @@ -68,9 +65,6 @@ public class CreateOrUpdateFunctionAppTask extends AzureTask private static final String FUNCTION_SLOT_UPDATE_DONE = "Successfully updated the function slot: %s."; public static final JavaVersion DEFAULT_FUNCTION_JAVA_VERSION = JavaVersion.JAVA_8; - public static final OperatingSystem DEFAULT_FUNCTION_OS = OperatingSystem.WINDOWS; - public static final PricingTier DEFAULT_FUNCTION_PRICING = PricingTier.CONSUMPTION; - public static final Region DEFAULT_FUNCTION_REGION = Region.US_WEST; private final FunctionAppConfig functionAppConfig; private final List> tasks = new ArrayList<>(); @@ -83,30 +77,14 @@ public class CreateOrUpdateFunctionAppTask extends AzureTask public CreateOrUpdateFunctionAppTask(@Nonnull final FunctionAppConfig config) { this.functionAppConfig = config; - normalizeConfiguration(config); initTasks(); } - private void normalizeConfiguration(FunctionAppConfig config) { - if (config.region() == null) { - config.region(DEFAULT_FUNCTION_REGION); - } - if (config.pricingTier() == null) { - config.pricingTier(DEFAULT_FUNCTION_PRICING); - } - if (config.runtime() != null && config.runtime().os() == null) { - config.runtime().os(DEFAULT_FUNCTION_OS); - } - if (config.runtime() != null && config.runtime().javaVersion() == null) { - config.runtime().javaVersion(DEFAULT_FUNCTION_JAVA_VERSION); - } - } - private void initTasks() { final IFunctionApp functionApp = Azure.az(AzureAppService.class).subscription(functionAppConfig.subscriptionId()) .functionApp(functionAppConfig.resourceGroup(), functionAppConfig.appName()); registerSubTask(getResourceGroupTask(), result -> this.resourceGroup = result); - registerSubTask(getServicePlanTask(functionApp), result -> this.appServicePlan = result); + registerSubTask(getServicePlanTask(), result -> this.appServicePlan = result); // get/create ai instances only if user didn't specify ai connection string in app settings if (!functionAppConfig.disableAppInsights() && !functionAppConfig.appSettings().containsKey(APPINSIGHTS_INSTRUMENTATION_KEY)) { if (StringUtils.isNotEmpty(functionAppConfig.appInsightsKey())) { @@ -259,31 +237,19 @@ private CreateResourceGroupTask getResourceGroupTask() { return new CreateResourceGroupTask(functionAppConfig.subscriptionId(), functionAppConfig.resourceGroup(), functionAppConfig.region()); } - private CreateOrUpdateAppServicePlanTask getServicePlanTask(final IFunctionApp functionApp) { - final String servicePlanName = functionApp.exists() ? functionApp.plan().name() : - StringUtils.firstNonBlank(functionAppConfig.servicePlanName(), String.format("asp-%s", functionAppConfig.appName())); - final String servicePlanGroup = functionApp.exists() ? functionApp.plan().resourceGroup() : - StringUtils.firstNonBlank(functionAppConfig.resourceGroup(), functionAppConfig.servicePlanResourceGroup()); - final AppServicePlanConfig servicePlanConfig = functionAppConfig.getServicePlanConfig().servicePlanName(servicePlanName) - .servicePlanResourceGroup(servicePlanGroup); - return new CreateOrUpdateAppServicePlanTask(servicePlanConfig); + private CreateOrUpdateAppServicePlanTask getServicePlanTask() { + return new CreateOrUpdateAppServicePlanTask(functionAppConfig.getServicePlanConfig()); } - // todo: remove duplicated with Create Web App Task private Runtime getRuntime(RuntimeConfig runtime) { - if (runtime != null && OperatingSystem.DOCKER != runtime.os()) { - return Runtime.getRuntime(runtime.os(), - runtime.webContainer(), - runtime.javaVersion()); - } else if (runtime != null && OperatingSystem.DOCKER == runtime.os()) { - return Runtime.getRuntime(OperatingSystem.DOCKER, WebContainer.JAVA_OFF, JavaVersion.OFF); - } - return null; + return Runtime.getRuntime(runtime.os(), + WebContainer.JAVA_OFF, + OperatingSystem.DOCKER != runtime.os() ? runtime.javaVersion() : JavaVersion.OFF); } // todo: remove duplicated with Create Web App Task private DockerConfiguration getDockerConfiguration(RuntimeConfig runtime) { - if (runtime != null && OperatingSystem.DOCKER == runtime.os()) { + if (OperatingSystem.DOCKER == runtime.os()) { return DockerConfiguration.builder() .userName(runtime.username()) .password(runtime.password()) diff --git a/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/utils/AppServiceConfigUtils.java b/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/utils/AppServiceConfigUtils.java index e658d384b2..0eced85ded 100644 --- a/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/utils/AppServiceConfigUtils.java +++ b/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/utils/AppServiceConfigUtils.java @@ -23,6 +23,8 @@ import java.util.List; import java.util.Map; +import static com.microsoft.azure.toolkit.lib.appservice.utils.Utils.mergeObjects; + public class AppServiceConfigUtils { private static final String SETTING_DOCKER_IMAGE = "DOCKER_CUSTOM_IMAGE_NAME"; private static final String SETTING_REGISTRY_SERVER = "DOCKER_REGISTRY_SERVER_URL"; @@ -64,7 +66,7 @@ public static AppServiceConfig fromAppService(IAppService appService, IAppSer return config; } - public static AppServiceConfig buildDefaultConfig(String subscriptionId, String resourceGroup, String appName, String packaging, JavaVersion javaVersion) { + public static AppServiceConfig buildDefaultWebAppConfig(String subscriptionId, String resourceGroup, String appName, String packaging, JavaVersion javaVersion) { final AppServiceConfig appServiceConfig = AppServiceConfig.buildDefaultWebAppConfig(resourceGroup, appName, packaging, javaVersion); final List regions = Azure.az(AzureAppService.class).listSupportedRegions(subscriptionId); // replace with first region when the default region is not present @@ -72,6 +74,14 @@ public static AppServiceConfig buildDefaultConfig(String subscriptionId, String return appServiceConfig; } + public static AppServiceConfig buildDefaultFunctionConfig(String subscriptionId, String resourceGroup, String appName, JavaVersion javaVersion) { + final AppServiceConfig appServiceConfig = AppServiceConfig.buildDefaultFunctionConfig(resourceGroup, appName, javaVersion); + final List regions = Azure.az(AzureAppService.class).listSupportedRegions(subscriptionId); + // replace with first region when the default region is not present + appServiceConfig.region(Utils.selectFirstOptionIfCurrentInvalid("region", regions, appServiceConfig.region())); + return appServiceConfig; + } + public static void mergeAppServiceConfig(AppServiceConfig to, AppServiceConfig from) { try { mergeObjects(to, from); @@ -91,16 +101,4 @@ private static void mergeRuntime(RuntimeConfig to, RuntimeConfig from) { throw new AzureToolkitRuntimeException("Cannot copy object for class RuntimeConfig.", e); } } - - private static void mergeObjects(T to, T from) throws IllegalAccessException { - for (Field field : FieldUtils.getAllFields(to.getClass())) { - if (FieldUtils.readField(field, to, true) == null) { - final Object value = FieldUtils.readField(field, from, true); - if (value != null) { - FieldUtils.writeField(field, to, value, true); - } - } - - } - } } diff --git a/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/utils/Utils.java b/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/utils/Utils.java index 8a30408615..fe76999695 100644 --- a/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/utils/Utils.java +++ b/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/utils/Utils.java @@ -12,10 +12,12 @@ import com.microsoft.azure.toolkit.lib.common.exception.AzureToolkitRuntimeException; import org.apache.commons.io.FilenameUtils; import org.apache.commons.lang3.StringUtils; +import org.apache.commons.lang3.reflect.FieldUtils; import javax.annotation.Nonnull; import javax.annotation.Nullable; import java.io.File; +import java.lang.reflect.Field; import java.util.ArrayList; import java.util.List; import java.util.Map; @@ -67,4 +69,15 @@ public static T selectFirstOptionIfCurrentInvalid(String name, List optio } return options.contains(value) ? value : options.get(0); } + + public static void mergeObjects(T to, T from) throws IllegalAccessException { + for (Field field : FieldUtils.getAllFields(from.getClass())) { + if (FieldUtils.readField(field, to, true) == null) { + final Object value = FieldUtils.readField(field, from, true); + if (value != null) { + FieldUtils.writeField(field, to, value, true); + } + } + } + } } diff --git a/azure-webapp-maven-plugin/src/main/java/com/microsoft/azure/maven/webapp/DeployMojo.java b/azure-webapp-maven-plugin/src/main/java/com/microsoft/azure/maven/webapp/DeployMojo.java index 3fef713667..6344a1304e 100644 --- a/azure-webapp-maven-plugin/src/main/java/com/microsoft/azure/maven/webapp/DeployMojo.java +++ b/azure-webapp-maven-plugin/src/main/java/com/microsoft/azure/maven/webapp/DeployMojo.java @@ -93,7 +93,7 @@ private AppServiceConfig buildDefaultConfig(String subscriptionId, String resour javaVersionForProject = ObjectUtils.firstNonNull(javaVersionForProject, new ComparableVersion(System.getProperty("java.version"))); // get java version according to project java version JavaVersion javaVersion = javaVersionForProject.compareTo(new ComparableVersion("9")) < 0 ? JavaVersion.JAVA_8 : JavaVersion.JAVA_11; - return AppServiceConfigUtils.buildDefaultConfig(subscriptionId, resourceGroup, appName, this.project.getPackaging(), javaVersion); + return AppServiceConfigUtils.buildDefaultWebAppConfig(subscriptionId, resourceGroup, appName, this.project.getPackaging(), javaVersion); } private IWebAppDeploymentSlot getDeploymentSlot(final DeploymentSlotConfig config) throws AzureExecutionException { From 73202c43c44e9b5f4cc3c7eb630941774ac55e8e Mon Sep 17 00:00:00 2001 From: andxu Date: Wed, 22 Sep 2021 14:33:12 +0800 Subject: [PATCH 083/126] Remove azure-resourcemanager --- .../toolkit/lib/applicationinsights/ApplicationInsights.java | 4 ++-- azure-toolkit-libs/azure-toolkit-auth-lib/pom.xml | 5 ----- 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/azure-toolkit-libs/azure-toolkit-applicationinsights-lib/src/main/java/com/microsoft/azure/toolkit/lib/applicationinsights/ApplicationInsights.java b/azure-toolkit-libs/azure-toolkit-applicationinsights-lib/src/main/java/com/microsoft/azure/toolkit/lib/applicationinsights/ApplicationInsights.java index 860e6acd4c..61a6dc6df3 100644 --- a/azure-toolkit-libs/azure-toolkit-applicationinsights-lib/src/main/java/com/microsoft/azure/toolkit/lib/applicationinsights/ApplicationInsights.java +++ b/azure-toolkit-libs/azure-toolkit-applicationinsights-lib/src/main/java/com/microsoft/azure/toolkit/lib/applicationinsights/ApplicationInsights.java @@ -9,10 +9,10 @@ import com.azure.core.http.policy.HttpPipelinePolicy; import com.azure.core.management.exception.ManagementException; import com.azure.core.management.profile.AzureProfile; -import com.azure.resourcemanager.AzureResourceManager; import com.azure.resourcemanager.applicationinsights.ApplicationInsightsManager; import com.azure.resourcemanager.applicationinsights.models.ApplicationInsightsComponent; import com.azure.resourcemanager.applicationinsights.models.ApplicationType; +import com.azure.resourcemanager.resources.ResourceManager; import com.azure.resourcemanager.resources.fluentcore.arm.ResourceId; import com.azure.resourcemanager.resources.fluentcore.policy.ProviderRegistrationPolicy; import com.azure.resourcemanager.resources.models.Providers; @@ -108,7 +108,7 @@ private ApplicationInsightsManager getApplicationInsightsManager(String subscrip logOptions.setLogLevel(Optional.ofNullable(config.getLogLevel()).map(HttpLogDetailLevel::valueOf).orElse(HttpLogDetailLevel.NONE)); final AzureProfile azureProfile = new AzureProfile(tenantId, subscriptionId, account.getEnvironment()); // todo: migrate resource provider related codes to common library - final Providers providers = AzureResourceManager.configure() + final Providers providers = ResourceManager.configure() .withPolicy(getUserAgentPolicy(userAgent)) .authenticate(account.getTokenCredential(subscriptionId), azureProfile) .withSubscription(subscriptionId).providers(); diff --git a/azure-toolkit-libs/azure-toolkit-auth-lib/pom.xml b/azure-toolkit-libs/azure-toolkit-auth-lib/pom.xml index 1ed4c28cfe..724784e5c1 100644 --- a/azure-toolkit-libs/azure-toolkit-auth-lib/pom.xml +++ b/azure-toolkit-libs/azure-toolkit-auth-lib/pom.xml @@ -63,11 +63,6 @@ com.microsoft.azure azure-client-runtime - - com.azure.resourcemanager - azure-resourcemanager - - com.azure azure-identity From 3d8e92eff2659c63699ab383b98f1edaef02c831 Mon Sep 17 00:00:00 2001 From: andxu Date: Wed, 22 Sep 2021 14:37:59 +0800 Subject: [PATCH 084/126] Fix check style problems --- .../toolkit/lib/appservice/utils/AppServiceConfigUtils.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/utils/AppServiceConfigUtils.java b/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/utils/AppServiceConfigUtils.java index 0eced85ded..f8632104b2 100644 --- a/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/utils/AppServiceConfigUtils.java +++ b/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/utils/AppServiceConfigUtils.java @@ -17,9 +17,7 @@ import com.microsoft.azure.toolkit.lib.common.model.Region; import com.microsoft.azure.toolkit.lib.legacy.appservice.AppServiceUtils; import org.apache.commons.lang3.StringUtils; -import org.apache.commons.lang3.reflect.FieldUtils; -import java.lang.reflect.Field; import java.util.List; import java.util.Map; From f05d45990390a2ab243f2d94e3776a93c63d6d3b Mon Sep 17 00:00:00 2001 From: andxu Date: Wed, 22 Sep 2021 15:26:45 +0800 Subject: [PATCH 085/126] remove useless code --- .../java/com/microsoft/azure/maven/function/DeployMojo.java | 5 ----- 1 file changed, 5 deletions(-) diff --git a/azure-functions-maven-plugin/src/main/java/com/microsoft/azure/maven/function/DeployMojo.java b/azure-functions-maven-plugin/src/main/java/com/microsoft/azure/maven/function/DeployMojo.java index da4d8d036f..45135e4344 100644 --- a/azure-functions-maven-plugin/src/main/java/com/microsoft/azure/maven/function/DeployMojo.java +++ b/azure-functions-maven-plugin/src/main/java/com/microsoft/azure/maven/function/DeployMojo.java @@ -153,11 +153,6 @@ protected IFunctionAppBase createOrUpdateResource(final FunctionAppConfig con if (config.pricingTier() == null) { config.pricingTier(PricingTier.CONSUMPTION); } - try { - com.microsoft.azure.toolkit.lib.appservice.utils.Utils.mergeObjects(config, defaultConfig); - } catch (IllegalAccessException e) { - throw new AzureToolkitRuntimeException("Cannot copy object for class AppServiceConfig.", e); - } if (!newFunctionApp && !config.disableAppInsights()) { // fill ai key from existing app settings config.appInsightsKey(app.entity().getAppSettings().get(CreateOrUpdateFunctionAppTask.APPINSIGHTS_INSTRUMENTATION_KEY)); From 27c4757b891d379b6474f21e2a9dbc0f96cc6178 Mon Sep 17 00:00:00 2001 From: Mingliang Wang Date: Wed, 22 Sep 2021 16:00:23 +0800 Subject: [PATCH 086/126] fix warnings --- azure-toolkit-libs/pom.xml | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/azure-toolkit-libs/pom.xml b/azure-toolkit-libs/pom.xml index 159686b021..a6250139df 100644 --- a/azure-toolkit-libs/pom.xml +++ b/azure-toolkit-libs/pom.xml @@ -68,9 +68,7 @@ 1.6.7 2.6.3 [2.0,) - 1.0.0-beta 1.0.0-beta.1 - 1.0.0-beta 1.7.12 1.3.0 2.5.0 @@ -111,7 +109,7 @@ 2.3.2 21.0.1 2.2.14 - 2.5.14 + 3.0.9 4.13.2 1.18.20 3.10.0 @@ -315,11 +313,6 @@ azure-security-keyvault-certificates ${azure.security.keyvault.certificates.version} - - com.microsoft.azure.appplatform.v2020_07_01 - azure-mgmt-appplatform - ${azure.azure-mgmt-appplatform.version} - com.azure azure-core-http-netty From 0ea32d5c3f10040b1275c34e4c47282e570df77b Mon Sep 17 00:00:00 2001 From: andxu Date: Wed, 22 Sep 2021 17:01:12 +0800 Subject: [PATCH 087/126] Bump version for september endgame --- .../azure-toolkit-applicationinsights-lib/pom.xml | 2 +- azure-toolkit-libs/azure-toolkit-appservice-lib/pom.xml | 2 +- azure-toolkit-libs/azure-toolkit-auth-lib/pom.xml | 2 +- azure-toolkit-libs/azure-toolkit-common-lib/pom.xml | 2 +- azure-toolkit-libs/azure-toolkit-compute-lib/pom.xml | 4 ++-- azure-toolkit-libs/azure-toolkit-database-lib/pom.xml | 4 ++-- azure-toolkit-libs/azure-toolkit-mysql-lib/pom.xml | 2 +- azure-toolkit-libs/azure-toolkit-redis-lib/pom.xml | 2 +- azure-toolkit-libs/azure-toolkit-resource-lib/pom.xml | 2 +- azure-toolkit-libs/azure-toolkit-springcloud-lib/pom.xml | 2 +- azure-toolkit-libs/azure-toolkit-sqlserver-lib/pom.xml | 2 +- azure-toolkit-libs/azure-toolkit-storage-lib/pom.xml | 4 ++-- azure-toolkit-libs/pom.xml | 2 +- pom.xml | 2 +- 14 files changed, 17 insertions(+), 17 deletions(-) diff --git a/azure-toolkit-libs/azure-toolkit-applicationinsights-lib/pom.xml b/azure-toolkit-libs/azure-toolkit-applicationinsights-lib/pom.xml index 6eed0ab520..13cfeb3cf0 100644 --- a/azure-toolkit-libs/azure-toolkit-applicationinsights-lib/pom.xml +++ b/azure-toolkit-libs/azure-toolkit-applicationinsights-lib/pom.xml @@ -5,7 +5,7 @@ azure-toolkit-libs com.microsoft.azure - 0.12.0-SNAPSHOT + 0.12.0 4.0.0 diff --git a/azure-toolkit-libs/azure-toolkit-appservice-lib/pom.xml b/azure-toolkit-libs/azure-toolkit-appservice-lib/pom.xml index 37d4670eb6..16b9d64e39 100644 --- a/azure-toolkit-libs/azure-toolkit-appservice-lib/pom.xml +++ b/azure-toolkit-libs/azure-toolkit-appservice-lib/pom.xml @@ -5,7 +5,7 @@ azure-toolkit-libs com.microsoft.azure - 0.12.0-SNAPSHOT + 0.12.0 4.0.0 diff --git a/azure-toolkit-libs/azure-toolkit-auth-lib/pom.xml b/azure-toolkit-libs/azure-toolkit-auth-lib/pom.xml index 1ed4c28cfe..d21938a95d 100644 --- a/azure-toolkit-libs/azure-toolkit-auth-lib/pom.xml +++ b/azure-toolkit-libs/azure-toolkit-auth-lib/pom.xml @@ -5,7 +5,7 @@ azure-toolkit-libs com.microsoft.azure - 0.12.0-SNAPSHOT + 0.12.0 4.0.0 diff --git a/azure-toolkit-libs/azure-toolkit-common-lib/pom.xml b/azure-toolkit-libs/azure-toolkit-common-lib/pom.xml index 4991c938e1..c1ff7baaf0 100644 --- a/azure-toolkit-libs/azure-toolkit-common-lib/pom.xml +++ b/azure-toolkit-libs/azure-toolkit-common-lib/pom.xml @@ -5,7 +5,7 @@ azure-toolkit-libs com.microsoft.azure - 0.12.0-SNAPSHOT + 0.12.0 4.0.0 diff --git a/azure-toolkit-libs/azure-toolkit-compute-lib/pom.xml b/azure-toolkit-libs/azure-toolkit-compute-lib/pom.xml index 321729b10d..eec7cf3fda 100644 --- a/azure-toolkit-libs/azure-toolkit-compute-lib/pom.xml +++ b/azure-toolkit-libs/azure-toolkit-compute-lib/pom.xml @@ -5,7 +5,7 @@ azure-toolkit-libs com.microsoft.azure - 0.12.0-SNAPSHOT + 0.12.0 4.0.0 @@ -118,4 +118,4 @@ - \ No newline at end of file + diff --git a/azure-toolkit-libs/azure-toolkit-database-lib/pom.xml b/azure-toolkit-libs/azure-toolkit-database-lib/pom.xml index d0e4795945..f219206325 100644 --- a/azure-toolkit-libs/azure-toolkit-database-lib/pom.xml +++ b/azure-toolkit-libs/azure-toolkit-database-lib/pom.xml @@ -5,7 +5,7 @@ azure-toolkit-libs com.microsoft.azure - 0.12.0-SNAPSHOT + 0.12.0 4.0.0 @@ -107,4 +107,4 @@
    - \ No newline at end of file + diff --git a/azure-toolkit-libs/azure-toolkit-mysql-lib/pom.xml b/azure-toolkit-libs/azure-toolkit-mysql-lib/pom.xml index c6c987658a..29b0269f30 100644 --- a/azure-toolkit-libs/azure-toolkit-mysql-lib/pom.xml +++ b/azure-toolkit-libs/azure-toolkit-mysql-lib/pom.xml @@ -5,7 +5,7 @@ azure-toolkit-libs com.microsoft.azure - 0.12.0-SNAPSHOT + 0.12.0 4.0.0 diff --git a/azure-toolkit-libs/azure-toolkit-redis-lib/pom.xml b/azure-toolkit-libs/azure-toolkit-redis-lib/pom.xml index bf83c2cdf6..3ed7b5812a 100644 --- a/azure-toolkit-libs/azure-toolkit-redis-lib/pom.xml +++ b/azure-toolkit-libs/azure-toolkit-redis-lib/pom.xml @@ -5,7 +5,7 @@ azure-toolkit-libs com.microsoft.azure - 0.12.0-SNAPSHOT + 0.12.0 4.0.0 diff --git a/azure-toolkit-libs/azure-toolkit-resource-lib/pom.xml b/azure-toolkit-libs/azure-toolkit-resource-lib/pom.xml index 03a793bf8b..eb8c61be08 100644 --- a/azure-toolkit-libs/azure-toolkit-resource-lib/pom.xml +++ b/azure-toolkit-libs/azure-toolkit-resource-lib/pom.xml @@ -5,7 +5,7 @@ azure-toolkit-libs com.microsoft.azure - 0.12.0-SNAPSHOT + 0.12.0 4.0.0 diff --git a/azure-toolkit-libs/azure-toolkit-springcloud-lib/pom.xml b/azure-toolkit-libs/azure-toolkit-springcloud-lib/pom.xml index cfd6da4a3f..d9735fdb5b 100644 --- a/azure-toolkit-libs/azure-toolkit-springcloud-lib/pom.xml +++ b/azure-toolkit-libs/azure-toolkit-springcloud-lib/pom.xml @@ -5,7 +5,7 @@ azure-toolkit-libs com.microsoft.azure - 0.12.0-SNAPSHOT + 0.12.0 4.0.0 diff --git a/azure-toolkit-libs/azure-toolkit-sqlserver-lib/pom.xml b/azure-toolkit-libs/azure-toolkit-sqlserver-lib/pom.xml index 86dd0d0551..c48aeced71 100644 --- a/azure-toolkit-libs/azure-toolkit-sqlserver-lib/pom.xml +++ b/azure-toolkit-libs/azure-toolkit-sqlserver-lib/pom.xml @@ -5,7 +5,7 @@ azure-toolkit-libs com.microsoft.azure - 0.12.0-SNAPSHOT + 0.12.0 4.0.0 diff --git a/azure-toolkit-libs/azure-toolkit-storage-lib/pom.xml b/azure-toolkit-libs/azure-toolkit-storage-lib/pom.xml index c3d60c1cb0..156fdec15d 100644 --- a/azure-toolkit-libs/azure-toolkit-storage-lib/pom.xml +++ b/azure-toolkit-libs/azure-toolkit-storage-lib/pom.xml @@ -5,7 +5,7 @@ azure-toolkit-libs com.microsoft.azure - 0.12.0-SNAPSHOT + 0.12.0 4.0.0 @@ -114,4 +114,4 @@ - \ No newline at end of file + diff --git a/azure-toolkit-libs/pom.xml b/azure-toolkit-libs/pom.xml index a6250139df..f50653cbad 100644 --- a/azure-toolkit-libs/pom.xml +++ b/azure-toolkit-libs/pom.xml @@ -5,7 +5,7 @@ 4.0.0 com.microsoft.azure azure-toolkit-libs - 0.12.0-SNAPSHOT + 0.12.0 pom Libs for Azure Toolkits Wrapped libs for Microsoft Azure Toolkits diff --git a/pom.xml b/pom.xml index 8b9940d0f6..492f7eb9a8 100644 --- a/pom.xml +++ b/pom.xml @@ -92,7 +92,7 @@ com.microsoft.azure azure-toolkit-libs - 0.12.0-SNAPSHOT + 0.12.0 pom import From bab6637cca7f0d0c02a0221b34aa43e7f29e499f Mon Sep 17 00:00:00 2001 From: andxu Date: Wed, 22 Sep 2021 17:10:05 +0800 Subject: [PATCH 088/126] Bump version for september endgame --- azure-functions-maven-plugin/pom.xml | 4 ++-- azure-maven-plugin-lib/pom.xml | 2 +- azure-sfmesh-maven-plugin/pom.xml | 2 +- azure-spring-cloud-maven-plugin/pom.xml | 2 +- azure-webapp-maven-plugin/pom.xml | 4 ++-- build-tools/pom.xml | 2 +- pom.xml | 6 +++--- 7 files changed, 11 insertions(+), 11 deletions(-) diff --git a/azure-functions-maven-plugin/pom.xml b/azure-functions-maven-plugin/pom.xml index c28f476245..122b7e2ec8 100644 --- a/azure-functions-maven-plugin/pom.xml +++ b/azure-functions-maven-plugin/pom.xml @@ -6,11 +6,11 @@ com.microsoft.azure azure-maven-plugins - 1.14.0-SNAPSHOT + 1.14.0 azure-functions-maven-plugin - 1.14.0-SNAPSHOT + 1.14.0 maven-plugin Maven Plugin for Azure Functions Maven Plugin for Azure Functions diff --git a/azure-maven-plugin-lib/pom.xml b/azure-maven-plugin-lib/pom.xml index 4f5962d50a..9a055daf5a 100644 --- a/azure-maven-plugin-lib/pom.xml +++ b/azure-maven-plugin-lib/pom.xml @@ -7,7 +7,7 @@ com.microsoft.azure azure-maven-plugins - 1.14.0-SNAPSHOT + 1.14.0 azure-maven-plugin-lib diff --git a/azure-sfmesh-maven-plugin/pom.xml b/azure-sfmesh-maven-plugin/pom.xml index dc3bbf31dc..2c0aab652d 100644 --- a/azure-sfmesh-maven-plugin/pom.xml +++ b/azure-sfmesh-maven-plugin/pom.xml @@ -8,7 +8,7 @@ com.microsoft.azure azure-maven-plugins - 1.14.0-SNAPSHOT + 1.14.0 azure-sfmesh-maven-plugin diff --git a/azure-spring-cloud-maven-plugin/pom.xml b/azure-spring-cloud-maven-plugin/pom.xml index 7ee6ebe140..48b2a049b4 100644 --- a/azure-spring-cloud-maven-plugin/pom.xml +++ b/azure-spring-cloud-maven-plugin/pom.xml @@ -12,7 +12,7 @@ com.microsoft.azure azure-maven-plugins - 1.14.0-SNAPSHOT + 1.14.0 Azure Spring Cloud Maven Plugin diff --git a/azure-webapp-maven-plugin/pom.xml b/azure-webapp-maven-plugin/pom.xml index 63467a90c2..94d6a525b7 100644 --- a/azure-webapp-maven-plugin/pom.xml +++ b/azure-webapp-maven-plugin/pom.xml @@ -7,11 +7,11 @@ com.microsoft.azure azure-maven-plugins - 1.14.0-SNAPSHOT + 1.14.0 azure-webapp-maven-plugin - 2.2.0-SNAPSHOT + 2.2.0 maven-plugin Maven Plugin for Azure Web Apps Maven Plugin for Azure Web Apps diff --git a/build-tools/pom.xml b/build-tools/pom.xml index b2cfe02c71..c7f1b31307 100644 --- a/build-tools/pom.xml +++ b/build-tools/pom.xml @@ -7,7 +7,7 @@ com.microsoft.azure azure-maven-plugins - 1.14.0-SNAPSHOT + 1.14.0 maven-plugins-build-tools diff --git a/pom.xml b/pom.xml index 492f7eb9a8..3fe3531425 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ 4.0.0 com.microsoft.azure azure-maven-plugins - 1.14.0-SNAPSHOT + 1.14.0 pom Maven Plugins for Azure Maven plugins for Microsoft Azure services @@ -81,7 +81,7 @@ 2.9.1 3.1.2 - 1.14.0-SNAPSHOT + 1.14.0 0.8.7 1.0.56 @@ -253,7 +253,7 @@ com.microsoft.azure maven-plugins-build-tools - 1.14.0-SNAPSHOT + 1.14.0 com.puppycrawl.tools From 111688c162a0f403f6d3fcfbec24588ad5b1a59a Mon Sep 17 00:00:00 2001 From: andxu Date: Wed, 22 Sep 2021 17:12:12 +0800 Subject: [PATCH 089/126] remove useless code --- .../java/com/microsoft/azure/maven/function/DeployMojo.java | 4 ---- 1 file changed, 4 deletions(-) diff --git a/azure-functions-maven-plugin/src/main/java/com/microsoft/azure/maven/function/DeployMojo.java b/azure-functions-maven-plugin/src/main/java/com/microsoft/azure/maven/function/DeployMojo.java index 45135e4344..56ad9f17be 100644 --- a/azure-functions-maven-plugin/src/main/java/com/microsoft/azure/maven/function/DeployMojo.java +++ b/azure-functions-maven-plugin/src/main/java/com/microsoft/azure/maven/function/DeployMojo.java @@ -148,11 +148,7 @@ protected IFunctionAppBase createOrUpdateResource(final FunctionAppConfig con final boolean newFunctionApp = !app.exists(); AppServiceConfig defaultConfig = !newFunctionApp ? fromAppService(app, app.plan()) : buildDefaultConfig(config.subscriptionId(), config.resourceGroup(), config.appName()); - mergeAppServiceConfig(config, defaultConfig); - if (config.pricingTier() == null) { - config.pricingTier(PricingTier.CONSUMPTION); - } if (!newFunctionApp && !config.disableAppInsights()) { // fill ai key from existing app settings config.appInsightsKey(app.entity().getAppSettings().get(CreateOrUpdateFunctionAppTask.APPINSIGHTS_INSTRUMENTATION_KEY)); From 31065b570bb0ca90cf781acd149583eae82bbc0d Mon Sep 17 00:00:00 2001 From: Mingliang Wang Date: Thu, 23 Sep 2021 10:19:18 +0800 Subject: [PATCH 090/126] #1869768: the format of content on error notification in intellij is not correct. --- .../lib/common/messager/AzureMessage.java | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/azure-toolkit-libs/azure-toolkit-common-lib/src/main/java/com/microsoft/azure/toolkit/lib/common/messager/AzureMessage.java b/azure-toolkit-libs/azure-toolkit-common-lib/src/main/java/com/microsoft/azure/toolkit/lib/common/messager/AzureMessage.java index c694c30b21..8adf92469f 100644 --- a/azure-toolkit-libs/azure-toolkit-common-lib/src/main/java/com/microsoft/azure/toolkit/lib/common/messager/AzureMessage.java +++ b/azure-toolkit-libs/azure-toolkit-common-lib/src/main/java/com/microsoft/azure/toolkit/lib/common/messager/AzureMessage.java @@ -65,14 +65,8 @@ public String getContent() { final List operations = this.getOperations(); final String failure = operations.stream().findFirst().map(IAzureOperation::getTitle) .map(azureString -> "Failed to " + this.decorateText(azureString, azureString::getString)).orElse("Failed to proceed"); - final String cause = Optional.ofNullable(this.getCause(throwable)) - .map(StringUtils::uncapitalize) - .map(c -> "," + (c.endsWith(".") ? c : c + '.')) - .orElse(""); - final String errorAction = Optional.ofNullable(this.getErrorAction(throwable)) - .map(StringUtils::capitalize) - .map(c -> System.lineSeparator() + (c.endsWith(".") ? c : c + '.')) - .orElse(""); + final String cause = Optional.ofNullable(this.getCause(throwable)).map(c -> ", " + c).orElse(""); + final String errorAction = Optional.ofNullable(this.getErrorAction(throwable)).map(c -> System.lineSeparator() + c).orElse(""); return failure + cause + errorAction; } @@ -113,7 +107,12 @@ protected String getCause(@Nonnull Throwable throwable) { } else if (root instanceof HttpResponseException) { cause = ((HttpResponseException) root).getResponse().getBodyAsString().block(); } - return StringUtils.firstNonBlank(cause, root.getMessage()); + final String causeMsg = StringUtils.firstNonBlank(cause, root.getMessage()); + return Optional.ofNullable(causeMsg) + .filter(StringUtils::isNotBlank) + .map(StringUtils::uncapitalize) + .map(c -> c.endsWith(".") ? c : c + '.') + .orElse(null); } @Nullable @@ -139,6 +138,8 @@ protected String getErrorAction(@Nonnull Throwable throwable) { .map(t -> t instanceof AzureToolkitRuntimeException ? ((AzureToolkitRuntimeException) t).getAction() : ((AzureToolkitException) t).getAction()) .filter(StringUtils::isNotBlank) .findFirst() + .map(StringUtils::capitalize) + .map(c -> c.endsWith(".") ? c : c + '.') .orElse(null); } From 94036b84ef7ed507aaae6f1535b3772fcb14fb6b Mon Sep 17 00:00:00 2001 From: andxu Date: Wed, 22 Sep 2021 14:51:39 +0800 Subject: [PATCH 091/126] add the logic to allow user to disable creating new azure resources --- .../maven/webapp/AbstractWebAppMojo.java | 14 +++++++++ .../azure/maven/webapp/DeployMojo.java | 30 +++++++++++++++++++ 2 files changed, 44 insertions(+) diff --git a/azure-webapp-maven-plugin/src/main/java/com/microsoft/azure/maven/webapp/AbstractWebAppMojo.java b/azure-webapp-maven-plugin/src/main/java/com/microsoft/azure/maven/webapp/AbstractWebAppMojo.java index bb6a68c429..6cfedd9f87 100644 --- a/azure-webapp-maven-plugin/src/main/java/com/microsoft/azure/maven/webapp/AbstractWebAppMojo.java +++ b/azure-webapp-maven-plugin/src/main/java/com/microsoft/azure/maven/webapp/AbstractWebAppMojo.java @@ -87,6 +87,20 @@ public abstract class AbstractWebAppMojo extends AbstractAppServiceMojo { @Parameter(property = "webapp.skip", defaultValue = "false") protected boolean skip; + /** + * TODO(andxu): move this flag to AbstractAzureMojo + */ + @JsonIgnore + @Parameter(property = "azure.resource.create.skip", defaultValue = "false") + protected boolean skipAzureResourceCreate; + + /** + * TODO(andxu): move this flag to AbstractAzureMojo + */ + @JsonIgnore + @Parameter(property = "skipCreateAzureResource") + protected boolean skipCreateAzureResource; + /** * App Service region, which will only be used to create App Service at the first time. */ diff --git a/azure-webapp-maven-plugin/src/main/java/com/microsoft/azure/maven/webapp/DeployMojo.java b/azure-webapp-maven-plugin/src/main/java/com/microsoft/azure/maven/webapp/DeployMojo.java index 6344a1304e..f796f5c60b 100644 --- a/azure-webapp-maven-plugin/src/main/java/com/microsoft/azure/maven/webapp/DeployMojo.java +++ b/azure-webapp-maven-plugin/src/main/java/com/microsoft/azure/maven/webapp/DeployMojo.java @@ -5,6 +5,7 @@ package com.microsoft.azure.maven.webapp; +import com.azure.core.management.exception.ManagementException; import com.microsoft.azure.maven.model.DeploymentResource; import com.microsoft.azure.maven.webapp.configuration.DeploymentSlotConfig; import com.microsoft.azure.maven.webapp.task.DeployExternalResourcesTask; @@ -23,8 +24,10 @@ import com.microsoft.azure.toolkit.lib.appservice.utils.AppServiceConfigUtils; import com.microsoft.azure.toolkit.lib.common.bundle.AzureString; import com.microsoft.azure.toolkit.lib.common.exception.AzureExecutionException; +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.utils.Utils; +import com.microsoft.azure.toolkit.lib.resource.AzureGroup; import org.apache.commons.lang3.ObjectUtils; import org.apache.commons.lang3.StringUtils; import org.apache.maven.artifact.versioning.ComparableVersion; @@ -63,12 +66,34 @@ private IWebAppBase createOrUpdateResource() throws AzureExecutionException { final AppServiceConfig appServiceConfig = getConfigParser().getAppServiceConfig(); IWebApp app = Azure.az(AzureAppService.class).webapp(appServiceConfig.resourceGroup(), appServiceConfig.appName()); final boolean newWebApp = !app.exists(); + final boolean skipCreate = skipAzureResourceCreate || skipCreateAzureResource; + if (skipCreate) { + if (newWebApp) { + throwForbidCreateResourceWarning("Web app", appName); + } + if (StringUtils.isNotBlank(appServiceConfig.servicePlanResourceGroup())) { + final AzureGroup az = Azure.az(AzureGroup.class).subscription(subscriptionId); + try { + // check servicePlanResourceGroup for existence + az.getByName(appServiceConfig.servicePlanResourceGroup()); + } catch (ManagementException e) { + if (e.getResponse().getStatusCode() == 404) { + throwForbidCreateResourceWarning("Resource group", appServiceConfig.servicePlanResourceGroup()); + } + } + } + } AppServiceConfig defaultConfig = !newWebApp ? fromAppService(app, app.plan()) : buildDefaultConfig(appServiceConfig.subscriptionId(), appServiceConfig.resourceGroup(), appServiceConfig.appName()); mergeAppServiceConfig(appServiceConfig, defaultConfig); if (appServiceConfig.pricingTier() == null) { appServiceConfig.pricingTier(appServiceConfig.runtime().webContainer() == WebContainer.JBOSS_7 ? PricingTier.PREMIUM_P1V3 : PricingTier.PREMIUM_P1V2); } + if (skipCreate) { + if (!Azure.az(AzureAppService.class).appServicePlan(appServiceConfig.servicePlanResourceGroup(), appServiceConfig.servicePlanName()).exists()) { + throwForbidCreateResourceWarning("Service plan", appServiceConfig.servicePlanName()); + } + } return new CreateOrUpdateWebAppTask(appServiceConfig).execute(); } else { // todo: New CreateOrUpdateDeploymentSlotTask @@ -78,6 +103,11 @@ private IWebAppBase createOrUpdateResource() throws AzureExecutionException { } } + private static void throwForbidCreateResourceWarning(String resourceType, String name) { + throw new AzureToolkitRuntimeException(String.format("%s(%s) cannot be found, if you want to create please remove these maven arguments: " + + "`-Dazure.resource.create.skip=true` or `-DskipCreateAzureResource`.", resourceType, name)); + } + private AppServiceConfig buildDefaultConfig(String subscriptionId, String resourceGroup, String appName) { ComparableVersion javaVersionForProject = null; final String outputFileName = project.getBuild().getFinalName() + "." + project.getPackaging(); From 05cd469a52c7d14b8f2f97ed0ad055b6e9666bbb Mon Sep 17 00:00:00 2001 From: Hanxiao Liu Date: Wed, 15 Sep 2021 22:53:26 +0800 Subject: [PATCH 092/126] Add no args constructor for draft resources --- .../lib/compute/AbstractAzureResource.java | 11 +++++----- .../lib/compute/ip/DraftPublicIpAddress.java | 20 +++++++++++++++++ .../lib/compute/ip/PublicIpAddress.java | 2 ++ .../lib/compute/network/DraftNetwork.java | 20 +++++++++++++++++ .../toolkit/lib/compute/network/Network.java | 2 ++ .../security/DraftNetworkSecurityGroup.java | 22 +++++++++++++++++++ .../security/NetworkSecurityGroup.java | 5 ++++- .../lib/compute/vm/DraftVirtualMachine.java | 20 +++++++++++++++++ .../lib/compute/vm/VirtualMachine.java | 2 ++ 9 files changed, 97 insertions(+), 7 deletions(-) diff --git a/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/AbstractAzureResource.java b/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/AbstractAzureResource.java index 46ad6d0124..b01e64d1f3 100644 --- a/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/AbstractAzureResource.java +++ b/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/AbstractAzureResource.java @@ -13,6 +13,7 @@ import com.microsoft.azure.toolkit.lib.common.exception.AzureToolkitRuntimeException; import com.microsoft.azure.toolkit.lib.common.task.AzureTaskManager; import lombok.Getter; +import lombok.NoArgsConstructor; import org.apache.commons.lang3.StringUtils; import org.apache.http.HttpStatus; @@ -20,16 +21,14 @@ import javax.annotation.Nullable; import java.util.Objects; +@NoArgsConstructor public abstract class AbstractAzureResource implements IAzureBaseResource, P> { - @Nonnull @Getter - protected final String name; + protected String name; @Getter - @Nonnull - protected final String resourceGroup; + protected String resourceGroup; @Getter - @Nonnull - protected final String subscriptionId; + protected String subscriptionId; @Getter protected String id; diff --git a/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/ip/DraftPublicIpAddress.java b/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/ip/DraftPublicIpAddress.java index 6db3d446aa..95cf0477c8 100644 --- a/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/ip/DraftPublicIpAddress.java +++ b/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/ip/DraftPublicIpAddress.java @@ -5,10 +5,12 @@ package com.microsoft.azure.toolkit.lib.compute.ip; +import com.azure.resourcemanager.resources.fluentcore.arm.models.HasId; import com.microsoft.azure.toolkit.lib.common.model.Region; import com.microsoft.azure.toolkit.lib.compute.AzureResourceDraft; import lombok.EqualsAndHashCode; import lombok.Getter; +import lombok.NoArgsConstructor; import lombok.Setter; import org.jetbrains.annotations.Nullable; @@ -17,6 +19,7 @@ @Getter @Setter +@NoArgsConstructor @EqualsAndHashCode(callSuper = true) public class DraftPublicIpAddress extends PublicIpAddress implements AzureResourceDraft { private Region region; @@ -26,6 +29,23 @@ public DraftPublicIpAddress(@Nonnull final String subscriptionId, @Nonnull final super(getResourceId(subscriptionId, resourceGroup, name), null); } + public void setSubscriptionId(final String subscriptionId) { + this.subscriptionId = subscriptionId; + } + + public void setResourceGroup(final String resourceGroup) { + this.resourceGroup = resourceGroup; + } + + public void setName(final String name) { + this.name = name; + } + + @Override + public String getId() { + return Optional.ofNullable(remote).map(HasId::id).orElseGet(() -> getResourceId(subscriptionId, resourceGroup, name)); + } + PublicIpAddress create(AzurePublicIpAddress module) { this.module = module; this.remote = module.getPublicIpAddressManager(subscriptionId).define(name) diff --git a/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/ip/PublicIpAddress.java b/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/ip/PublicIpAddress.java index cd52d8973f..8b9d6f2dd5 100644 --- a/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/ip/PublicIpAddress.java +++ b/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/ip/PublicIpAddress.java @@ -10,10 +10,12 @@ import com.microsoft.azure.toolkit.lib.common.event.AzureOperationEvent; import com.microsoft.azure.toolkit.lib.compute.AbstractAzureResource; import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; import javax.annotation.Nonnull; import javax.annotation.Nullable; +@NoArgsConstructor @EqualsAndHashCode(callSuper = true) public class PublicIpAddress extends AbstractAzureResource implements AzureOperationEvent.Source { diff --git a/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/network/DraftNetwork.java b/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/network/DraftNetwork.java index a301e97ed9..e3a17e193f 100644 --- a/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/network/DraftNetwork.java +++ b/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/network/DraftNetwork.java @@ -6,11 +6,13 @@ package com.microsoft.azure.toolkit.lib.compute.network; import com.azure.resourcemanager.network.models.Network.DefinitionStages.WithCreateAndSubnet; +import com.azure.resourcemanager.resources.fluentcore.arm.models.HasId; import com.microsoft.azure.toolkit.lib.common.model.Region; import com.microsoft.azure.toolkit.lib.compute.AzureResourceDraft; import com.microsoft.azure.toolkit.lib.compute.network.model.Subnet; import lombok.EqualsAndHashCode; import lombok.Getter; +import lombok.NoArgsConstructor; import lombok.Setter; import org.apache.commons.lang3.StringUtils; import org.jetbrains.annotations.Nullable; @@ -22,6 +24,7 @@ @Getter @Setter +@NoArgsConstructor @EqualsAndHashCode(callSuper = true) public class DraftNetwork extends Network implements AzureResourceDraft { @@ -35,6 +38,23 @@ public DraftNetwork(@Nonnull final String subscriptionId, @Nonnull final String super(getResourceId(subscriptionId, resourceGroup, name), null); } + public void setSubscriptionId(final String subscriptionId) { + this.subscriptionId = subscriptionId; + } + + public void setResourceGroup(final String resourceGroup) { + this.resourceGroup = resourceGroup; + } + + public void setName(final String name) { + this.name = name; + } + + @Override + public String getId() { + return Optional.ofNullable(remote).map(HasId::id).orElseGet(() -> getResourceId(subscriptionId, resourceGroup, name)); + } + Network create(final AzureNetwork module) { this.module = module; WithCreateAndSubnet withCreateAndSubnet = module.getNetworkManager(subscriptionId).define(name) diff --git a/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/network/Network.java b/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/network/Network.java index d70dc6cf4b..1db434f46a 100644 --- a/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/network/Network.java +++ b/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/network/Network.java @@ -11,12 +11,14 @@ import com.microsoft.azure.toolkit.lib.compute.AbstractAzureResource; import com.microsoft.azure.toolkit.lib.compute.network.model.Subnet; import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; import javax.annotation.Nonnull; import javax.annotation.Nullable; import java.util.List; import java.util.stream.Collectors; +@NoArgsConstructor @EqualsAndHashCode(callSuper = true) public class Network extends AbstractAzureResource implements AzureOperationEvent.Source { diff --git a/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/security/DraftNetworkSecurityGroup.java b/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/security/DraftNetworkSecurityGroup.java index bb00ab32cc..156a9231f5 100644 --- a/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/security/DraftNetworkSecurityGroup.java +++ b/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/security/DraftNetworkSecurityGroup.java @@ -11,12 +11,15 @@ import com.azure.resourcemanager.network.models.NetworkSecurityRule.DefinitionStages.WithSourceAddressOrSecurityGroup; import com.azure.resourcemanager.network.models.NetworkSecurityRule.DefinitionStages.WithSourcePort; import com.azure.resourcemanager.network.models.SecurityRuleProtocol; +import com.azure.resourcemanager.resources.fluentcore.arm.models.HasId; import com.microsoft.azure.toolkit.lib.common.entity.IAzureBaseResource; import com.microsoft.azure.toolkit.lib.common.model.Region; import com.microsoft.azure.toolkit.lib.compute.AzureResourceDraft; import com.microsoft.azure.toolkit.lib.compute.security.model.SecurityRule; import io.jsonwebtoken.lang.Collections; +import lombok.EqualsAndHashCode; import lombok.Getter; +import lombok.NoArgsConstructor; import lombok.Setter; import javax.annotation.Nonnull; @@ -26,6 +29,8 @@ @Getter @Setter +@NoArgsConstructor +@EqualsAndHashCode(callSuper = true) public class DraftNetworkSecurityGroup extends NetworkSecurityGroup implements AzureResourceDraft { private static final int BASE_PRIORITY = 300; private static final int PRIORITY_STEP = 20; @@ -37,6 +42,23 @@ public DraftNetworkSecurityGroup(@Nonnull final String subscriptionId, @Nonnull super(getResourceId(subscriptionId, resourceGroup, name), null); } + public void setSubscriptionId(final String subscriptionId) { + this.subscriptionId = subscriptionId; + } + + public void setResourceGroup(final String resourceGroup) { + this.resourceGroup = resourceGroup; + } + + public void setName(final String name) { + this.name = name; + } + + @Override + public String getId() { + return Optional.ofNullable(remote).map(HasId::id).orElseGet(() -> getResourceId(subscriptionId, resourceGroup, name)); + } + NetworkSecurityGroup create(final AzureNetworkSecurityGroup module) { this.module = module; WithCreate withCreate = module.getSecurityGroupManager(subscriptionId) diff --git a/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/security/NetworkSecurityGroup.java b/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/security/NetworkSecurityGroup.java index b1b3571b05..398b0c8ece 100644 --- a/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/security/NetworkSecurityGroup.java +++ b/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/security/NetworkSecurityGroup.java @@ -9,11 +9,14 @@ import com.microsoft.azure.toolkit.lib.common.entity.IAzureModule; import com.microsoft.azure.toolkit.lib.common.event.AzureOperationEvent; import com.microsoft.azure.toolkit.lib.compute.AbstractAzureResource; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; import javax.annotation.Nonnull; import javax.annotation.Nullable; - +@NoArgsConstructor +@EqualsAndHashCode(callSuper = true) public class NetworkSecurityGroup extends AbstractAzureResource implements AzureOperationEvent.Source { diff --git a/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/vm/DraftVirtualMachine.java b/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/vm/DraftVirtualMachine.java index f629c30ab0..8666511b75 100644 --- a/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/vm/DraftVirtualMachine.java +++ b/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/vm/DraftVirtualMachine.java @@ -11,6 +11,7 @@ import com.azure.resourcemanager.compute.models.VirtualMachine.DefinitionStages.WithLinuxRootPasswordOrPublicKeyManagedOrUnmanaged; import com.azure.resourcemanager.compute.models.VirtualMachine.DefinitionStages.WithProximityPlacementGroup; import com.azure.resourcemanager.compute.models.VirtualMachine.DefinitionStages.WithPublicIPAddress; +import com.azure.resourcemanager.resources.fluentcore.arm.models.HasId; import com.microsoft.azure.toolkit.lib.common.model.Region; import com.microsoft.azure.toolkit.lib.compute.AzureResourceDraft; import com.microsoft.azure.toolkit.lib.compute.ip.PublicIpAddress; @@ -22,6 +23,7 @@ import com.microsoft.azure.toolkit.lib.compute.vm.model.OperatingSystem; import com.microsoft.azure.toolkit.lib.storage.service.StorageAccount; import lombok.Getter; +import lombok.NoArgsConstructor; import lombok.Setter; import org.apache.commons.lang3.StringUtils; import org.jetbrains.annotations.Nullable; @@ -31,6 +33,7 @@ @Getter @Setter +@NoArgsConstructor public class DraftVirtualMachine extends VirtualMachine implements AzureResourceDraft { private Region region; private AzureImage image; @@ -51,6 +54,23 @@ public DraftVirtualMachine(@Nonnull final String subscriptionId, @Nonnull final super(getResourceId(subscriptionId, resourceGroup, name), null); } + public void setSubscriptionId(final String subscriptionId) { + this.subscriptionId = subscriptionId; + } + + public void setResourceGroup(final String resourceGroup) { + this.resourceGroup = resourceGroup; + } + + public void setName(final String name) { + this.name = name; + } + + @Override + public String getId() { + return Optional.ofNullable(remote).map(HasId::id).orElseGet(() -> getResourceId(subscriptionId, resourceGroup, name)); + } + @Override protected String loadStatus() { return Optional.ofNullable(remote).map(ignore -> super.loadStatus()).orElse(Status.DRAFT); diff --git a/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/vm/VirtualMachine.java b/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/vm/VirtualMachine.java index e31b3dfbfb..972a239a7f 100644 --- a/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/vm/VirtualMachine.java +++ b/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/vm/VirtualMachine.java @@ -11,11 +11,13 @@ import com.microsoft.azure.toolkit.lib.common.entity.Removable; import com.microsoft.azure.toolkit.lib.common.event.AzureOperationEvent; import com.microsoft.azure.toolkit.lib.compute.AbstractAzureResource; +import lombok.NoArgsConstructor; import org.apache.commons.lang3.StringUtils; import javax.annotation.Nonnull; import javax.annotation.Nullable; +@NoArgsConstructor public class VirtualMachine extends AbstractAzureResource implements AzureOperationEvent.Source, Removable { From 8d18cd3aad2e6d77301d36ba9bfb41e71865f973 Mon Sep 17 00:00:00 2001 From: Hanxiao Liu Date: Wed, 15 Sep 2021 22:53:41 +0800 Subject: [PATCH 093/126] Fix equals and hash method for azure image --- .../toolkit/lib/compute/vm/AzureImage.java | 50 +++++++++---------- 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/vm/AzureImage.java b/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/vm/AzureImage.java index 6586d34823..febb6171a7 100644 --- a/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/vm/AzureImage.java +++ b/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/vm/AzureImage.java @@ -20,43 +20,43 @@ public class AzureImage { @Nonnull @Getter(value = AccessLevel.PACKAGE) + @EqualsAndHashCode.Exclude private final ImageReference imageReference; + @Nonnull @Getter private final OperatingSystem operatingSystem; + @Getter + private final String id; + @Getter + private final String publisherName; + @Getter + private final String offer; + @Getter + private final String sku; + @Getter + private final String version; - AzureImage(@Nonnull VirtualMachineImage virtualMachineImage) { - this.operatingSystem = OperatingSystem.fromString(virtualMachineImage.osDiskImage().operatingSystem().name()); - this.imageReference = virtualMachineImage.imageReference(); + public AzureImage(@Nonnull VirtualMachineImage virtualMachineImage) { + this(OperatingSystem.fromString(virtualMachineImage.osDiskImage().operatingSystem().name()), virtualMachineImage.imageReference()); } public AzureImage(@Nonnull KnownWindowsVirtualMachineImage windowsVirtualMachineImage) { - this.operatingSystem = OperatingSystem.Windows; - this.imageReference = windowsVirtualMachineImage.imageReference(); + this(OperatingSystem.Windows, windowsVirtualMachineImage.imageReference()); } - AzureImage(@Nonnull KnownLinuxVirtualMachineImage linuxVirtualMachineImage) { - this.operatingSystem = OperatingSystem.Linux; - this.imageReference = linuxVirtualMachineImage.imageReference(); + public AzureImage(@Nonnull KnownLinuxVirtualMachineImage linuxVirtualMachineImage) { + this(OperatingSystem.Linux, linuxVirtualMachineImage.imageReference()); } - public String id() { - return imageReference.id(); - } - - public String publisherName() { - return imageReference.publisher(); - } - - public String offer() { - return imageReference.offer(); - } - - public String sku() { - return imageReference.sku(); - } + public AzureImage(final OperatingSystem operatingSystem, final ImageReference imageReference) { + this.operatingSystem = operatingSystem; + this.id = imageReference.id(); + this.publisherName = imageReference.publisher(); + this.offer = imageReference.offer(); + this.sku = imageReference.sku(); + this.version = imageReference.version(); - public String version() { - return imageReference.version(); + this.imageReference = imageReference; } } From aacafc1ec319778e0576f16f87a85314f529fbf9 Mon Sep 17 00:00:00 2001 From: Hanxiao Liu Date: Thu, 16 Sep 2021 10:36:08 +0800 Subject: [PATCH 094/126] Fix possible NPE for vm without security group --- .../azure/toolkit/lib/compute/vm/DraftVirtualMachine.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/vm/DraftVirtualMachine.java b/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/vm/DraftVirtualMachine.java index 8666511b75..48857c37f1 100644 --- a/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/vm/DraftVirtualMachine.java +++ b/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/vm/DraftVirtualMachine.java @@ -103,7 +103,9 @@ VirtualMachine create(final AzureVirtualMachine module) { // todo: implement azure spot related configs } this.remote = withCreate.create(); - this.remote.getPrimaryNetworkInterface().update().withExistingNetworkSecurityGroup(getSecurityGroupClient()).apply(); + if (securityGroup != null) { + this.remote.getPrimaryNetworkInterface().update().withExistingNetworkSecurityGroup(getSecurityGroupClient()).apply(); + } refreshStatus(); module.refresh(); return this; From fe77b92fed9cc0648dcaa072bb09c537254c2ce9 Mon Sep 17 00:00:00 2001 From: Hanxiao Liu Date: Thu, 16 Sep 2021 11:22:26 +0800 Subject: [PATCH 095/126] Resolve possible NPE for vm status --- .../azure/toolkit/lib/compute/vm/VirtualMachine.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/vm/VirtualMachine.java b/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/vm/VirtualMachine.java index 972a239a7f..f6c2a71ab8 100644 --- a/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/vm/VirtualMachine.java +++ b/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/vm/VirtualMachine.java @@ -16,6 +16,8 @@ import javax.annotation.Nonnull; import javax.annotation.Nullable; +import java.util.Objects; +import java.util.Optional; @NoArgsConstructor public class VirtualMachine extends AbstractAzureResource @@ -42,7 +44,7 @@ public VirtualMachine(@Nonnull com.azure.resourcemanager.compute.models.VirtualM @Override protected String loadStatus() { - final String powerState = remote().powerState().toString(); + final String powerState = Optional.ofNullable(remote().powerState()).map(Objects::toString).orElse(StringUtils.EMPTY); if (StringUtils.equalsIgnoreCase(powerState, PowerState.RUNNING.toString())) { return Status.RUNNING; } else if (StringUtils.equalsAnyIgnoreCase(powerState, PowerState.DEALLOCATING.toString(), PowerState.STOPPING.toString(), From f0ead16bcfcd8718676e54e61e756e7c42492e86 Mon Sep 17 00:00:00 2001 From: Hanxiao Liu Date: Thu, 23 Sep 2021 11:09:15 +0800 Subject: [PATCH 096/126] Add getRegion to virtual machine resource interface --- .../lib/compute/ip/PublicIpAddress.java | 5 +++ .../toolkit/lib/compute/network/Network.java | 5 +++ .../security/NetworkSecurityGroup.java | 5 +++ .../lib/compute/vm/VirtualMachine.java | 41 +++++++++++-------- 4 files changed, 38 insertions(+), 18 deletions(-) diff --git a/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/ip/PublicIpAddress.java b/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/ip/PublicIpAddress.java index 8b9d6f2dd5..2e8904bfe2 100644 --- a/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/ip/PublicIpAddress.java +++ b/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/ip/PublicIpAddress.java @@ -8,6 +8,7 @@ import com.microsoft.azure.toolkit.lib.common.entity.IAzureBaseResource; import com.microsoft.azure.toolkit.lib.common.entity.IAzureModule; import com.microsoft.azure.toolkit.lib.common.event.AzureOperationEvent; +import com.microsoft.azure.toolkit.lib.common.model.Region; import com.microsoft.azure.toolkit.lib.compute.AbstractAzureResource; import lombok.EqualsAndHashCode; import lombok.NoArgsConstructor; @@ -37,6 +38,10 @@ public PublicIpAddress(@Nonnull final com.azure.resourcemanager.network.models.P return module; } + public Region getRegion() { + return Region.fromName(remote().regionName()); + } + @Nullable @Override protected com.azure.resourcemanager.network.models.PublicIpAddress loadRemote() { diff --git a/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/network/Network.java b/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/network/Network.java index 1db434f46a..1eb56ea20b 100644 --- a/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/network/Network.java +++ b/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/network/Network.java @@ -8,6 +8,7 @@ import com.microsoft.azure.toolkit.lib.common.entity.IAzureBaseResource; import com.microsoft.azure.toolkit.lib.common.entity.IAzureModule; import com.microsoft.azure.toolkit.lib.common.event.AzureOperationEvent; +import com.microsoft.azure.toolkit.lib.common.model.Region; import com.microsoft.azure.toolkit.lib.compute.AbstractAzureResource; import com.microsoft.azure.toolkit.lib.compute.network.model.Subnet; import lombok.EqualsAndHashCode; @@ -44,6 +45,10 @@ public List subnets() { return module; } + public Region getRegion() { + return Region.fromName(remote().regionName()); + } + @Nullable @Override protected com.azure.resourcemanager.network.models.Network loadRemote() { diff --git a/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/security/NetworkSecurityGroup.java b/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/security/NetworkSecurityGroup.java index 398b0c8ece..5b1193d4c3 100644 --- a/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/security/NetworkSecurityGroup.java +++ b/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/security/NetworkSecurityGroup.java @@ -8,6 +8,7 @@ import com.microsoft.azure.toolkit.lib.common.entity.IAzureBaseResource; import com.microsoft.azure.toolkit.lib.common.entity.IAzureModule; import com.microsoft.azure.toolkit.lib.common.event.AzureOperationEvent; +import com.microsoft.azure.toolkit.lib.common.model.Region; import com.microsoft.azure.toolkit.lib.compute.AbstractAzureResource; import lombok.EqualsAndHashCode; import lombok.NoArgsConstructor; @@ -39,6 +40,10 @@ public NetworkSecurityGroup(@Nonnull final com.azure.resourcemanager.network.mod return module; } + public Region getRegion() { + return Region.fromName(remote().regionName()); + } + @Nullable @Override protected com.azure.resourcemanager.network.models.NetworkSecurityGroup loadRemote() { diff --git a/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/vm/VirtualMachine.java b/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/vm/VirtualMachine.java index f6c2a71ab8..a316f4086d 100644 --- a/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/vm/VirtualMachine.java +++ b/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/vm/VirtualMachine.java @@ -10,6 +10,7 @@ import com.microsoft.azure.toolkit.lib.common.entity.IAzureModule; import com.microsoft.azure.toolkit.lib.common.entity.Removable; import com.microsoft.azure.toolkit.lib.common.event.AzureOperationEvent; +import com.microsoft.azure.toolkit.lib.common.model.Region; import com.microsoft.azure.toolkit.lib.compute.AbstractAzureResource; import lombok.NoArgsConstructor; import org.apache.commons.lang3.StringUtils; @@ -42,6 +43,28 @@ public VirtualMachine(@Nonnull com.azure.resourcemanager.compute.models.VirtualM return module; } + public void start() { + this.status(Status.PENDING); + remote().start(); + this.refreshStatus(); + } + + public void stop() { + this.status(Status.PENDING); + remote().powerOff(); + this.refreshStatus(); + } + + public void restart() { + this.status(Status.PENDING); + remote().restart(); + this.refreshStatus(); + } + + public Region getRegion() { + return Region.fromName(remote().regionName()); + } + @Override protected String loadStatus() { final String powerState = Optional.ofNullable(remote().powerState()).map(Objects::toString).orElse(StringUtils.EMPTY); @@ -63,24 +86,6 @@ protected com.azure.resourcemanager.compute.models.VirtualMachine loadRemote() { return module.getVirtualMachinesManager(subscriptionId).getByResourceGroup(resourceGroup, name); } - public void start() { - this.status(Status.PENDING); - remote().start(); - this.refreshStatus(); - } - - public void stop() { - this.status(Status.PENDING); - remote().powerOff(); - this.refreshStatus(); - } - - public void restart() { - this.status(Status.PENDING); - remote().restart(); - this.refreshStatus(); - } - @Override public void remove() { if (this.exists()) { From 14e7a8685e5cc3ba7bcd3c7903f88d90ca15fdb0 Mon Sep 17 00:00:00 2001 From: Hanxiao Liu Date: Thu, 23 Sep 2021 11:10:37 +0800 Subject: [PATCH 097/126] Add default draft to azure resources --- .../azure/toolkit/lib/common/utils/Utils.java | 13 ++++++++++--- .../lib/compute/ip/DraftPublicIpAddress.java | 7 +++++++ .../toolkit/lib/compute/network/DraftNetwork.java | 10 ++++++++++ 3 files changed, 27 insertions(+), 3 deletions(-) diff --git a/azure-toolkit-libs/azure-toolkit-common-lib/src/main/java/com/microsoft/azure/toolkit/lib/common/utils/Utils.java b/azure-toolkit-libs/azure-toolkit-common-lib/src/main/java/com/microsoft/azure/toolkit/lib/common/utils/Utils.java index 15fa311055..df60f0cf14 100644 --- a/azure-toolkit-libs/azure-toolkit-common-lib/src/main/java/com/microsoft/azure/toolkit/lib/common/utils/Utils.java +++ b/azure-toolkit-libs/azure-toolkit-common-lib/src/main/java/com/microsoft/azure/toolkit/lib/common/utils/Utils.java @@ -18,18 +18,20 @@ import java.io.InputStream; import java.math.BigInteger; import java.nio.charset.StandardCharsets; +import java.text.SimpleDateFormat; import java.util.Collection; import java.util.Collections; +import java.util.Date; import java.util.List; import java.util.Map; +import java.util.Set; import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; import java.util.function.Function; +import java.util.function.Predicate; import java.util.jar.JarEntry; import java.util.jar.JarFile; import java.util.stream.Collectors; -import java.util.Set; -import java.util.concurrent.ConcurrentHashMap; -import java.util.function.Predicate; public class Utils { private static final boolean isWindows = System.getProperty("os.name").contains("Windows"); @@ -38,6 +40,11 @@ public class Utils { private static final String WAR = "war"; private static final String EAR = "ear"; private static final String SUBSCRIPTIONS = "subscriptions"; + private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yyMMddHHmmss"); + + public static String getTimestamp() { + return DATE_FORMAT.format(new Date()); + } public static String getArtifactCompileVersion(File artifact) throws AzureExecutionException { try (JarFile jarFile = new JarFile(artifact)) { diff --git a/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/ip/DraftPublicIpAddress.java b/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/ip/DraftPublicIpAddress.java index 95cf0477c8..515d87a3bd 100644 --- a/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/ip/DraftPublicIpAddress.java +++ b/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/ip/DraftPublicIpAddress.java @@ -7,6 +7,7 @@ import com.azure.resourcemanager.resources.fluentcore.arm.models.HasId; import com.microsoft.azure.toolkit.lib.common.model.Region; +import com.microsoft.azure.toolkit.lib.common.utils.Utils; import com.microsoft.azure.toolkit.lib.compute.AzureResourceDraft; import lombok.EqualsAndHashCode; import lombok.Getter; @@ -29,6 +30,12 @@ public DraftPublicIpAddress(@Nonnull final String subscriptionId, @Nonnull final super(getResourceId(subscriptionId, resourceGroup, name), null); } + public static DraftPublicIpAddress getDefaultPublicIpAddressDraft() { + final DraftPublicIpAddress publicIpAddress = new DraftPublicIpAddress(); + publicIpAddress.setName(String.format("public-ip-%s", Utils.getTimestamp())); + return publicIpAddress; + } + public void setSubscriptionId(final String subscriptionId) { this.subscriptionId = subscriptionId; } diff --git a/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/network/DraftNetwork.java b/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/network/DraftNetwork.java index e3a17e193f..8b15d5e26c 100644 --- a/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/network/DraftNetwork.java +++ b/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/network/DraftNetwork.java @@ -8,6 +8,7 @@ import com.azure.resourcemanager.network.models.Network.DefinitionStages.WithCreateAndSubnet; import com.azure.resourcemanager.resources.fluentcore.arm.models.HasId; import com.microsoft.azure.toolkit.lib.common.model.Region; +import com.microsoft.azure.toolkit.lib.common.utils.Utils; import com.microsoft.azure.toolkit.lib.compute.AzureResourceDraft; import com.microsoft.azure.toolkit.lib.compute.network.model.Subnet; import lombok.EqualsAndHashCode; @@ -38,6 +39,15 @@ public DraftNetwork(@Nonnull final String subscriptionId, @Nonnull final String super(getResourceId(subscriptionId, resourceGroup, name), null); } + public static DraftNetwork getDefaultNetworkDraft() { + final DraftNetwork draftNetwork = new DraftNetwork(); + draftNetwork.setName(String.format("network-%s", Utils.getTimestamp())); + draftNetwork.setAddressSpace("10.0.2.0/24"); + draftNetwork.setSubnet("default"); + draftNetwork.setSubnetAddressSpace("10.0.2.0/24"); + return draftNetwork; + } + public void setSubscriptionId(final String subscriptionId) { this.subscriptionId = subscriptionId; } From be0336bace395e96459f153dc495893beb69dbd9 Mon Sep 17 00:00:00 2001 From: Hanxiao Liu Date: Thu, 23 Sep 2021 11:11:07 +0800 Subject: [PATCH 098/126] Add enum for image and vm size --- .../toolkit/lib/compute/vm/AzureImage.java | 22 +++++++++++++++++++ .../compute/vm/AzureVirtualMachineSize.java | 7 ++++++ 2 files changed, 29 insertions(+) diff --git a/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/vm/AzureImage.java b/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/vm/AzureImage.java index febb6171a7..3adfb991f2 100644 --- a/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/vm/AzureImage.java +++ b/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/vm/AzureImage.java @@ -18,6 +18,28 @@ @EqualsAndHashCode public class AzureImage { + public static final AzureImage WINDOWS_DESKTOP_10_20H1_PRO = new AzureImage(KnownWindowsVirtualMachineImage.WINDOWS_DESKTOP_10_20H1_PRO); + public static final AzureImage WINDOWS_SERVER_2019_DATACENTER = new AzureImage(KnownWindowsVirtualMachineImage.WINDOWS_SERVER_2019_DATACENTER); + public static final AzureImage WINDOWS_SERVER_2019_DATACENTER_WITH_CONTAINER = + new AzureImage(KnownWindowsVirtualMachineImage.WINDOWS_SERVER_2019_DATACENTER_WITH_CONTAINERS); + public static final AzureImage WINDOWS_SERVER_2016_DATACENTER = new AzureImage(KnownWindowsVirtualMachineImage.WINDOWS_SERVER_2016_DATACENTER); + public static final AzureImage WINDOWS_SERVER_2012_R2_DATACENTER = new AzureImage(KnownWindowsVirtualMachineImage.WINDOWS_SERVER_2012_R2_DATACENTER); + public static final AzureImage UBUNTU_SERVER_16_04_LTS = new AzureImage(KnownLinuxVirtualMachineImage.UBUNTU_SERVER_16_04_LTS); + public static final AzureImage UBUNTU_SERVER_18_04_LTS = new AzureImage(KnownLinuxVirtualMachineImage.UBUNTU_SERVER_18_04_LTS); + public static final AzureImage DEBIAN_9 = new AzureImage(KnownLinuxVirtualMachineImage.DEBIAN_9); + public static final AzureImage DEBIAN_10 = new AzureImage(KnownLinuxVirtualMachineImage.DEBIAN_10); + public static final AzureImage CENTOS_8_1 = new AzureImage(KnownLinuxVirtualMachineImage.CENTOS_8_1); + public static final AzureImage CENTOS_8_3 = new AzureImage(KnownLinuxVirtualMachineImage.CENTOS_8_3); + @Deprecated + public static final AzureImage OPENSUSE_LEAP_15_1 = new AzureImage(KnownLinuxVirtualMachineImage.OPENSUSE_LEAP_15_1); + public static final AzureImage OPENSUSE_LEAP_15 = new AzureImage(KnownLinuxVirtualMachineImage.OPENSUSE_LEAP_15); + @Deprecated + public static final AzureImage SLES_15_SP1 = new AzureImage(KnownLinuxVirtualMachineImage.SLES_15_SP1); + public static final AzureImage SLES_15 = new AzureImage(KnownLinuxVirtualMachineImage.SLES_15); + public static final AzureImage REDHAT_RHEL_8_2 = new AzureImage(KnownLinuxVirtualMachineImage.REDHAT_RHEL_8_2); + public static final AzureImage ORACLE_LINUX_8_1 = new AzureImage(KnownLinuxVirtualMachineImage.ORACLE_LINUX_8_1); + + @Nonnull @Getter(value = AccessLevel.PACKAGE) @EqualsAndHashCode.Exclude diff --git a/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/vm/AzureVirtualMachineSize.java b/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/vm/AzureVirtualMachineSize.java index 85e2345dfd..2dfd4bd2ab 100644 --- a/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/vm/AzureVirtualMachineSize.java +++ b/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/vm/AzureVirtualMachineSize.java @@ -12,6 +12,13 @@ @Getter @EqualsAndHashCode public class AzureVirtualMachineSize { + public static final AzureVirtualMachineSize Standard_D2 = new AzureVirtualMachineSize("Standard_D2"); + public static final AzureVirtualMachineSize Standard_D2_v2 = new AzureVirtualMachineSize("Standard_D2_v2"); + public static final AzureVirtualMachineSize Standard_DS2 = new AzureVirtualMachineSize("Standard_DS2"); + public static final AzureVirtualMachineSize Standard_D2s_v3 = new AzureVirtualMachineSize("Standard_D2s_v3"); + public static final AzureVirtualMachineSize Standard_D4s_v3 = new AzureVirtualMachineSize("Standard_D4s_v3"); + public static final AzureVirtualMachineSize Standard_E2s_v3 = new AzureVirtualMachineSize("Standard_E2s_v3"); + private final String name; public AzureVirtualMachineSize(final ComputeSku size) { From e55ccd125c177c3dfc9368eca6bd3b68520b5212 Mon Sep 17 00:00:00 2001 From: andxu Date: Thu, 23 Sep 2021 11:32:56 +0800 Subject: [PATCH 099/126] add the logic to allow user to disable creating new azure resources --- .../task/CreateOrUpdateWebAppTask.java | 14 ++++++ .../toolkit/lib/appservice/utils/Utils.java | 5 +++ .../azure/toolkit/lib/AzureService.java | 1 - .../azure/maven/webapp/DeployMojo.java | 43 +++++-------------- 4 files changed, 30 insertions(+), 33 deletions(-) diff --git a/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/task/CreateOrUpdateWebAppTask.java b/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/task/CreateOrUpdateWebAppTask.java index 946594be9c..2ae5f8b1af 100644 --- a/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/task/CreateOrUpdateWebAppTask.java +++ b/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/task/CreateOrUpdateWebAppTask.java @@ -28,6 +28,7 @@ import com.microsoft.azure.toolkit.lib.common.task.AzureTask; import com.microsoft.azure.toolkit.lib.common.telemetry.AzureTelemetry; import com.microsoft.azure.toolkit.lib.resource.task.CreateResourceGroupTask; +import lombok.Setter; import org.apache.commons.lang3.ObjectUtils; import org.apache.commons.lang3.StringUtils; import reactor.core.publisher.Flux; @@ -36,6 +37,8 @@ import java.util.HashMap; import java.util.List; +import static com.microsoft.azure.toolkit.lib.appservice.utils.Utils.throwForbidCreateResourceWarning; + public class CreateOrUpdateWebAppTask extends AzureTask { private static final String CREATE_NEW_WEB_APP = "createNewWebApp"; @@ -47,6 +50,9 @@ public class CreateOrUpdateWebAppTask extends AzureTask { private final AppServiceConfig config; private final List> subTasks; + @Setter + private boolean skipCreateAzureResource; + public CreateOrUpdateWebAppTask(AppServiceConfig config) { this.config = config; this.subTasks = this.initTasks(); @@ -60,6 +66,9 @@ private List> initTasks() { final IWebApp target = az.subscription(config.subscriptionId()) .webapp(config.resourceGroup(), config.appName()); if (!target.exists()) { + if (skipCreateAzureResource) { + throwForbidCreateResourceWarning("Web app", config.appName()); + } CheckNameAvailabilityResultEntity result = az.checkNameAvailability(config.subscriptionId(), config.appName()); if (!result.isAvailable()) { throw new AzureToolkitRuntimeException(AzureString.format("Cannot create webapp {0} due to error: {1}", @@ -102,6 +111,11 @@ private IWebApp update(final IWebApp webApp) { final IAppServicePlan currentPlan = webApp.plan(); final AppServicePlanConfig servicePlanConfig = config.getServicePlanConfig(); + if (skipCreateAzureResource && !Azure.az(AzureAppService.class).appServicePlan(servicePlanConfig.servicePlanResourceGroup(), servicePlanConfig.servicePlanName()).exists()) { + throwForbidCreateResourceWarning("Service plan", servicePlanConfig.servicePlanName()); + } + throwForbidCreateResourceWarning("Web app", config.appName()); + final Runtime runtime = getRuntime(config.runtime()); final IAppServicePlan appServicePlan = new CreateOrUpdateAppServicePlanTask(servicePlanConfig).execute(); final IAppServiceUpdater draft = webApp.update(); diff --git a/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/utils/Utils.java b/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/utils/Utils.java index fe76999695..44ef8ca156 100644 --- a/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/utils/Utils.java +++ b/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/utils/Utils.java @@ -80,4 +80,9 @@ public static void mergeObjects(T to, T from) throws IllegalAccessException } } } + + public static void throwForbidCreateResourceWarning(String resourceType, String name) { + throw new AzureToolkitRuntimeException(String.format("%s(%s) cannot be found, if you want to create please remove these maven arguments: " + + "`-Dazure.resource.create.skip=true` or `-DskipCreateAzureResource`.", resourceType, name)); + } } diff --git a/azure-toolkit-libs/azure-toolkit-common-lib/src/main/java/com/microsoft/azure/toolkit/lib/AzureService.java b/azure-toolkit-libs/azure-toolkit-common-lib/src/main/java/com/microsoft/azure/toolkit/lib/AzureService.java index c2960bbc73..7090f2f256 100644 --- a/azure-toolkit-libs/azure-toolkit-common-lib/src/main/java/com/microsoft/azure/toolkit/lib/AzureService.java +++ b/azure-toolkit-libs/azure-toolkit-common-lib/src/main/java/com/microsoft/azure/toolkit/lib/AzureService.java @@ -34,7 +34,6 @@ default List getSubscriptions() { return Azure.az(IAzureAccount.class).account().getSelectedSubscriptions(); } - @SuppressWarnings("checkstyle:Indentation") default List listSupportedRegions(String subscriptionId) { String[] names = StringUtils.split(name(), "/"); if (names.length != 2) { diff --git a/azure-webapp-maven-plugin/src/main/java/com/microsoft/azure/maven/webapp/DeployMojo.java b/azure-webapp-maven-plugin/src/main/java/com/microsoft/azure/maven/webapp/DeployMojo.java index f796f5c60b..be9dc82c23 100644 --- a/azure-webapp-maven-plugin/src/main/java/com/microsoft/azure/maven/webapp/DeployMojo.java +++ b/azure-webapp-maven-plugin/src/main/java/com/microsoft/azure/maven/webapp/DeployMojo.java @@ -5,7 +5,6 @@ package com.microsoft.azure.maven.webapp; -import com.azure.core.management.exception.ManagementException; import com.microsoft.azure.maven.model.DeploymentResource; import com.microsoft.azure.maven.webapp.configuration.DeploymentSlotConfig; import com.microsoft.azure.maven.webapp.task.DeployExternalResourcesTask; @@ -27,7 +26,6 @@ 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.utils.Utils; -import com.microsoft.azure.toolkit.lib.resource.AzureGroup; import org.apache.commons.lang3.ObjectUtils; import org.apache.commons.lang3.StringUtils; import org.apache.maven.artifact.versioning.ComparableVersion; @@ -39,6 +37,7 @@ import static com.microsoft.azure.toolkit.lib.appservice.utils.AppServiceConfigUtils.fromAppService; import static com.microsoft.azure.toolkit.lib.appservice.utils.AppServiceConfigUtils.mergeAppServiceConfig; +import static com.microsoft.azure.toolkit.lib.appservice.utils.Utils.throwForbidCreateResourceWarning; /** * Deploy an Azure Web App, either Windows-based or Linux-based. @@ -62,52 +61,32 @@ protected void doExecute() throws AzureExecutionException { } private IWebAppBase createOrUpdateResource() throws AzureExecutionException { + final boolean skipCreate = skipAzureResourceCreate || skipCreateAzureResource; if (!isDeployToDeploymentSlot()) { final AppServiceConfig appServiceConfig = getConfigParser().getAppServiceConfig(); IWebApp app = Azure.az(AzureAppService.class).webapp(appServiceConfig.resourceGroup(), appServiceConfig.appName()); final boolean newWebApp = !app.exists(); - final boolean skipCreate = skipAzureResourceCreate || skipCreateAzureResource; - if (skipCreate) { - if (newWebApp) { - throwForbidCreateResourceWarning("Web app", appName); - } - if (StringUtils.isNotBlank(appServiceConfig.servicePlanResourceGroup())) { - final AzureGroup az = Azure.az(AzureGroup.class).subscription(subscriptionId); - try { - // check servicePlanResourceGroup for existence - az.getByName(appServiceConfig.servicePlanResourceGroup()); - } catch (ManagementException e) { - if (e.getResponse().getStatusCode() == 404) { - throwForbidCreateResourceWarning("Resource group", appServiceConfig.servicePlanResourceGroup()); - } - } - } - } AppServiceConfig defaultConfig = !newWebApp ? fromAppService(app, app.plan()) : buildDefaultConfig(appServiceConfig.subscriptionId(), appServiceConfig.resourceGroup(), appServiceConfig.appName()); mergeAppServiceConfig(appServiceConfig, defaultConfig); if (appServiceConfig.pricingTier() == null) { appServiceConfig.pricingTier(appServiceConfig.runtime().webContainer() == WebContainer.JBOSS_7 ? PricingTier.PREMIUM_P1V3 : PricingTier.PREMIUM_P1V2); } - if (skipCreate) { - if (!Azure.az(AzureAppService.class).appServicePlan(appServiceConfig.servicePlanResourceGroup(), appServiceConfig.servicePlanName()).exists()) { - throwForbidCreateResourceWarning("Service plan", appServiceConfig.servicePlanName()); - } - } - return new CreateOrUpdateWebAppTask(appServiceConfig).execute(); + final CreateOrUpdateWebAppTask task = new CreateOrUpdateWebAppTask(appServiceConfig); + task.setSkipCreateAzureResource(skipCreate); + return task.execute(); } else { // todo: New CreateOrUpdateDeploymentSlotTask final DeploymentSlotConfig config = getConfigParser().getDeploymentSlotConfig(); final IWebAppDeploymentSlot slot = getDeploymentSlot(config); - return slot.exists() ? updateDeploymentSlot(slot, config) : createDeploymentSlot(slot, config); + final boolean slotExists = slot.exists(); + if (!slotExists && skipCreate) { + throwForbidCreateResourceWarning("Deployment slot", config.getName()); + } + return slotExists ? updateDeploymentSlot(slot, config) : createDeploymentSlot(slot, config); } } - private static void throwForbidCreateResourceWarning(String resourceType, String name) { - throw new AzureToolkitRuntimeException(String.format("%s(%s) cannot be found, if you want to create please remove these maven arguments: " + - "`-Dazure.resource.create.skip=true` or `-DskipCreateAzureResource`.", resourceType, name)); - } - private AppServiceConfig buildDefaultConfig(String subscriptionId, String resourceGroup, String appName) { ComparableVersion javaVersionForProject = null; final String outputFileName = project.getBuild().getFinalName() + "." + project.getPackaging(); @@ -147,7 +126,7 @@ private IWebAppDeploymentSlot createDeploymentSlot(final IWebAppDeploymentSlot s // update existing slot is not supported in current version, will implement it later private IWebAppDeploymentSlot updateDeploymentSlot(final IWebAppDeploymentSlot slot, final DeploymentSlotConfig slotConfig) { - return slot; + throw new AzureToolkitRuntimeException("update existing slot is not supported in current version"); } private void deploy(IWebAppBase target, List artifacts) { From cc6bb0a530dec8516869e2762b0d2720904ddb18 Mon Sep 17 00:00:00 2001 From: andxu Date: Thu, 23 Sep 2021 11:36:23 +0800 Subject: [PATCH 100/126] provide resource group name in warning message --- .../toolkit/lib/appservice/task/CreateOrUpdateWebAppTask.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/task/CreateOrUpdateWebAppTask.java b/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/task/CreateOrUpdateWebAppTask.java index 2ae5f8b1af..1ae8dbc045 100644 --- a/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/task/CreateOrUpdateWebAppTask.java +++ b/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/task/CreateOrUpdateWebAppTask.java @@ -112,7 +112,7 @@ private IWebApp update(final IWebApp webApp) { final AppServicePlanConfig servicePlanConfig = config.getServicePlanConfig(); if (skipCreateAzureResource && !Azure.az(AzureAppService.class).appServicePlan(servicePlanConfig.servicePlanResourceGroup(), servicePlanConfig.servicePlanName()).exists()) { - throwForbidCreateResourceWarning("Service plan", servicePlanConfig.servicePlanName()); + throwForbidCreateResourceWarning("Service plan", servicePlanConfig.servicePlanResourceGroup() + "/" + servicePlanConfig.servicePlanName()); } throwForbidCreateResourceWarning("Web app", config.appName()); From 81be0fce6a8326ddc50310d32a463864c5321331 Mon Sep 17 00:00:00 2001 From: Hanxiao Liu Date: Thu, 23 Sep 2021 11:11:47 +0800 Subject: [PATCH 101/126] Support create new vm and configure azure spot during vm creation --- .../toolkit/lib/compute/vm/AzureImage.java | 1 - .../lib/compute/vm/DraftVirtualMachine.java | 64 +++++++++++++++---- .../vm/task/CreateVirtualMachineTask.java | 14 ++++ .../storage/model/StorageAccountConfig.java | 2 + 4 files changed, 69 insertions(+), 12 deletions(-) diff --git a/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/vm/AzureImage.java b/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/vm/AzureImage.java index 3adfb991f2..a70b264fab 100644 --- a/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/vm/AzureImage.java +++ b/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/vm/AzureImage.java @@ -39,7 +39,6 @@ public class AzureImage { public static final AzureImage REDHAT_RHEL_8_2 = new AzureImage(KnownLinuxVirtualMachineImage.REDHAT_RHEL_8_2); public static final AzureImage ORACLE_LINUX_8_1 = new AzureImage(KnownLinuxVirtualMachineImage.ORACLE_LINUX_8_1); - @Nonnull @Getter(value = AccessLevel.PACKAGE) @EqualsAndHashCode.Exclude diff --git a/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/vm/DraftVirtualMachine.java b/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/vm/DraftVirtualMachine.java index 48857c37f1..5e3a17006e 100644 --- a/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/vm/DraftVirtualMachine.java +++ b/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/vm/DraftVirtualMachine.java @@ -10,18 +10,27 @@ import com.azure.resourcemanager.compute.models.VirtualMachine.DefinitionStages.WithLinuxCreateManagedOrUnmanaged; import com.azure.resourcemanager.compute.models.VirtualMachine.DefinitionStages.WithLinuxRootPasswordOrPublicKeyManagedOrUnmanaged; import com.azure.resourcemanager.compute.models.VirtualMachine.DefinitionStages.WithProximityPlacementGroup; -import com.azure.resourcemanager.compute.models.VirtualMachine.DefinitionStages.WithPublicIPAddress; +import com.azure.resourcemanager.compute.models.VirtualMachineEvictionPolicyTypes; +import com.azure.resourcemanager.network.models.NetworkInterface; import com.azure.resourcemanager.resources.fluentcore.arm.models.HasId; +import com.azure.resourcemanager.storage.models.StorageAccount; +import com.microsoft.azure.toolkit.lib.common.bundle.AzureString; +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.utils.Utils; import com.microsoft.azure.toolkit.lib.compute.AzureResourceDraft; +import com.microsoft.azure.toolkit.lib.compute.ip.DraftPublicIpAddress; import com.microsoft.azure.toolkit.lib.compute.ip.PublicIpAddress; +import com.microsoft.azure.toolkit.lib.compute.network.DraftNetwork; import com.microsoft.azure.toolkit.lib.compute.network.Network; import com.microsoft.azure.toolkit.lib.compute.network.model.Subnet; +import com.microsoft.azure.toolkit.lib.compute.security.DraftNetworkSecurityGroup; import com.microsoft.azure.toolkit.lib.compute.security.NetworkSecurityGroup; import com.microsoft.azure.toolkit.lib.compute.vm.model.AuthenticationType; import com.microsoft.azure.toolkit.lib.compute.vm.model.AzureSpotConfig; import com.microsoft.azure.toolkit.lib.compute.vm.model.OperatingSystem; -import com.microsoft.azure.toolkit.lib.storage.service.StorageAccount; +import com.microsoft.azure.toolkit.lib.storage.StorageManagerFactory; +import com.microsoft.azure.toolkit.lib.storage.model.StorageAccountConfig; import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; @@ -31,6 +40,10 @@ import javax.annotation.Nonnull; import java.util.Optional; +import static com.azure.resourcemanager.compute.models.VirtualMachineEvictionPolicyTypes.DEALLOCATE; +import static com.azure.resourcemanager.compute.models.VirtualMachineEvictionPolicyTypes.DELETE; +import static com.microsoft.azure.toolkit.lib.compute.vm.model.AzureSpotConfig.EvictionPolicy.StopAndDeallocate; + @Getter @Setter @NoArgsConstructor @@ -47,13 +60,24 @@ public class DraftVirtualMachine extends VirtualMachine implements AzureResource private String sshKey; private AzureVirtualMachineSize size; private String availabilitySet; - private StorageAccount storageAccount; + private StorageAccountConfig storageAccount; private AzureSpotConfig azureSpotConfig; public DraftVirtualMachine(@Nonnull final String subscriptionId, @Nonnull final String resourceGroup, @Nonnull final String name) { super(getResourceId(subscriptionId, resourceGroup, name), null); } + public static DraftVirtualMachine getDefaultVirtualMachineDraft() { + final DraftVirtualMachine virtualMachine = new DraftVirtualMachine(); + virtualMachine.setRegion(Region.US_CENTRAL); + virtualMachine.setImage(AzureImage.UBUNTU_SERVER_18_04_LTS); + virtualMachine.setSize(AzureVirtualMachineSize.Standard_D2s_v3); + virtualMachine.setNetwork(DraftNetwork.getDefaultNetworkDraft()); + virtualMachine.setIpAddress(DraftPublicIpAddress.getDefaultPublicIpAddressDraft()); + virtualMachine.setSecurityGroup(new DraftNetworkSecurityGroup()); + return virtualMachine; + } + public void setSubscriptionId(final String subscriptionId) { this.subscriptionId = subscriptionId; } @@ -84,33 +108,51 @@ protected com.azure.resourcemanager.compute.models.VirtualMachine loadRemote() { VirtualMachine create(final AzureVirtualMachine module) { this.module = module; - final WithPublicIPAddress withPublicIPAddress = module.getVirtualMachinesManager(subscriptionId).define(this.getName()) + final NetworkInterface.DefinitionStages.WithCreate interfaceWithCreate = module.getVirtualMachinesManager(subscriptionId).manager().networkManager() + .networkInterfaces().define(name + "-interface-" + Utils.getTimestamp()) .withRegion(this.getRegion().getName()) .withExistingResourceGroup(this.getResourceGroup()) .withExistingPrimaryNetwork(this.getNetworkClient()) .withSubnet(subnet.getName()) .withPrimaryPrivateIPAddressDynamic(); - final WithProximityPlacementGroup withProximityPlacementGroup = ipAddress != null ? - withPublicIPAddress.withExistingPrimaryPublicIPAddress(getPublicIpAddressClient()) : withPublicIPAddress.withoutPrimaryPublicIPAddress(); + if (ipAddress != null) { + final com.azure.resourcemanager.network.models.PublicIpAddress publicIpAddressClient = getPublicIpAddressClient(); + if (publicIpAddressClient.hasAssignedNetworkInterface()) { + AzureMessager.getMessager().warning(AzureString.format("Can not assign public ip %s to vm %s, which has been assigned to %s", + ipAddress.getName(), name, publicIpAddressClient.getAssignedNetworkInterfaceIPConfiguration().name())); + } else { + interfaceWithCreate.withExistingPrimaryPublicIPAddress(getPublicIpAddressClient()); + } + } + if (securityGroup != null) { + interfaceWithCreate.withExistingNetworkSecurityGroup(getSecurityGroupClient()); + } + final NetworkInterface networkInterface = interfaceWithCreate.create(); + final WithProximityPlacementGroup withProximityPlacementGroup = module.getVirtualMachinesManager(subscriptionId).define(this.getName()) + .withRegion(this.getRegion().getName()) + .withExistingResourceGroup(this.getResourceGroup()) + .withExistingPrimaryNetworkInterface(networkInterface); final WithCreate withCreate = configureImage(withProximityPlacementGroup); if (StringUtils.isNotEmpty(availabilitySet)) { withCreate.withExistingAvailabilitySet(getAvailabilitySetClient()); } if (storageAccount != null) { - // todo: implement storage account + withCreate.withExistingStorageAccount(getStorageAccountClient()); } if (azureSpotConfig != null) { - // todo: implement azure spot related configs + final VirtualMachineEvictionPolicyTypes evictionPolicyTypes = azureSpotConfig.getPolicy() == StopAndDeallocate ? DEALLOCATE : DELETE; + withCreate.withSpotPriority(evictionPolicyTypes).withMaxPrice(azureSpotConfig.getMaximumPrice()); } this.remote = withCreate.create(); - if (securityGroup != null) { - this.remote.getPrimaryNetworkInterface().update().withExistingNetworkSecurityGroup(getSecurityGroupClient()).apply(); - } refreshStatus(); module.refresh(); return this; } + private StorageAccount getStorageAccountClient() { + return StorageManagerFactory.create(subscriptionId).storageAccounts().getById(storageAccount.getId()); + } + private WithCreate configureImage(final WithProximityPlacementGroup withCreate) { if (getImage().getOperatingSystem() == OperatingSystem.Windows) { return withCreate.withSpecificWindowsImageVersion(image.getImageReference()) diff --git a/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/vm/task/CreateVirtualMachineTask.java b/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/vm/task/CreateVirtualMachineTask.java index a639e96821..ddda3a554f 100644 --- a/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/vm/task/CreateVirtualMachineTask.java +++ b/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/vm/task/CreateVirtualMachineTask.java @@ -22,6 +22,9 @@ import com.microsoft.azure.toolkit.lib.compute.vm.DraftVirtualMachine; import com.microsoft.azure.toolkit.lib.compute.vm.VirtualMachine; import com.microsoft.azure.toolkit.lib.resource.task.CreateResourceGroupTask; +import com.microsoft.azure.toolkit.lib.storage.model.StorageAccountConfig; +import com.microsoft.azure.toolkit.lib.storage.service.AzureStorageAccount; +import com.microsoft.azure.toolkit.lib.storage.service.StorageAccount; import org.apache.commons.lang3.StringUtils; import java.util.ArrayList; @@ -59,6 +62,17 @@ private List> initTasks() { tasks.add(new AzureTask(title, () -> Azure.az(AzureNetworkSecurityGroup.class).create((DraftNetworkSecurityGroup) securityGroup))); } + // Create Storage Account + // todo: migrate storage account to draft style + final StorageAccountConfig storageAccount = draftVirtualMachine.getStorageAccount(); + if (storageAccount != null && StringUtils.isEmpty(storageAccount.getId())) { + tasks.add(new CreateResourceGroupTask(storageAccount.getSubscriptionId(), storageAccount.getResourceGroupName(), storageAccount.getRegion())); + final AzureString title = AzureString.format("Create storage account ({0})", storageAccount.getName()); + tasks.add(new AzureTask(title, () -> { + final StorageAccount result = Azure.az(AzureStorageAccount.class).create(storageAccount).commit(); + storageAccount.setId(result.id()); + })); + } // Create VM final AzureString title = AzureString.format("Create virtual machine ({0})", draftVirtualMachine.getName()); tasks.add(new AzureTask<>(title, () -> { diff --git a/azure-toolkit-libs/azure-toolkit-storage-lib/src/main/java/com/microsoft/azure/toolkit/lib/storage/model/StorageAccountConfig.java b/azure-toolkit-libs/azure-toolkit-storage-lib/src/main/java/com/microsoft/azure/toolkit/lib/storage/model/StorageAccountConfig.java index 453c3228be..2099268b2d 100644 --- a/azure-toolkit-libs/azure-toolkit-storage-lib/src/main/java/com/microsoft/azure/toolkit/lib/storage/model/StorageAccountConfig.java +++ b/azure-toolkit-libs/azure-toolkit-storage-lib/src/main/java/com/microsoft/azure/toolkit/lib/storage/model/StorageAccountConfig.java @@ -9,6 +9,7 @@ import com.microsoft.azure.toolkit.lib.common.model.ResourceGroup; import com.microsoft.azure.toolkit.lib.common.model.Subscription; import lombok.Builder; +import lombok.EqualsAndHashCode; import lombok.Getter; import lombok.Setter; @@ -17,6 +18,7 @@ @Getter @Setter @Builder +@EqualsAndHashCode public class StorageAccountConfig implements IStorageAccountEntity { private String name; From d8f58b5418bbd949e6e318eca9b2d452a835c10a Mon Sep 17 00:00:00 2001 From: andxu Date: Thu, 23 Sep 2021 12:16:06 +0800 Subject: [PATCH 102/126] show warning of updating deploy slot are not supported --- .../java/com/microsoft/azure/maven/webapp/DeployMojo.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/azure-webapp-maven-plugin/src/main/java/com/microsoft/azure/maven/webapp/DeployMojo.java b/azure-webapp-maven-plugin/src/main/java/com/microsoft/azure/maven/webapp/DeployMojo.java index be9dc82c23..35d76a9894 100644 --- a/azure-webapp-maven-plugin/src/main/java/com/microsoft/azure/maven/webapp/DeployMojo.java +++ b/azure-webapp-maven-plugin/src/main/java/com/microsoft/azure/maven/webapp/DeployMojo.java @@ -23,7 +23,6 @@ import com.microsoft.azure.toolkit.lib.appservice.utils.AppServiceConfigUtils; import com.microsoft.azure.toolkit.lib.common.bundle.AzureString; import com.microsoft.azure.toolkit.lib.common.exception.AzureExecutionException; -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.utils.Utils; import org.apache.commons.lang3.ObjectUtils; @@ -126,7 +125,8 @@ private IWebAppDeploymentSlot createDeploymentSlot(final IWebAppDeploymentSlot s // update existing slot is not supported in current version, will implement it later private IWebAppDeploymentSlot updateDeploymentSlot(final IWebAppDeploymentSlot slot, final DeploymentSlotConfig slotConfig) { - throw new AzureToolkitRuntimeException("update existing slot is not supported in current version"); + AzureMessager.getMessager().warning("update existing slot is not supported in current version"); + return slot; } private void deploy(IWebAppBase target, List artifacts) { From ce22f785de842ec5d5a6da4b81b44f9b4ac6251f Mon Sep 17 00:00:00 2001 From: andxu Date: Thu, 23 Sep 2021 12:24:50 +0800 Subject: [PATCH 103/126] redefine the warning message --- .../com/microsoft/azure/toolkit/lib/appservice/utils/Utils.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/utils/Utils.java b/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/utils/Utils.java index 44ef8ca156..9ffa3f7c96 100644 --- a/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/utils/Utils.java +++ b/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/utils/Utils.java @@ -82,7 +82,7 @@ public static void mergeObjects(T to, T from) throws IllegalAccessException } public static void throwForbidCreateResourceWarning(String resourceType, String name) { - throw new AzureToolkitRuntimeException(String.format("%s(%s) cannot be found, if you want to create please remove these maven arguments: " + + throw new AzureToolkitRuntimeException(String.format("%s(%s) cannot be found, if you want to create azure resources please remove command line arguments: " + "`-Dazure.resource.create.skip=true` or `-DskipCreateAzureResource`.", resourceType, name)); } } From 2da4e6df0675483dc8d016a3d3b475d3d71dc747 Mon Sep 17 00:00:00 2001 From: andxu Date: Thu, 23 Sep 2021 12:38:14 +0800 Subject: [PATCH 104/126] change default region for functions --- .../microsoft/azure/maven/function/AbstractFunctionMojo.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/azure-functions-maven-plugin/src/main/java/com/microsoft/azure/maven/function/AbstractFunctionMojo.java b/azure-functions-maven-plugin/src/main/java/com/microsoft/azure/maven/function/AbstractFunctionMojo.java index 52e39be377..f85356cd0c 100644 --- a/azure-functions-maven-plugin/src/main/java/com/microsoft/azure/maven/function/AbstractFunctionMojo.java +++ b/azure-functions-maven-plugin/src/main/java/com/microsoft/azure/maven/function/AbstractFunctionMojo.java @@ -65,7 +65,7 @@ public abstract class AbstractFunctionMojo extends AbstractAppServiceMojo { /** * App Service region, which will only be used to create App Service at the first time. */ - @Parameter(property = "functions.region", defaultValue = "westeurope") + @Parameter(property = "functions.region") protected String region; @Parameter(property = "functions.runtime") From 92e7f4a698ce07c37a0e5ad4c66d052f2b26b264 Mon Sep 17 00:00:00 2001 From: andxu Date: Thu, 23 Sep 2021 14:03:10 +0800 Subject: [PATCH 105/126] Remove the local debug code --- .../toolkit/lib/appservice/task/CreateOrUpdateWebAppTask.java | 1 - 1 file changed, 1 deletion(-) diff --git a/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/task/CreateOrUpdateWebAppTask.java b/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/task/CreateOrUpdateWebAppTask.java index 1ae8dbc045..5d986a8537 100644 --- a/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/task/CreateOrUpdateWebAppTask.java +++ b/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/task/CreateOrUpdateWebAppTask.java @@ -114,7 +114,6 @@ private IWebApp update(final IWebApp webApp) { if (skipCreateAzureResource && !Azure.az(AzureAppService.class).appServicePlan(servicePlanConfig.servicePlanResourceGroup(), servicePlanConfig.servicePlanName()).exists()) { throwForbidCreateResourceWarning("Service plan", servicePlanConfig.servicePlanResourceGroup() + "/" + servicePlanConfig.servicePlanName()); } - throwForbidCreateResourceWarning("Web app", config.appName()); final Runtime runtime = getRuntime(config.runtime()); final IAppServicePlan appServicePlan = new CreateOrUpdateAppServicePlanTask(servicePlanConfig).execute(); From 15ef17a45ec213b9c419f105c6ddeea99d565345 Mon Sep 17 00:00:00 2001 From: andxu Date: Thu, 23 Sep 2021 14:16:56 +0800 Subject: [PATCH 106/126] Add change log and update readme version --- azure-functions-maven-plugin/CHANGELOG.md | 5 +++++ azure-webapp-maven-plugin/CHANGELOG.md | 10 +++++++++- azure-webapp-maven-plugin/README.md | 4 ++-- 3 files changed, 16 insertions(+), 3 deletions(-) diff --git a/azure-functions-maven-plugin/CHANGELOG.md b/azure-functions-maven-plugin/CHANGELOG.md index 04be11bbd9..61ac4bf198 100644 --- a/azure-functions-maven-plugin/CHANGELOG.md +++ b/azure-functions-maven-plugin/CHANGELOG.md @@ -22,6 +22,11 @@ All notable changes to the "Maven Plugin for Azure Function" will be documented - [1.2.1](#121) - [1.2.0](#120) +## 1.14.0 +- Support default value for region/pricing tier/javaVersion [#1755](https://github.com/microsoft/azure-maven-plugins/pull/1761) +- Support username and password in proxy [#1677](https://github.com/microsoft/azure-maven-plugins/pull/1677) +- Fix warning message of `illegal reflective access from groovy` [#1763](https://github.com/microsoft/azure-maven-plugins/pull/1763) + ## 1.13.0 - Support skip function extensions installation [#1616](https://github.com/microsoft/azure-maven-plugins/issues/1616) (Thanks @sschmeck) diff --git a/azure-webapp-maven-plugin/CHANGELOG.md b/azure-webapp-maven-plugin/CHANGELOG.md index 798e874c59..697f6d60ff 100644 --- a/azure-webapp-maven-plugin/CHANGELOG.md +++ b/azure-webapp-maven-plugin/CHANGELOG.md @@ -1,6 +1,7 @@ # Change Log All notable changes to the "Maven Plugin for Azure App Service" will be documented in this file. - [Change Log](#change-log) + - [2.2.0](#210) - [2.1.0](#210) - [2.0.0](#200) - [1.15.0](#1150) @@ -26,6 +27,14 @@ All notable changes to the "Maven Plugin for Azure App Service" will be document - [1.1.0](#110) - [1.0.0](#100) +## 2.2.0 +- Support default value for region/pricing tier/webContainer/javaVersion [#1755](https://github.com/microsoft/azure-maven-plugins/pull/1755) +- Support flag to skip create azure resources PR [#1762](https://github.com/microsoft/azure-maven-plugins/pull/1762), Issue [#1651](https://github.com/microsoft/azure-maven-plugins/issues/1651) +- Support username and password in proxy [#1677](https://github.com/microsoft/azure-maven-plugins/pull/1677) +- Check whether webapp name is available before creating webapp [#1728](https://github.com/microsoft/azure-maven-plugins/pull/1728) +- Remove unsupported JBoss 7.2 Runtime(use JBoss 7 instead) [#1751](https://github.com/microsoft/azure-maven-plugins/pull/1751) +- Fix warning message of `illegal reflective access from groovy` [#1763](https://github.com/microsoft/azure-maven-plugins/pull/1763) + ## 2.1.0 - Support static validation against json schema [#1647](https://github.com/microsoft/azure-maven-plugins/pull/1647) - Support custom values for pricingTier/region/webContainer/javaVersion [#1643](https://github.com/microsoft/azure-maven-plugins/pull/1643) @@ -138,4 +147,3 @@ All notable changes to the "Maven Plugin for Azure App Service" will be document ## 1.0.0 - Add the support for deploying Web App to an existing App Service Plan - diff --git a/azure-webapp-maven-plugin/README.md b/azure-webapp-maven-plugin/README.md index 1a9fc727da..385104014a 100644 --- a/azure-webapp-maven-plugin/README.md +++ b/azure-webapp-maven-plugin/README.md @@ -25,7 +25,7 @@ Mavan plugins supports Azure Cli and some other auth methods, see [Authenticatio You can prepare your application for Azure Web App easily with one command: ```shell -mvn com.microsoft.azure:azure-webapp-maven-plugin:2.1.0:config +mvn com.microsoft.azure:azure-webapp-maven-plugin:2.2.0:config ``` This command adds a `azure-webapp-maven-plugin` plugin and related configuration by prompting you to select an existing Azure Web App or create a new one. Then you can deploy your Java app to Azure using the following command: @@ -39,7 +39,7 @@ Here is a typical configuration for Azure Web App Maven Plugin: com.microsoft.azure azure-webapp-maven-plugin - 2.1.0 + 2.2.0 111111-11111-11111-1111111 spring-boot-xxxxxxxxxx-rg From 4499a2d8861d0a2f83920482fb0ea8787357e64d Mon Sep 17 00:00:00 2001 From: andxu Date: Thu, 23 Sep 2021 15:15:41 +0800 Subject: [PATCH 107/126] remove track1 sdk dependency --- azure-toolkit-libs/azure-toolkit-appservice-lib/pom.xml | 5 ----- 1 file changed, 5 deletions(-) diff --git a/azure-toolkit-libs/azure-toolkit-appservice-lib/pom.xml b/azure-toolkit-libs/azure-toolkit-appservice-lib/pom.xml index 16b9d64e39..977d77423d 100644 --- a/azure-toolkit-libs/azure-toolkit-appservice-lib/pom.xml +++ b/azure-toolkit-libs/azure-toolkit-appservice-lib/pom.xml @@ -141,11 +141,6 @@ 1.7.12 compile - - com.microsoft.azure - azure - compile - com.microsoft.azure azure-toolkit-common-lib From 31e9c620aa996cd2154223d05e4eff720808754e Mon Sep 17 00:00:00 2001 From: andxu Date: Thu, 23 Sep 2021 15:28:31 +0800 Subject: [PATCH 108/126] add azure-storage dependency in appservice-lib --- azure-toolkit-libs/azure-toolkit-appservice-lib/pom.xml | 5 +++++ azure-toolkit-libs/pom.xml | 1 - 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/azure-toolkit-libs/azure-toolkit-appservice-lib/pom.xml b/azure-toolkit-libs/azure-toolkit-appservice-lib/pom.xml index 977d77423d..695a993359 100644 --- a/azure-toolkit-libs/azure-toolkit-appservice-lib/pom.xml +++ b/azure-toolkit-libs/azure-toolkit-appservice-lib/pom.xml @@ -38,6 +38,11 @@ azure-resourcemanager + + com.microsoft.azure + azure-storage + + com.microsoft.azure azure-toolkit-common-lib diff --git a/azure-toolkit-libs/pom.xml b/azure-toolkit-libs/pom.xml index f50653cbad..f40e1271b4 100644 --- a/azure-toolkit-libs/pom.xml +++ b/azure-toolkit-libs/pom.xml @@ -78,7 +78,6 @@ 1.6.2 12.9.1 1.4.2 - 11.0.1 4.2.8 4.2.8 4.1.8 From 3b06f5e310eaadb8ab161861fa3e17465ad4a443 Mon Sep 17 00:00:00 2001 From: andxu Date: Thu, 23 Sep 2021 16:45:40 +0800 Subject: [PATCH 109/126] remove the dependency of azure-resourcemanager and track 1 azure --- .../src/it/3-eventhub-trigger/cleanup.groovy | 32 ---- .../src/it/3-eventhub-trigger/pom.xml | 115 -------------- .../src/it/3-eventhub-trigger/setup.groovy | 33 ---- .../microsoft/azure/EventHubTriggerJava.java | 23 --- .../invoker/storage/EventHubProcesser.java | 150 ------------------ azure-maven-plugin-lib/pom.xml | 5 - .../azure/maven/AbstractAzureMojo.java | 13 -- .../azure/maven/auth/AzureClientFactory.java | 26 --- .../azure-toolkit-appservice-lib/pom.xml | 2 +- azure-toolkit-libs/pom.xml | 23 +-- azure-webapp-maven-plugin/CHANGELOG.md | 1 - 11 files changed, 2 insertions(+), 421 deletions(-) delete mode 100644 azure-functions-maven-plugin/src/it/3-eventhub-trigger/cleanup.groovy delete mode 100644 azure-functions-maven-plugin/src/it/3-eventhub-trigger/pom.xml delete mode 100644 azure-functions-maven-plugin/src/it/3-eventhub-trigger/setup.groovy delete mode 100644 azure-functions-maven-plugin/src/it/3-eventhub-trigger/src/main/java/com/microsoft/azure/EventHubTriggerJava.java delete mode 100644 azure-functions-maven-plugin/src/test/java/com/microsoft/azure/maven/function/invoker/storage/EventHubProcesser.java delete mode 100644 azure-maven-plugin-lib/src/main/java/com/microsoft/azure/maven/auth/AzureClientFactory.java diff --git a/azure-functions-maven-plugin/src/it/3-eventhub-trigger/cleanup.groovy b/azure-functions-maven-plugin/src/it/3-eventhub-trigger/cleanup.groovy deleted file mode 100644 index 2e5b53b5e4..0000000000 --- a/azure-functions-maven-plugin/src/it/3-eventhub-trigger/cleanup.groovy +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - */ - -import com.microsoft.azure.maven.function.invoker.storage.EventHubProcesser -import com.microsoft.azure.maven.function.invoker.CommonUtils - -String storageName = "cihub${timestamp}" -String namespaceName = "FunctionCIEventHubNamespace-${timestamp}" -String resourceGroupName = "maven-functions-it-${timestamp}-rg-3" - -EventHubProcesser eventHubProcesser = null -try { - eventHubProcesser = new EventHubProcesser(resourceGroupName, namespaceName, storageName); - // verify - CommonUtils.runVerification(new Runnable() { - @Override - void run() { - eventHubProcesser.sendMessageToEventHub("trigger", "CIInput") - sleep(10 * 1000 /* ms */) - assert eventHubProcesser.getMessageFromEventHub("output").get(0) == "CITest" - } - }) -} finally { - if (eventHubProcesser != null) { - eventHubProcesser.close() - } -} -CommonUtils.deleteAzureResourceGroup(resourceGroupName, false) -return true - diff --git a/azure-functions-maven-plugin/src/it/3-eventhub-trigger/pom.xml b/azure-functions-maven-plugin/src/it/3-eventhub-trigger/pom.xml deleted file mode 100644 index 976c142edc..0000000000 --- a/azure-functions-maven-plugin/src/it/3-eventhub-trigger/pom.xml +++ /dev/null @@ -1,115 +0,0 @@ - - - 4.0.0 - - com.microsoft.azure - azure-java-functions - 1.0-SNAPSHOT - jar - - Azure Java Functions - - - UTF-8 - 1.8 - 1.8 - maven-functions-it-${timestamp}-3 - westus - ${project.build.directory}/azure-functions/${functionAppName} - maven-functions-it-${timestamp}-rg-3 - - - - - com.microsoft.azure.functions - azure-functions-java-library - 1.2.0 - - - com.microsoft.azure - azure-eventhubs - 1.2.0 - - - com.microsoft.azure - azure-eventhubs-eph - 2.0.1 - - - com.microsoft.azure - azure - 1.18.0 - - - org.codehaus.plexus - plexus-utils - 3.0.24 - - - - - - - - maven-resources-plugin - 3.0.2 - - - @project.groupId@ - @project.artifactId@ - @project.version@ - - - - - - - @project.groupId@ - @project.artifactId@ - - - azure-auth - - ${functionResourceGroup} - ${functionAppName} - ${functionAppRegion} - - - - package-functions - - package - - - - - - org.apache.maven.plugins - maven-dependency-plugin - 3.0.2 - - - copy-dependencies - prepare-package - - copy-dependencies - - - ${stagingDirectory}/lib - false - false - true - runtime - azure-functions-java-library - - - - - - - - - - diff --git a/azure-functions-maven-plugin/src/it/3-eventhub-trigger/setup.groovy b/azure-functions-maven-plugin/src/it/3-eventhub-trigger/setup.groovy deleted file mode 100644 index a7ad21f1df..0000000000 --- a/azure-functions-maven-plugin/src/it/3-eventhub-trigger/setup.groovy +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - */ - -import com.microsoft.azure.maven.function.invoker.CommonUtils -import com.microsoft.azure.maven.function.invoker.storage.EventHubProcesser - -String functionName = "maven-functions-it-${timestamp}-3" -String storageName = "cihub${timestamp}" -String namespaceName = "FunctionCIEventHubNamespace-${timestamp}" -String resourceGroupName = "maven-functions-it-${timestamp}-rg-3" - -CommonUtils.azureLogin() -CommonUtils.deleteAzureResourceGroup(resourceGroupName, true) - -// Create EventHub -EventHubProcesser eventHubProcesser = null -eventHubProcesser = new EventHubProcesser(resourceGroupName, namespaceName, storageName); -eventHubProcesser.createOrGetEventHubByName("trigger") -eventHubProcesser.createOrGetEventHubByName("output") - -// Get connnection string of EventHub and save it to pom -def connectionString = eventHubProcesser.getEventHubConnectionString() - -// Create FunctionApp and set eventhub connection string -CommonUtils.executeCommand("az functionapp create --resource-group ${resourceGroupName} --consumption-plan-location westus " + - "--name ${functionName} --storage-account ${storageName}") - -CommonUtils.executeCommand("az webapp config appsettings set --name ${functionName} --resource-group ${resourceGroupName} --settings CIEventHubConnection=\"${connectionString}\"") - -return true - diff --git a/azure-functions-maven-plugin/src/it/3-eventhub-trigger/src/main/java/com/microsoft/azure/EventHubTriggerJava.java b/azure-functions-maven-plugin/src/it/3-eventhub-trigger/src/main/java/com/microsoft/azure/EventHubTriggerJava.java deleted file mode 100644 index 53b39057ae..0000000000 --- a/azure-functions-maven-plugin/src/it/3-eventhub-trigger/src/main/java/com/microsoft/azure/EventHubTriggerJava.java +++ /dev/null @@ -1,23 +0,0 @@ -package com.microsoft.azure; - -import com.microsoft.azure.functions.annotation.*; -import com.microsoft.azure.functions.*; - -/** - * Azure Functions with Event Hub trigger. - */ -public class EventHubTriggerJava { - /** - * This function will be invoked when an event is received from Event Hub. - */ - @FunctionName("EventHubTriggerJava") - public void run( - @EventHubTrigger(name = "message", eventHubName = "trigger", connection = "CIEventHubConnection", consumerGroup = "$Default") String message, - @EventHubOutput(name = "result", eventHubName = "output", connection = "CIEventHubConnection") OutputBinding result, - final ExecutionContext context - ) { - if(message.contains("CIInput")) { - result.setValue("CITest"); - } - } -} diff --git a/azure-functions-maven-plugin/src/test/java/com/microsoft/azure/maven/function/invoker/storage/EventHubProcesser.java b/azure-functions-maven-plugin/src/test/java/com/microsoft/azure/maven/function/invoker/storage/EventHubProcesser.java deleted file mode 100644 index 85abe8f100..0000000000 --- a/azure-functions-maven-plugin/src/test/java/com/microsoft/azure/maven/function/invoker/storage/EventHubProcesser.java +++ /dev/null @@ -1,150 +0,0 @@ -/* - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - */ - -package com.microsoft.azure.maven.function.invoker.storage; - -import com.google.gson.Gson; -import com.microsoft.azure.eventhubs.ConnectionStringBuilder; -import com.microsoft.azure.eventhubs.EventData; -import com.microsoft.azure.eventhubs.EventHubClient; -import com.microsoft.azure.eventhubs.EventPosition; -import com.microsoft.azure.eventhubs.PartitionReceiver; -import com.microsoft.azure.management.Azure; -import com.microsoft.azure.management.eventhub.EventHub; -import com.microsoft.azure.management.eventhub.EventHubNamespace; -import com.microsoft.azure.management.resources.ResourceGroup; -import com.microsoft.azure.management.resources.fluentcore.arm.Region; -import com.microsoft.azure.management.storage.StorageAccount; -import com.microsoft.azure.management.storage.StorageAccountSkuType; -import com.microsoft.azure.maven.function.invoker.CommonUtils; - -import java.nio.charset.Charset; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Optional; -import java.util.concurrent.CopyOnWriteArrayList; -import java.util.concurrent.Executors; -import java.util.concurrent.ScheduledExecutorService; - -public class EventHubProcesser { - - private static final String SAS_KAY_NAME = "RootManageSharedAccessKey"; - - private EventHubNamespace eventHubNamespace; - private StorageAccount storageAccount; - private ResourceGroup resourceGroup; - - private ScheduledExecutorService executorService = Executors.newScheduledThreadPool(8); - private Map eventHubClientMap = new HashMap<>(); - - public EventHubProcesser(String resourceGroupName, String namespaceName, String storageAccountName) - throws Exception { - final Azure azureClint = CommonUtils.getAzureClient(); - - if (azureClint.resourceGroups().contain(resourceGroupName)) { - resourceGroup = azureClint.resourceGroups().getByName(resourceGroupName); - } else { - resourceGroup = azureClint.resourceGroups().define(resourceGroupName).withRegion(Region.US_EAST).create(); - } - - final boolean isEventHubNamespaceExist = azureClint.eventHubNamespaces().list().stream() - .anyMatch(namespace -> namespace.name().equals(namespaceName) && - namespace.resourceGroupName().equals(resourceGroupName)); - if (isEventHubNamespaceExist) { - eventHubNamespace = azureClint.eventHubNamespaces().getByResourceGroup(resourceGroupName, namespaceName); - } else { - eventHubNamespace = azureClint.eventHubNamespaces() - .define(namespaceName).withRegion(resourceGroup.region()) - .withExistingResourceGroup(resourceGroupName).create(); - } - - storageAccount = azureClint.storageAccounts().getByResourceGroup(resourceGroupName, storageAccountName); - if (storageAccount == null) { - storageAccount = azureClint.storageAccounts() - .define(storageAccountName).withRegion(resourceGroup.region()) - .withExistingResourceGroup(resourceGroup) - .withSku(StorageAccountSkuType.STANDARD_LRS) - .withGeneralPurposeAccountKindV2().create(); - } - } - - public EventHub createOrGetEventHubByName(final String eventHubName) throws Exception { - final Azure azureClient = CommonUtils.getAzureClient(); - final Optional eventHub = eventHubNamespace.listEventHubs().stream() - .filter(eventHubEntry -> eventHubEntry.name().equals(eventHubName)).findFirst(); - return eventHub.isPresent() ? eventHub.get() : azureClient.eventHubs().define(eventHubName) - .withExistingNamespace(eventHubNamespace) - .withExistingStorageAccountForCapturedData(storageAccount, eventHubName) - .withDataCaptureEnabled().create(); - } - - public void sendMessageToEventHub(final String eventHubName, final String message) throws Exception { - final EventHubClient eventHubClient = getEventHubClientByName(eventHubName); - final Gson gson = new Gson(); - final byte[] payloadBytes = gson.toJson(message).getBytes(Charset.defaultCharset()); - final EventData sendEvent = EventData.create(payloadBytes); - eventHubClient.send(sendEvent).get(); - } - - public List getMessageFromEventHub(final String eventHubName) throws Exception { - final List result = new CopyOnWriteArrayList<>(); - final EventHubClient eventHubClient = getEventHubClientByName(eventHubName); - final List partitionIds = Arrays.asList(eventHubClient.getRuntimeInformation().get().getPartitionIds()); - partitionIds.parallelStream() - .forEach(partitionId -> result.addAll(getMessageFromPartition(eventHubClient, partitionId))); - return result; - } - - public List getMessageFromPartition(final EventHubClient eventHubClient, final String partitionId) { - final List result = new ArrayList<>(); - try { - final PartitionReceiver partitionReceiver = eventHubClient - .createReceiver(EventHubClient.DEFAULT_CONSUMER_GROUP_NAME, - partitionId, EventPosition.fromStartOfStream()).get(); - final Iterable data = partitionReceiver.receive(10).get(); - if (data != null) { - data.forEach(eventData -> result.add(new String(eventData.getBytes()))); - } - partitionReceiver.closeSync(); - } catch (Exception e) { - // When exception, just return empty List - e.printStackTrace(); - } - return result; - } - - public void close() throws Exception { - for (final EventHubClient eventHubClient : eventHubClientMap.values()) { - eventHubClient.closeSync(); - } - executorService.shutdown(); - } - - private EventHubClient getEventHubClientByName(final String eventHubName) throws Exception { - if (eventHubClientMap.containsKey(eventHubName)) { - return eventHubClientMap.get(eventHubName); - } else { - final ConnectionStringBuilder connStr = new ConnectionStringBuilder() - .setNamespaceName(eventHubNamespace.name()) - .setEventHubName(eventHubName) - .setSasKeyName(SAS_KAY_NAME) - .setSasKey(getEventHubKey()); - final EventHubClient eventHubClient = EventHubClient.createFromConnectionStringSync(connStr.toString(), executorService); - eventHubClientMap.put(eventHubName, eventHubClient); - return eventHubClient; - } - } - - private String getEventHubKey() { - return eventHubNamespace.listAuthorizationRules().get(0).getKeys().primaryKey(); - } - - public String getEventHubConnectionString() { - return eventHubNamespace.listAuthorizationRules().get(0).getKeys().primaryConnectionString(); - } -} diff --git a/azure-maven-plugin-lib/pom.xml b/azure-maven-plugin-lib/pom.xml index 9a055daf5a..7b02fa4829 100644 --- a/azure-maven-plugin-lib/pom.xml +++ b/azure-maven-plugin-lib/pom.xml @@ -159,11 +159,6 @@ lombok provided - - com.microsoft.azure - azure - compile - com.github.java-json-tools json-schema-validator diff --git a/azure-maven-plugin-lib/src/main/java/com/microsoft/azure/maven/AbstractAzureMojo.java b/azure-maven-plugin-lib/src/main/java/com/microsoft/azure/maven/AbstractAzureMojo.java index 658f6041da..8fdfae38b6 100755 --- a/azure-maven-plugin-lib/src/main/java/com/microsoft/azure/maven/AbstractAzureMojo.java +++ b/azure-maven-plugin-lib/src/main/java/com/microsoft/azure/maven/AbstractAzureMojo.java @@ -221,9 +221,6 @@ public abstract class AbstractAzureMojo extends AbstractMojo { @JsonIgnore private Account azureAccount; - @JsonIgnore - private com.microsoft.azure.management.Azure azure; - @Getter @JsonIgnore protected AzureTelemetryClient telemetryProxy; @@ -440,16 +437,6 @@ protected void initTelemetryProxy() { } //endregion - protected static void printCurrentSubscription(com.microsoft.azure.management.Azure azure) { - if (azure == null) { - return; - } - final com.microsoft.azure.management.resources.Subscription subscription = azure.getCurrentSubscription(); - if (subscription != null) { - Log.info(String.format(SUBSCRIPTION_TEMPLATE, TextUtils.cyan(subscription.displayName()), TextUtils.cyan(subscription.subscriptionId()))); - } - } - public Map getTelemetryProperties() { final Map map = new HashMap<>(); map.put(INSTALLATION_ID_KEY, getInstallationId()); diff --git a/azure-maven-plugin-lib/src/main/java/com/microsoft/azure/maven/auth/AzureClientFactory.java b/azure-maven-plugin-lib/src/main/java/com/microsoft/azure/maven/auth/AzureClientFactory.java deleted file mode 100644 index 887ea469c5..0000000000 --- a/azure-maven-plugin-lib/src/main/java/com/microsoft/azure/maven/auth/AzureClientFactory.java +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - */ - -package com.microsoft.azure.maven.auth; - -import com.microsoft.azure.management.Azure; -import com.microsoft.azure.management.Azure.Authenticated; -import com.microsoft.azure.toolkit.lib.auth.Account; -import com.microsoft.azure.toolkit.lib.auth.AzureAccount; -import com.microsoft.azure.toolkit.lib.auth.exception.AzureLoginException; -import org.apache.commons.lang3.StringUtils; - -import java.io.IOException; - -public class AzureClientFactory { - public static Azure getAzureClient(String userAgent, String defaultSubscriptionId) throws IOException, AzureLoginException { - final Account account = com.microsoft.azure.toolkit.lib.Azure.az(AzureAccount.class).account(); - final Authenticated authenticated = Azure.configure().withUserAgent(userAgent) - .authenticate(account.getTokenCredentialV1(defaultSubscriptionId)); - - return StringUtils.isEmpty(defaultSubscriptionId) ? authenticated.withDefaultSubscription() : - authenticated.withSubscription(defaultSubscriptionId); - } -} diff --git a/azure-toolkit-libs/azure-toolkit-appservice-lib/pom.xml b/azure-toolkit-libs/azure-toolkit-appservice-lib/pom.xml index 695a993359..08ed9f6e72 100644 --- a/azure-toolkit-libs/azure-toolkit-appservice-lib/pom.xml +++ b/azure-toolkit-libs/azure-toolkit-appservice-lib/pom.xml @@ -35,7 +35,7 @@ com.azure.resourcemanager - azure-resourcemanager + azure-resourcemanager-appservice diff --git a/azure-toolkit-libs/pom.xml b/azure-toolkit-libs/pom.xml index f40e1271b4..e519878a13 100644 --- a/azure-toolkit-libs/pom.xml +++ b/azure-toolkit-libs/pom.xml @@ -216,17 +216,6 @@ ${azure.toolkit-lib.version} - - com.microsoft.azure - azure - ${azure.version} - - - javax.xml.bind - jaxb-api - - - com.microsoft.azure azure-annotations @@ -247,11 +236,6 @@ azure-client-authentication ${azure.client.version} - - com.microsoft.azure - azure-mgmt-storage - ${azure.version} - com.microsoft.azure applicationinsights-core @@ -317,11 +301,6 @@ azure-core-http-netty ${azure.core-http-netty.version} - - com.microsoft.azure - azure-mgmt-resources - ${azure.version} - com.nimbusds oauth2-oidc-sdk @@ -516,7 +495,7 @@ com.azure.resourcemanager - azure-resourcemanager + azure-resourcemanager-appservice ${azure.resourcemanager.version} diff --git a/azure-webapp-maven-plugin/CHANGELOG.md b/azure-webapp-maven-plugin/CHANGELOG.md index 798e874c59..bd08fcde8b 100644 --- a/azure-webapp-maven-plugin/CHANGELOG.md +++ b/azure-webapp-maven-plugin/CHANGELOG.md @@ -138,4 +138,3 @@ All notable changes to the "Maven Plugin for Azure App Service" will be document ## 1.0.0 - Add the support for deploying Web App to an existing App Service Plan - From 4ad8297e080ab123d4c9babbe329c84645a27931 Mon Sep 17 00:00:00 2001 From: andxu Date: Thu, 23 Sep 2021 16:54:11 +0800 Subject: [PATCH 110/126] add track 1 azure in test scope --- azure-functions-maven-plugin/pom.xml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/azure-functions-maven-plugin/pom.xml b/azure-functions-maven-plugin/pom.xml index 122b7e2ec8..e483956f27 100644 --- a/azure-functions-maven-plugin/pom.xml +++ b/azure-functions-maven-plugin/pom.xml @@ -173,6 +173,12 @@ azure-eventhubs-eph test + + com.microsoft.azure + azure + 1.41.1 + test + org.jacoco org.jacoco.agent From 12f99028028c77433e8e4741f2f3e9650dff3b8d Mon Sep 17 00:00:00 2001 From: Mingliang Wang Date: Thu, 23 Sep 2021 23:42:47 +0800 Subject: [PATCH 111/126] popup dialog when user execute an action requiring auth. --- .../toolkit/lib/common/action/Action.java | 43 +++++++++---------- 1 file changed, 21 insertions(+), 22 deletions(-) diff --git a/azure-toolkit-libs/azure-toolkit-common-lib/src/main/java/com/microsoft/azure/toolkit/lib/common/action/Action.java b/azure-toolkit-libs/azure-toolkit-common-lib/src/main/java/com/microsoft/azure/toolkit/lib/common/action/Action.java index c640a32e4d..32f590a092 100644 --- a/azure-toolkit-libs/azure-toolkit-common-lib/src/main/java/com/microsoft/azure/toolkit/lib/common/action/Action.java +++ b/azure-toolkit-libs/azure-toolkit-common-lib/src/main/java/com/microsoft/azure/toolkit/lib/common/action/Action.java @@ -14,6 +14,7 @@ import com.microsoft.azure.toolkit.lib.common.telemetry.AzureTelemetry; import com.microsoft.azure.toolkit.lib.common.view.IView; import lombok.Getter; +import lombok.Setter; import lombok.experimental.Accessors; import org.apache.commons.lang3.StringUtils; @@ -32,11 +33,14 @@ @Accessors(chain = true, fluent = true) public class Action { public static final String SOURCE = "ACTION_SOURCE"; + public static final Id REQUIRE_AUTH = Id.of("action.common.requireAuth"); @Nonnull private List, BiConsumer>> handlers = new ArrayList<>(); @Nullable @Getter private ActionView.Builder view; + @Setter + private boolean authRequired = true; public Action(@Nullable ActionView.Builder view) { this.view = view; @@ -84,13 +88,23 @@ public BiConsumer handler(D source, Object e) { } public void handle(D source, Object e) { - final BiConsumer handler = this.handler(source, e); - if (Objects.nonNull(handler)) { - final AzureString title = Optional.ofNullable(this.view).map(b -> b.title).map(t -> t.apply(source)) - .orElse(AzureString.fromString(IAzureOperation.UNKNOWN_NAME)); - final AzureTask task = new AzureTask<>(title, () -> handle(source, e, handler)); - task.setType(AzureOperation.Type.ACTION.name()); - AzureTaskManager.getInstance().runInBackground(task); + final Runnable runnable = () -> { + final BiConsumer handler = this.handler(source, e); + if (Objects.nonNull(handler)) { + final AzureString title = Optional.ofNullable(this.view).map(b -> b.title).map(t -> t.apply(source)) + .orElse(AzureString.fromString(IAzureOperation.UNKNOWN_NAME)); + final AzureTask task = new AzureTask<>(title, () -> handle(source, e, handler)); + task.setType(AzureOperation.Type.ACTION.name()); + AzureTaskManager.getInstance().runInBackground(task); + } + }; + if (this.authRequired) { + final Action requireAuth = AzureActionManager.getInstance().getAction(REQUIRE_AUTH); + if (Objects.nonNull(requireAuth)) { + requireAuth.handle(runnable, e); + } + } else { + runnable.run(); } } @@ -114,21 +128,6 @@ public void registerHandler(@Nonnull BiPredicate condition, @Nonnull B this.handlers.add(new AbstractMap.SimpleEntry<>(condition, handler)); } - @Getter - @Accessors(chain = true, fluent = true) - public static class Delegate extends Action { - @Nonnull - private final String id; - @Nonnull - private final Action action; - - public Delegate(@Nonnull Action action, @Nonnull String id) { - super(action.handlers, action.view); - this.id = id; - this.action = action; - } - } - public static class Id { @Nonnull private final String id; From 220e3cc158a07cac90858fa42f3a8b59cd5ff1e3 Mon Sep 17 00:00:00 2001 From: Hanxiao Liu Date: Thu, 23 Sep 2021 21:58:23 +0800 Subject: [PATCH 112/126] Clean up resources when meet exception while create vm --- .../lib/compute/vm/DraftVirtualMachine.java | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/vm/DraftVirtualMachine.java b/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/vm/DraftVirtualMachine.java index 5e3a17006e..38048951c1 100644 --- a/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/vm/DraftVirtualMachine.java +++ b/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/vm/DraftVirtualMachine.java @@ -5,6 +5,7 @@ package com.microsoft.azure.toolkit.lib.compute.vm; +import com.azure.core.management.exception.ManagementException; import com.azure.resourcemanager.compute.models.AvailabilitySet; import com.azure.resourcemanager.compute.models.VirtualMachine.DefinitionStages.WithCreate; import com.azure.resourcemanager.compute.models.VirtualMachine.DefinitionStages.WithLinuxCreateManagedOrUnmanaged; @@ -26,6 +27,7 @@ import com.microsoft.azure.toolkit.lib.compute.network.model.Subnet; import com.microsoft.azure.toolkit.lib.compute.security.DraftNetworkSecurityGroup; import com.microsoft.azure.toolkit.lib.compute.security.NetworkSecurityGroup; +import com.microsoft.azure.toolkit.lib.compute.security.model.SecurityRule; import com.microsoft.azure.toolkit.lib.compute.vm.model.AuthenticationType; import com.microsoft.azure.toolkit.lib.compute.vm.model.AzureSpotConfig; import com.microsoft.azure.toolkit.lib.compute.vm.model.OperatingSystem; @@ -38,6 +40,7 @@ import org.jetbrains.annotations.Nullable; import javax.annotation.Nonnull; +import java.util.Arrays; import java.util.Optional; import static com.azure.resourcemanager.compute.models.VirtualMachineEvictionPolicyTypes.DEALLOCATE; @@ -74,7 +77,9 @@ public static DraftVirtualMachine getDefaultVirtualMachineDraft() { virtualMachine.setSize(AzureVirtualMachineSize.Standard_D2s_v3); virtualMachine.setNetwork(DraftNetwork.getDefaultNetworkDraft()); virtualMachine.setIpAddress(DraftPublicIpAddress.getDefaultPublicIpAddressDraft()); - virtualMachine.setSecurityGroup(new DraftNetworkSecurityGroup()); + final DraftNetworkSecurityGroup defaultSecurityGroup = new DraftNetworkSecurityGroup(); + defaultSecurityGroup.setSecurityRuleList(Arrays.asList(SecurityRule.SSH_RULE)); + virtualMachine.setSecurityGroup(defaultSecurityGroup); return virtualMachine; } @@ -143,7 +148,13 @@ VirtualMachine create(final AzureVirtualMachine module) { final VirtualMachineEvictionPolicyTypes evictionPolicyTypes = azureSpotConfig.getPolicy() == StopAndDeallocate ? DEALLOCATE : DELETE; withCreate.withSpotPriority(evictionPolicyTypes).withMaxPrice(azureSpotConfig.getMaximumPrice()); } - this.remote = withCreate.create(); + try { + this.remote = withCreate.create(); + } catch (Exception e) { + // clean up resource once creation failed + networkInterface.manager().networkInterfaces().deleteById(networkInterface.id()); + throw e; + } refreshStatus(); module.refresh(); return this; From 09647698454ea7a2b32b9cba6f8b777e5c906bd0 Mon Sep 17 00:00:00 2001 From: Hanxiao Liu Date: Thu, 23 Sep 2021 21:59:04 +0800 Subject: [PATCH 113/126] Add hasAssignedNetworkInterface to public ip address --- .../azure/toolkit/lib/compute/ip/DraftPublicIpAddress.java | 5 +++++ .../azure/toolkit/lib/compute/ip/PublicIpAddress.java | 4 ++++ .../azure/toolkit/lib/compute/vm/DraftVirtualMachine.java | 1 - 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/ip/DraftPublicIpAddress.java b/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/ip/DraftPublicIpAddress.java index 515d87a3bd..3c9a062a34 100644 --- a/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/ip/DraftPublicIpAddress.java +++ b/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/ip/DraftPublicIpAddress.java @@ -48,6 +48,11 @@ public void setName(final String name) { this.name = name; } + @Override + public boolean hasAssignedNetworkInterface() { + return Optional.ofNullable(remote).map(ignore -> super.hasAssignedNetworkInterface()).orElse(false); + } + @Override public String getId() { return Optional.ofNullable(remote).map(HasId::id).orElseGet(() -> getResourceId(subscriptionId, resourceGroup, name)); diff --git a/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/ip/PublicIpAddress.java b/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/ip/PublicIpAddress.java index 2e8904bfe2..187f690f5a 100644 --- a/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/ip/PublicIpAddress.java +++ b/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/ip/PublicIpAddress.java @@ -42,6 +42,10 @@ public Region getRegion() { return Region.fromName(remote().regionName()); } + public boolean hasAssignedNetworkInterface() { + return remote().hasAssignedNetworkInterface(); + } + @Nullable @Override protected com.azure.resourcemanager.network.models.PublicIpAddress loadRemote() { diff --git a/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/vm/DraftVirtualMachine.java b/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/vm/DraftVirtualMachine.java index 38048951c1..e6a5cb54e7 100644 --- a/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/vm/DraftVirtualMachine.java +++ b/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/vm/DraftVirtualMachine.java @@ -5,7 +5,6 @@ package com.microsoft.azure.toolkit.lib.compute.vm; -import com.azure.core.management.exception.ManagementException; import com.azure.resourcemanager.compute.models.AvailabilitySet; import com.azure.resourcemanager.compute.models.VirtualMachine.DefinitionStages.WithCreate; import com.azure.resourcemanager.compute.models.VirtualMachine.DefinitionStages.WithLinuxCreateManagedOrUnmanaged; From 93adbcc3f3db21eef7e300ee83fd2b51be1bd465 Mon Sep 17 00:00:00 2001 From: Hanxiao Liu Date: Sun, 26 Sep 2021 09:54:21 +0800 Subject: [PATCH 114/126] Make status of azure resource to be async --- .../toolkit/lib/compute/AbstractAzureResource.java | 10 ++++++---- .../toolkit/lib/compute/ip/DraftPublicIpAddress.java | 4 ++-- .../toolkit/lib/compute/network/DraftNetwork.java | 4 ++-- .../compute/security/DraftNetworkSecurityGroup.java | 5 ++--- .../toolkit/lib/compute/vm/DraftVirtualMachine.java | 4 ++-- 5 files changed, 14 insertions(+), 13 deletions(-) diff --git a/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/AbstractAzureResource.java b/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/AbstractAzureResource.java index b01e64d1f3..f927421e88 100644 --- a/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/AbstractAzureResource.java +++ b/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/AbstractAzureResource.java @@ -93,11 +93,13 @@ protected final T remote() { } @Override - public final String status() { - if (Objects.isNull(this.status)) { - this.status(loadStatus()); + public String status() { + if (Objects.nonNull(this.status)) { + return this.status; + } else { + this.refreshStatus(); + return Status.LOADING; } - return this.status; } public final void refreshStatus() { diff --git a/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/ip/DraftPublicIpAddress.java b/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/ip/DraftPublicIpAddress.java index 3c9a062a34..faa2b40545 100644 --- a/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/ip/DraftPublicIpAddress.java +++ b/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/ip/DraftPublicIpAddress.java @@ -71,8 +71,8 @@ PublicIpAddress create(AzurePublicIpAddress module) { } @Override - protected String loadStatus() { - return Optional.ofNullable(remote).map(ignore -> super.loadStatus()).orElse(Status.DRAFT); + public String status() { + return Optional.ofNullable(remote).map(ignore -> super.status()).orElse(Status.DRAFT); } @Nullable diff --git a/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/network/DraftNetwork.java b/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/network/DraftNetwork.java index 8b15d5e26c..244866984a 100644 --- a/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/network/DraftNetwork.java +++ b/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/network/DraftNetwork.java @@ -86,8 +86,8 @@ public List subnets() { } @Override - protected String loadStatus() { - return Optional.ofNullable(remote).map(ignore -> super.loadStatus()).orElse(Status.DRAFT); + public String status() { + return Optional.ofNullable(remote).map(ignore -> super.status()).orElse(Status.DRAFT); } @Nullable diff --git a/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/security/DraftNetworkSecurityGroup.java b/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/security/DraftNetworkSecurityGroup.java index 156a9231f5..5157cdca2f 100644 --- a/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/security/DraftNetworkSecurityGroup.java +++ b/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/security/DraftNetworkSecurityGroup.java @@ -12,7 +12,6 @@ import com.azure.resourcemanager.network.models.NetworkSecurityRule.DefinitionStages.WithSourcePort; import com.azure.resourcemanager.network.models.SecurityRuleProtocol; import com.azure.resourcemanager.resources.fluentcore.arm.models.HasId; -import com.microsoft.azure.toolkit.lib.common.entity.IAzureBaseResource; import com.microsoft.azure.toolkit.lib.common.model.Region; import com.microsoft.azure.toolkit.lib.compute.AzureResourceDraft; import com.microsoft.azure.toolkit.lib.compute.security.model.SecurityRule; @@ -96,8 +95,8 @@ private static void applySecurityRule(final WithCreate withCreate, final Securit } @Override - protected String loadStatus() { - return Optional.ofNullable(remote).map(ignore -> super.loadStatus()).orElse(IAzureBaseResource.Status.DRAFT); + public String status() { + return Optional.ofNullable(remote).map(ignore -> super.status()).orElse(Status.DRAFT); } @Nullable diff --git a/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/vm/DraftVirtualMachine.java b/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/vm/DraftVirtualMachine.java index e6a5cb54e7..479451d8fb 100644 --- a/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/vm/DraftVirtualMachine.java +++ b/azure-toolkit-libs/azure-toolkit-compute-lib/src/main/java/com/microsoft/azure/toolkit/lib/compute/vm/DraftVirtualMachine.java @@ -100,8 +100,8 @@ public String getId() { } @Override - protected String loadStatus() { - return Optional.ofNullable(remote).map(ignore -> super.loadStatus()).orElse(Status.DRAFT); + public String status() { + return Optional.ofNullable(remote).map(ignore -> super.status()).orElse(Status.DRAFT); } @Nullable From 91c90f52f0b26700699fafeb3a38f70c11658900 Mon Sep 17 00:00:00 2001 From: andxu Date: Fri, 24 Sep 2021 15:52:44 +0800 Subject: [PATCH 115/126] add telemetry for skipAzureResourceCreate --- .../com/microsoft/azure/maven/webapp/AbstractWebAppMojo.java | 3 +++ .../java/com/microsoft/azure/maven/webapp/DeployMojoTest.java | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/azure-webapp-maven-plugin/src/main/java/com/microsoft/azure/maven/webapp/AbstractWebAppMojo.java b/azure-webapp-maven-plugin/src/main/java/com/microsoft/azure/maven/webapp/AbstractWebAppMojo.java index 6cfedd9f87..3a1c6328c1 100644 --- a/azure-webapp-maven-plugin/src/main/java/com/microsoft/azure/maven/webapp/AbstractWebAppMojo.java +++ b/azure-webapp-maven-plugin/src/main/java/com/microsoft/azure/maven/webapp/AbstractWebAppMojo.java @@ -46,6 +46,7 @@ public abstract class AbstractWebAppMojo extends AbstractAppServiceMojo { public static final String OS_KEY = "os"; public static final String SCHEMA_VERSION_KEY = "schemaVersion"; public static final String DEPLOY_TO_SLOT_KEY = "isDeployToSlot"; + public static final String SKIP_CREATE_RESOURCE_KEY = "skipCreateResource"; public static final String INVALID_PARAMETER_ERROR_MESSAGE = "Invalid values found in configuration, please correct the value with messages below:"; //region Properties @@ -239,6 +240,8 @@ public Map getTelemetryProperties() { final boolean isDeployToSlot = Optional.ofNullable(getDeploymentSlotSetting()).map(DeploymentSlotSetting::getName) .map(StringUtils::isNotEmpty).orElse(false); map.put(DEPLOY_TO_SLOT_KEY, String.valueOf(isDeployToSlot)); + + map.put(SKIP_CREATE_RESOURCE_KEY, String.valueOf(skipAzureResourceCreate || skipCreateAzureResource)); return map; } diff --git a/azure-webapp-maven-plugin/src/test/java/com/microsoft/azure/maven/webapp/DeployMojoTest.java b/azure-webapp-maven-plugin/src/test/java/com/microsoft/azure/maven/webapp/DeployMojoTest.java index ac30a368c0..79b9afeffe 100644 --- a/azure-webapp-maven-plugin/src/test/java/com/microsoft/azure/maven/webapp/DeployMojoTest.java +++ b/azure-webapp-maven-plugin/src/test/java/com/microsoft/azure/maven/webapp/DeployMojoTest.java @@ -94,7 +94,7 @@ public void getTelemetryProperties() throws Exception { ReflectionUtils.setVariableValueInObject(spyMojo, "plugin", plugin); doReturn("azure-webapp-maven-plugin").when(plugin).getArtifactId(); final Map map = spyMojo.getTelemetryProperties(); - assertEquals(12, map.size()); + assertEquals(13, map.size()); assertTrue(map.containsKey(JAVA_VERSION_KEY)); assertTrue(map.containsKey(JAVA_WEB_CONTAINER_KEY)); assertTrue(map.containsKey(DOCKER_IMAGE_TYPE_KEY)); From 5ebaac8af73cd528e858fd37ddc5ce0015b76ae5 Mon Sep 17 00:00:00 2001 From: Hanxiao Liu Date: Sun, 26 Sep 2021 14:06:10 +0800 Subject: [PATCH 116/126] Fix app name was used for deployment slot by mistake --- .../lib/appservice/task/CreateOrUpdateFunctionAppTask.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/task/CreateOrUpdateFunctionAppTask.java b/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/task/CreateOrUpdateFunctionAppTask.java index c883c4b117..f630f52cce 100644 --- a/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/task/CreateOrUpdateFunctionAppTask.java +++ b/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/task/CreateOrUpdateFunctionAppTask.java @@ -217,7 +217,7 @@ private IFunctionAppDeploymentSlot getFunctionDeploymentSlot(final IFunctionApp if (!functionApp.exists()) { throw new AzureToolkitRuntimeException(FUNCTION_APP_NOT_EXIST_FOR_SLOT); } - return functionApp.deploymentSlot(functionAppConfig.appName()); + return functionApp.deploymentSlot(functionAppConfig.deploymentSlotName()); } private AzureTask getApplicationInsightsTask() { From ced7e0fdbcdd02201698557e3974c2d2b04065e3 Mon Sep 17 00:00:00 2001 From: Hanxiao Liu Date: Sun, 26 Sep 2021 14:51:13 +0800 Subject: [PATCH 117/126] Fix users ai key was replaced by default value --- .../java/com/microsoft/azure/maven/function/DeployMojo.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/azure-functions-maven-plugin/src/main/java/com/microsoft/azure/maven/function/DeployMojo.java b/azure-functions-maven-plugin/src/main/java/com/microsoft/azure/maven/function/DeployMojo.java index 56ad9f17be..0a92301380 100644 --- a/azure-functions-maven-plugin/src/main/java/com/microsoft/azure/maven/function/DeployMojo.java +++ b/azure-functions-maven-plugin/src/main/java/com/microsoft/azure/maven/function/DeployMojo.java @@ -149,7 +149,7 @@ protected IFunctionAppBase createOrUpdateResource(final FunctionAppConfig con AppServiceConfig defaultConfig = !newFunctionApp ? fromAppService(app, app.plan()) : buildDefaultConfig(config.subscriptionId(), config.resourceGroup(), config.appName()); mergeAppServiceConfig(config, defaultConfig); - if (!newFunctionApp && !config.disableAppInsights()) { + if (!newFunctionApp && !config.disableAppInsights() && StringUtils.isEmpty(config.appInsightsKey())) { // fill ai key from existing app settings config.appInsightsKey(app.entity().getAppSettings().get(CreateOrUpdateFunctionAppTask.APPINSIGHTS_INSTRUMENTATION_KEY)); } From 948f5771f41202629e3c8522f304e28fe696c7c3 Mon Sep 17 00:00:00 2001 From: Hanxiao Liu Date: Sun, 26 Sep 2021 15:32:24 +0800 Subject: [PATCH 118/126] Fix telemetry properties was missed in app service maven tooling --- azure-functions-maven-plugin/pom.xml | 51 ++++++++++++++++++- .../azure/maven/function/DeployMojo.java | 3 ++ .../azure/maven/AbstractAzureMojo.java | 5 ++ azure-spring-cloud-maven-plugin/pom.xml | 50 ++++++++++++++++++ .../lib/appservice/task/DeployWebAppTask.java | 4 +- .../title/base/functionapp.properties | 1 + .../operation/title/base/webapp.properties | 1 + azure-webapp-maven-plugin/pom.xml | 50 ++++++++++++++++++ .../azure/maven/webapp/DeployMojo.java | 3 ++ pom.xml | 7 ++- 10 files changed, 172 insertions(+), 3 deletions(-) diff --git a/azure-functions-maven-plugin/pom.xml b/azure-functions-maven-plugin/pom.xml index 122b7e2ec8..566cb0c007 100644 --- a/azure-functions-maven-plugin/pom.xml +++ b/azure-functions-maven-plugin/pom.xml @@ -275,6 +275,56 @@ + + + + com.nickwongdev + aspectj-maven-plugin + + false + 1.8 + 1.8 + ignore + 1.8 + UTF-8 + false + true + true + + + + com.microsoft.azure + azure-toolkit-common-lib + + + + + + compile-with-aspectj + process-classes + + + ${project.build.directory}/classes + + + + compile + + + + test-compile-with-aspectj + process-test-classes + + + ${project.build.directory}/test-classes + + + + test-compile + + + + org.apache.maven.plugins maven-plugin-plugin @@ -304,7 +354,6 @@ - org.jacoco jacoco-maven-plugin diff --git a/azure-functions-maven-plugin/src/main/java/com/microsoft/azure/maven/function/DeployMojo.java b/azure-functions-maven-plugin/src/main/java/com/microsoft/azure/maven/function/DeployMojo.java index 56ad9f17be..54b01229d9 100644 --- a/azure-functions-maven-plugin/src/main/java/com/microsoft/azure/maven/function/DeployMojo.java +++ b/azure-functions-maven-plugin/src/main/java/com/microsoft/azure/maven/function/DeployMojo.java @@ -24,6 +24,7 @@ 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.operation.AzureOperation; import com.microsoft.azure.toolkit.lib.common.utils.Utils; import org.apache.commons.io.FilenameUtils; import org.apache.commons.lang3.ObjectUtils; @@ -75,12 +76,14 @@ public class DeployMojo extends AbstractFunctionMojo { private static final String EXPANDABLE_JAVA_VERSION_WARNING = "'%s' may not be a valid java version, recommended values are `Java 8` and `Java 11`"; @Override + @AzureOperation(name = "functionapp|mojo.deploy", type = AzureOperation.Type.ACTION) protected void doExecute() throws AzureExecutionException { doValidate(); getOrCreateAzureAppServiceClient(); final IFunctionAppBase target = createOrUpdateResource(getParser().parseConfig()); deployArtifact(target); + updateTelemetryProperties(); } protected void doValidate() throws AzureExecutionException { diff --git a/azure-maven-plugin-lib/src/main/java/com/microsoft/azure/maven/AbstractAzureMojo.java b/azure-maven-plugin-lib/src/main/java/com/microsoft/azure/maven/AbstractAzureMojo.java index 658f6041da..3ef6346a77 100755 --- a/azure-maven-plugin-lib/src/main/java/com/microsoft/azure/maven/AbstractAzureMojo.java +++ b/azure-maven-plugin-lib/src/main/java/com/microsoft/azure/maven/AbstractAzureMojo.java @@ -34,6 +34,7 @@ import com.microsoft.azure.toolkit.lib.common.proxy.ProxyInfo; import com.microsoft.azure.toolkit.lib.common.proxy.ProxyManager; import com.microsoft.azure.toolkit.lib.common.telemetry.AzureTelemeter; +import com.microsoft.azure.toolkit.lib.common.telemetry.AzureTelemetry; import com.microsoft.azure.toolkit.lib.common.telemetry.AzureTelemetryClient; import com.microsoft.azure.toolkit.lib.common.utils.InstallationIdUtils; import com.microsoft.azure.toolkit.lib.common.utils.TextUtils; @@ -691,4 +692,8 @@ protected static void checkSubscription(List subscriptions, String } } + protected void updateTelemetryProperties() { + Optional.ofNullable(AzureTelemetry.getActionContext().getProperties()).ifPresent(properties -> + properties.forEach((key, value) -> telemetryProxy.addDefaultProperty(key, value))); + } } diff --git a/azure-spring-cloud-maven-plugin/pom.xml b/azure-spring-cloud-maven-plugin/pom.xml index 48b2a049b4..c46a2221e0 100644 --- a/azure-spring-cloud-maven-plugin/pom.xml +++ b/azure-spring-cloud-maven-plugin/pom.xml @@ -275,6 +275,56 @@ + + + + com.nickwongdev + aspectj-maven-plugin + + false + 1.8 + 1.8 + ignore + 1.8 + UTF-8 + false + true + true + + + + com.microsoft.azure + azure-toolkit-common-lib + + + + + + compile-with-aspectj + process-classes + + + ${project.build.directory}/classes + + + + compile + + + + test-compile-with-aspectj + process-test-classes + + + ${project.build.directory}/test-classes + + + + test-compile + + + + diff --git a/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/task/DeployWebAppTask.java b/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/task/DeployWebAppTask.java index c2d9136196..186f9ab612 100644 --- a/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/task/DeployWebAppTask.java +++ b/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/task/DeployWebAppTask.java @@ -12,6 +12,7 @@ import com.microsoft.azure.toolkit.lib.common.messager.AzureMessager; import com.microsoft.azure.toolkit.lib.common.operation.AzureOperation; import com.microsoft.azure.toolkit.lib.common.task.AzureTask; +import com.microsoft.azure.toolkit.lib.common.telemetry.AzureTelemetry; import org.apache.commons.lang3.StringUtils; import java.util.List; @@ -66,11 +67,12 @@ private void deployArtifacts() { if (artifacts.stream().anyMatch(artifact -> artifact.getDeployType() == null)) { throw new AzureToolkitRuntimeException("missing deployment type for some artifacts."); } - + final long startTime = System.currentTimeMillis(); final List artifactsOneDeploy = this.artifacts.stream() .filter(artifact -> artifact.getDeployType() != null) .collect(Collectors.toList()); artifactsOneDeploy.forEach(resource -> webApp.deploy(resource.getDeployType(), resource.getFile(), resource.getPath())); + AzureTelemetry.getActionContext().setProperty("deploy-cost", String.valueOf(System.currentTimeMillis() - startTime)); } private static void stopAppService(IWebAppBase target) { diff --git a/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/resources/com/microsoft/azure/toolkit/operation/title/base/functionapp.properties b/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/resources/com/microsoft/azure/toolkit/operation/title/base/functionapp.properties index c6a2d3119f..4aa54379f1 100644 --- a/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/resources/com/microsoft/azure/toolkit/operation/title/base/functionapp.properties +++ b/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/resources/com/microsoft/azure/toolkit/operation/title/base/functionapp.properties @@ -2,3 +2,4 @@ functionapp.get.id=get Azure Functions app({0}) functionapp.get.name|rg|sid=get Azure Functions app({0}) in resource group{(1)} functionapp.list.subscription|selected=list Azure Functions apps of selected subscriptions functionapp.list.subscription=list Azure Functions apps of subscription({0}) +functionapp|mojo.deploy=deploy to Azure Function App with resource creation or updating diff --git a/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/resources/com/microsoft/azure/toolkit/operation/title/base/webapp.properties b/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/resources/com/microsoft/azure/toolkit/operation/title/base/webapp.properties index 2fbadd240c..875251e16f 100644 --- a/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/resources/com/microsoft/azure/toolkit/operation/title/base/webapp.properties +++ b/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/resources/com/microsoft/azure/toolkit/operation/title/base/webapp.properties @@ -5,5 +5,6 @@ webapp.get.name|rg|sid=get Azure Web App({0}) in resource group({1}) webapp.list.subscription|selected=list Azure Web Apps of selected subscriptions webapp.list.subscription=list Azure Web Apps of subscription({0}) webapp|runtime.list.os|version=list available Azure Web App runtimes with os({0}) and java version({1}) +webapp|mojo.deploy=deploy to Azure Web App with resource creation or updating webapp.create=create Azure Web App ({0}) from config webapp.update=update Azure Web App ({0}) from config diff --git a/azure-webapp-maven-plugin/pom.xml b/azure-webapp-maven-plugin/pom.xml index 94d6a525b7..bcefd09af1 100644 --- a/azure-webapp-maven-plugin/pom.xml +++ b/azure-webapp-maven-plugin/pom.xml @@ -215,6 +215,56 @@ + + + + com.nickwongdev + aspectj-maven-plugin + + false + 1.8 + 1.8 + ignore + 1.8 + UTF-8 + false + true + true + + + + com.microsoft.azure + azure-toolkit-common-lib + + + + + + compile-with-aspectj + process-classes + + + ${project.build.directory}/classes + + + + compile + + + + test-compile-with-aspectj + process-test-classes + + + ${project.build.directory}/test-classes + + + + test-compile + + + + org.apache.maven.plugins maven-plugin-plugin diff --git a/azure-webapp-maven-plugin/src/main/java/com/microsoft/azure/maven/webapp/DeployMojo.java b/azure-webapp-maven-plugin/src/main/java/com/microsoft/azure/maven/webapp/DeployMojo.java index 35d76a9894..662a86a448 100644 --- a/azure-webapp-maven-plugin/src/main/java/com/microsoft/azure/maven/webapp/DeployMojo.java +++ b/azure-webapp-maven-plugin/src/main/java/com/microsoft/azure/maven/webapp/DeployMojo.java @@ -24,6 +24,7 @@ import com.microsoft.azure.toolkit.lib.common.bundle.AzureString; import com.microsoft.azure.toolkit.lib.common.exception.AzureExecutionException; import com.microsoft.azure.toolkit.lib.common.messager.AzureMessager; +import com.microsoft.azure.toolkit.lib.common.operation.AzureOperation; import com.microsoft.azure.toolkit.lib.common.utils.Utils; import org.apache.commons.lang3.ObjectUtils; import org.apache.commons.lang3.StringUtils; @@ -50,6 +51,7 @@ public class DeployMojo extends AbstractWebAppMojo { private static final String CREATE_NEW_DEPLOYMENT_SLOT = "createNewDeploymentSlot"; @Override + @AzureOperation(name = "webapp|mojo.deploy", type = AzureOperation.Type.ACTION) protected void doExecute() throws AzureExecutionException { validateConfiguration(message -> AzureMessager.getMessager().error(message.getMessage()), true); // initialize library client @@ -57,6 +59,7 @@ protected void doExecute() throws AzureExecutionException { final IWebAppBase target = createOrUpdateResource(); deployExternalResources(target, getConfigParser().getExternalArtifacts()); deploy(target, getConfigParser().getArtifacts()); + updateTelemetryProperties(); } private IWebAppBase createOrUpdateResource() throws AzureExecutionException { diff --git a/pom.xml b/pom.xml index 3fe3531425..b5ef62ec14 100644 --- a/pom.xml +++ b/pom.xml @@ -80,7 +80,7 @@ 3.1.0 2.9.1 3.1.2 - + 1.12.6 1.14.0 0.8.7 @@ -191,6 +191,11 @@ + + com.nickwongdev + aspectj-maven-plugin + ${maven.aspectj-plugin.version} + maven-clean-plugin ${maven.clean-plugin.version} From 3c8c0f093c7a4aca1eb49dcb0809883a7133d864 Mon Sep 17 00:00:00 2001 From: Hanxiao Liu Date: Tue, 28 Sep 2021 09:36:23 +0800 Subject: [PATCH 119/126] Bump azure toolkit lib version to 0.12.1 --- .../azure-toolkit-applicationinsights-lib/pom.xml | 2 +- azure-toolkit-libs/azure-toolkit-appservice-lib/pom.xml | 2 +- azure-toolkit-libs/azure-toolkit-auth-lib/pom.xml | 2 +- azure-toolkit-libs/azure-toolkit-common-lib/pom.xml | 2 +- azure-toolkit-libs/azure-toolkit-compute-lib/pom.xml | 2 +- azure-toolkit-libs/azure-toolkit-database-lib/pom.xml | 2 +- azure-toolkit-libs/azure-toolkit-mysql-lib/pom.xml | 2 +- azure-toolkit-libs/azure-toolkit-redis-lib/pom.xml | 2 +- azure-toolkit-libs/azure-toolkit-resource-lib/pom.xml | 2 +- azure-toolkit-libs/azure-toolkit-springcloud-lib/pom.xml | 2 +- azure-toolkit-libs/azure-toolkit-sqlserver-lib/pom.xml | 2 +- azure-toolkit-libs/azure-toolkit-storage-lib/pom.xml | 2 +- azure-toolkit-libs/pom.xml | 2 +- pom.xml | 2 +- 14 files changed, 14 insertions(+), 14 deletions(-) diff --git a/azure-toolkit-libs/azure-toolkit-applicationinsights-lib/pom.xml b/azure-toolkit-libs/azure-toolkit-applicationinsights-lib/pom.xml index 13cfeb3cf0..36df7025a3 100644 --- a/azure-toolkit-libs/azure-toolkit-applicationinsights-lib/pom.xml +++ b/azure-toolkit-libs/azure-toolkit-applicationinsights-lib/pom.xml @@ -5,7 +5,7 @@ azure-toolkit-libs com.microsoft.azure - 0.12.0 + 0.12.1 4.0.0 diff --git a/azure-toolkit-libs/azure-toolkit-appservice-lib/pom.xml b/azure-toolkit-libs/azure-toolkit-appservice-lib/pom.xml index 16b9d64e39..f03d3cf614 100644 --- a/azure-toolkit-libs/azure-toolkit-appservice-lib/pom.xml +++ b/azure-toolkit-libs/azure-toolkit-appservice-lib/pom.xml @@ -5,7 +5,7 @@ azure-toolkit-libs com.microsoft.azure - 0.12.0 + 0.12.1 4.0.0 diff --git a/azure-toolkit-libs/azure-toolkit-auth-lib/pom.xml b/azure-toolkit-libs/azure-toolkit-auth-lib/pom.xml index 71f5858bc4..3602c87700 100644 --- a/azure-toolkit-libs/azure-toolkit-auth-lib/pom.xml +++ b/azure-toolkit-libs/azure-toolkit-auth-lib/pom.xml @@ -5,7 +5,7 @@ azure-toolkit-libs com.microsoft.azure - 0.12.0 + 0.12.1 4.0.0 diff --git a/azure-toolkit-libs/azure-toolkit-common-lib/pom.xml b/azure-toolkit-libs/azure-toolkit-common-lib/pom.xml index c1ff7baaf0..a3b2a5ba86 100644 --- a/azure-toolkit-libs/azure-toolkit-common-lib/pom.xml +++ b/azure-toolkit-libs/azure-toolkit-common-lib/pom.xml @@ -5,7 +5,7 @@ azure-toolkit-libs com.microsoft.azure - 0.12.0 + 0.12.1 4.0.0 diff --git a/azure-toolkit-libs/azure-toolkit-compute-lib/pom.xml b/azure-toolkit-libs/azure-toolkit-compute-lib/pom.xml index eec7cf3fda..f026327e98 100644 --- a/azure-toolkit-libs/azure-toolkit-compute-lib/pom.xml +++ b/azure-toolkit-libs/azure-toolkit-compute-lib/pom.xml @@ -5,7 +5,7 @@ azure-toolkit-libs com.microsoft.azure - 0.12.0 + 0.12.1 4.0.0 diff --git a/azure-toolkit-libs/azure-toolkit-database-lib/pom.xml b/azure-toolkit-libs/azure-toolkit-database-lib/pom.xml index f219206325..1624e14778 100644 --- a/azure-toolkit-libs/azure-toolkit-database-lib/pom.xml +++ b/azure-toolkit-libs/azure-toolkit-database-lib/pom.xml @@ -5,7 +5,7 @@ azure-toolkit-libs com.microsoft.azure - 0.12.0 + 0.12.1 4.0.0 diff --git a/azure-toolkit-libs/azure-toolkit-mysql-lib/pom.xml b/azure-toolkit-libs/azure-toolkit-mysql-lib/pom.xml index 29b0269f30..e88ecd81b8 100644 --- a/azure-toolkit-libs/azure-toolkit-mysql-lib/pom.xml +++ b/azure-toolkit-libs/azure-toolkit-mysql-lib/pom.xml @@ -5,7 +5,7 @@ azure-toolkit-libs com.microsoft.azure - 0.12.0 + 0.12.1 4.0.0 diff --git a/azure-toolkit-libs/azure-toolkit-redis-lib/pom.xml b/azure-toolkit-libs/azure-toolkit-redis-lib/pom.xml index 3ed7b5812a..c4d80b3bcf 100644 --- a/azure-toolkit-libs/azure-toolkit-redis-lib/pom.xml +++ b/azure-toolkit-libs/azure-toolkit-redis-lib/pom.xml @@ -5,7 +5,7 @@ azure-toolkit-libs com.microsoft.azure - 0.12.0 + 0.12.1 4.0.0 diff --git a/azure-toolkit-libs/azure-toolkit-resource-lib/pom.xml b/azure-toolkit-libs/azure-toolkit-resource-lib/pom.xml index eb8c61be08..36ff86a00a 100644 --- a/azure-toolkit-libs/azure-toolkit-resource-lib/pom.xml +++ b/azure-toolkit-libs/azure-toolkit-resource-lib/pom.xml @@ -5,7 +5,7 @@ azure-toolkit-libs com.microsoft.azure - 0.12.0 + 0.12.1 4.0.0 diff --git a/azure-toolkit-libs/azure-toolkit-springcloud-lib/pom.xml b/azure-toolkit-libs/azure-toolkit-springcloud-lib/pom.xml index d9735fdb5b..e3308f61e0 100644 --- a/azure-toolkit-libs/azure-toolkit-springcloud-lib/pom.xml +++ b/azure-toolkit-libs/azure-toolkit-springcloud-lib/pom.xml @@ -5,7 +5,7 @@ azure-toolkit-libs com.microsoft.azure - 0.12.0 + 0.12.1 4.0.0 diff --git a/azure-toolkit-libs/azure-toolkit-sqlserver-lib/pom.xml b/azure-toolkit-libs/azure-toolkit-sqlserver-lib/pom.xml index c48aeced71..4f60210563 100644 --- a/azure-toolkit-libs/azure-toolkit-sqlserver-lib/pom.xml +++ b/azure-toolkit-libs/azure-toolkit-sqlserver-lib/pom.xml @@ -5,7 +5,7 @@ azure-toolkit-libs com.microsoft.azure - 0.12.0 + 0.12.1 4.0.0 diff --git a/azure-toolkit-libs/azure-toolkit-storage-lib/pom.xml b/azure-toolkit-libs/azure-toolkit-storage-lib/pom.xml index 156fdec15d..2d10f5b927 100644 --- a/azure-toolkit-libs/azure-toolkit-storage-lib/pom.xml +++ b/azure-toolkit-libs/azure-toolkit-storage-lib/pom.xml @@ -5,7 +5,7 @@ azure-toolkit-libs com.microsoft.azure - 0.12.0 + 0.12.1 4.0.0 diff --git a/azure-toolkit-libs/pom.xml b/azure-toolkit-libs/pom.xml index f50653cbad..354c8ae73d 100644 --- a/azure-toolkit-libs/pom.xml +++ b/azure-toolkit-libs/pom.xml @@ -5,7 +5,7 @@ 4.0.0 com.microsoft.azure azure-toolkit-libs - 0.12.0 + 0.12.1 pom Libs for Azure Toolkits Wrapped libs for Microsoft Azure Toolkits diff --git a/pom.xml b/pom.xml index b5ef62ec14..594b11929e 100644 --- a/pom.xml +++ b/pom.xml @@ -92,7 +92,7 @@ com.microsoft.azure azure-toolkit-libs - 0.12.0 + 0.12.1 pom import From 7fdabe59dbecbb471911bdc94b54402f3f07ba07 Mon Sep 17 00:00:00 2001 From: andxu Date: Tue, 28 Sep 2021 09:57:03 +0800 Subject: [PATCH 120/126] Fix region order in listSupportedRegions --- .../java/com/microsoft/azure/toolkit/lib/AzureService.java | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/azure-toolkit-libs/azure-toolkit-common-lib/src/main/java/com/microsoft/azure/toolkit/lib/AzureService.java b/azure-toolkit-libs/azure-toolkit-common-lib/src/main/java/com/microsoft/azure/toolkit/lib/AzureService.java index 7090f2f256..9622a0607f 100644 --- a/azure-toolkit-libs/azure-toolkit-common-lib/src/main/java/com/microsoft/azure/toolkit/lib/AzureService.java +++ b/azure-toolkit-libs/azure-toolkit-common-lib/src/main/java/com/microsoft/azure/toolkit/lib/AzureService.java @@ -20,7 +20,6 @@ import com.microsoft.azure.toolkit.lib.common.exception.AzureToolkitRuntimeException; import com.microsoft.azure.toolkit.lib.common.model.Region; import com.microsoft.azure.toolkit.lib.common.model.Subscription; -import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.lang3.StringUtils; import java.util.ArrayList; @@ -47,10 +46,7 @@ default List listSupportedRegions(String subscriptionId) { resourceManager.providers().getByName(provider).resourceTypes() .stream().filter(type -> StringUtils.equalsIgnoreCase(type.resourceType(), resourceType)) .findAny().map(ProviderResourceType::locations) - .ifPresent(list -> { - final List regionListByResource = list.stream().map(Region::fromName).collect(Collectors.toList()); - result.addAll(CollectionUtils.intersection(regionListByResource, allRegionList)); - }); + .ifPresent(list -> result.addAll(list.stream().map(Region::fromName).filter(allRegionList::contains).collect(Collectors.toList()))); return result.isEmpty() ? allRegionList : result; } From f7d1b0fb491b7bd428b926d6b47c501319f97fae Mon Sep 17 00:00:00 2001 From: andxu Date: Tue, 28 Sep 2021 16:05:13 +0800 Subject: [PATCH 121/126] Move from okhttp to netty --- azure-functions-maven-plugin/pom.xml | 19 ++++------ .../azure-toolkit-auth-lib/pom.xml | 8 +--- .../lib/auth/TokenCredentialManager.java | 8 +++- .../azure-toolkit-common-lib/pom.xml | 4 -- .../RestExceptionHandlerInterceptor.java | 37 ------------------- azure-toolkit-libs/pom.xml | 37 +++++++------------ 6 files changed, 28 insertions(+), 85 deletions(-) delete mode 100644 azure-toolkit-libs/azure-toolkit-common-lib/src/main/java/com/microsoft/azure/toolkit/lib/common/exception/RestExceptionHandlerInterceptor.java diff --git a/azure-functions-maven-plugin/pom.xml b/azure-functions-maven-plugin/pom.xml index 7860c776e6..293a4b1c12 100644 --- a/azure-functions-maven-plugin/pom.xml +++ b/azure-functions-maven-plugin/pom.xml @@ -52,22 +52,17 @@ provided - com.squareup.okhttp3 - okhttp - - - org.jetbrains.kotlin - kotlin-stdlib - - + io.projectreactor.netty + reactor-netty - com.squareup.okhttp3 - logging-interceptor + com.azure + azure-core-http-netty - com.squareup.okhttp3 - okhttp-urlconnection + org.projectlombok + lombok + provided com.microsoft.azure diff --git a/azure-toolkit-libs/azure-toolkit-auth-lib/pom.xml b/azure-toolkit-libs/azure-toolkit-auth-lib/pom.xml index 3602c87700..54010d0dcd 100644 --- a/azure-toolkit-libs/azure-toolkit-auth-lib/pom.xml +++ b/azure-toolkit-libs/azure-toolkit-auth-lib/pom.xml @@ -13,15 +13,11 @@ com.azure - azure-core + azure-core-http-netty com.azure - azure-core-http-okhttp - - - com.squareup.okhttp3 - okhttp + azure-core org.apache.commons diff --git a/azure-toolkit-libs/azure-toolkit-auth-lib/src/main/java/com/microsoft/azure/toolkit/lib/auth/TokenCredentialManager.java b/azure-toolkit-libs/azure-toolkit-auth-lib/src/main/java/com/microsoft/azure/toolkit/lib/auth/TokenCredentialManager.java index 42fb822a28..10bfd4843b 100644 --- a/azure-toolkit-libs/azure-toolkit-auth-lib/src/main/java/com/microsoft/azure/toolkit/lib/auth/TokenCredentialManager.java +++ b/azure-toolkit-libs/azure-toolkit-auth-lib/src/main/java/com/microsoft/azure/toolkit/lib/auth/TokenCredentialManager.java @@ -7,7 +7,7 @@ import com.azure.core.credential.TokenCredential; import com.azure.core.http.ProxyOptions; -import com.azure.core.http.okhttp.OkHttpAsyncHttpClientBuilder; +import com.azure.core.http.netty.NettyAsyncHttpClientBuilder; import com.azure.core.http.policy.FixedDelay; import com.azure.core.http.policy.HttpPipelinePolicy; import com.azure.core.http.policy.RetryPolicy; @@ -20,6 +20,7 @@ import com.microsoft.azure.toolkit.lib.AzureConfiguration; import com.microsoft.azure.toolkit.lib.common.model.Subscription; import com.microsoft.azure.toolkit.lib.common.utils.Utils; +import io.netty.resolver.DefaultAddressResolverGroup; import lombok.Getter; import lombok.Setter; import org.apache.commons.lang3.StringUtils; @@ -103,7 +104,10 @@ private ResourceManager.Authenticated createAzureClient(AzureEnvironment env) { * TODO: share the same code for creating ResourceManager.Configurable */ private static ResourceManager.Configurable configureAzure() { - OkHttpAsyncHttpClientBuilder builder = new OkHttpAsyncHttpClientBuilder(); + reactor.netty.http.client.HttpClient nettyHttpClient = + reactor.netty.http.client.HttpClient.create() + .resolver(DefaultAddressResolverGroup.INSTANCE); + NettyAsyncHttpClientBuilder builder = new NettyAsyncHttpClientBuilder(nettyHttpClient); final AzureConfiguration config = Azure.az().config(); if (StringUtils.isNotBlank(config.getProxySource())) { final ProxyOptions proxyOptions = new ProxyOptions(ProxyOptions.Type.HTTP, diff --git a/azure-toolkit-libs/azure-toolkit-common-lib/pom.xml b/azure-toolkit-libs/azure-toolkit-common-lib/pom.xml index a3b2a5ba86..571de32b43 100644 --- a/azure-toolkit-libs/azure-toolkit-common-lib/pom.xml +++ b/azure-toolkit-libs/azure-toolkit-common-lib/pom.xml @@ -84,10 +84,6 @@ org.reflections reflections - - com.squareup.okhttp3 - okhttp - org.apache.httpcomponents httpclient diff --git a/azure-toolkit-libs/azure-toolkit-common-lib/src/main/java/com/microsoft/azure/toolkit/lib/common/exception/RestExceptionHandlerInterceptor.java b/azure-toolkit-libs/azure-toolkit-common-lib/src/main/java/com/microsoft/azure/toolkit/lib/common/exception/RestExceptionHandlerInterceptor.java deleted file mode 100644 index c58b3b0d28..0000000000 --- a/azure-toolkit-libs/azure-toolkit-common-lib/src/main/java/com/microsoft/azure/toolkit/lib/common/exception/RestExceptionHandlerInterceptor.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - */ - -package com.microsoft.azure.toolkit.lib.common.exception; - -import com.google.common.base.Throwables; -import com.microsoft.aad.adal4j.AuthenticationException; -import okhttp3.Interceptor; -import okhttp3.Request; -import okhttp3.Response; - -import java.io.IOException; -import java.net.UnknownHostException; -import java.util.List; - -/** - * Interceptor to handle REST API related exceptions - */ -public class RestExceptionHandlerInterceptor implements Interceptor { - @Override - public Response intercept(final Chain chain) throws IOException { - try { - final Request request = chain.request(); - return chain.proceed(request); - } catch (final Exception ex) { - final List exceptions = Throwables.getCausalChain(ex); - if (exceptions.stream().anyMatch(e -> e instanceof UnknownHostException)) { - throw new AzureToolkitRuntimeException("Unknown host! You network condition maybe unstable, please try later."); - } else if (exceptions.stream().anyMatch(e -> e instanceof AuthenticationException)) { - throw new AzureToolkitRuntimeException("Invalid authentication! You may sign in again or run \"az login\" if using Azure CLI credential"); - } - throw ex; - } - } -} diff --git a/azure-toolkit-libs/pom.xml b/azure-toolkit-libs/pom.xml index c12a93c73b..94601d0b3d 100644 --- a/azure-toolkit-libs/pom.xml +++ b/azure-toolkit-libs/pom.xml @@ -75,7 +75,6 @@ 8.6.6 1.41.1 3.2.2 - 1.6.2 12.9.1 1.4.2 4.2.8 @@ -86,7 +85,7 @@ 12.11.1 12.9.1 12.5.1 - + 1.11.0 1.9.7.M3 3.3.0 1.15 @@ -102,7 +101,6 @@ 2.8.7 30.1.1-jre 4.5.13 - 4.9.1 2.12.3 0.8.7 2.3.2 @@ -120,6 +118,7 @@ 1.1.1 0.9.1 0.9.12 + 1.0.11 1.9.2 9.15 3.1.0 @@ -160,6 +159,11 @@ azure-toolkit-common-lib ${azure.toolkit-lib.version} + + com.azure + azure-core-http-netty + ${azure.core.http.netty.version} + com.microsoft.azure azure-toolkit-auth-lib @@ -564,30 +568,10 @@ com.azure - azure-core-http-netty + azure-core-http-okhttp - - com.azure - azure-core-http-okhttp - ${azure.core.http.okhttp.version} - - - com.squareup.okhttp3 - okhttp - ${okhttp.version} - - - com.squareup.okhttp3 - logging-interceptor - ${okhttp.version} - - - com.squareup.okhttp3 - okhttp-urlconnection - ${okhttp.version} - org.apache.httpcomponents httpclient @@ -680,6 +664,11 @@ java-semver ${semver.version} + + io.projectreactor.netty + reactor-netty + ${reactor.netty.version} + jakarta.xml.bind From d0c5ea2bf6e74309e7e9ba2b00d5ce9af87156c6 Mon Sep 17 00:00:00 2001 From: andxu Date: Tue, 28 Sep 2021 16:22:27 +0800 Subject: [PATCH 122/126] Provide http client for each client --- .../ApplicationInsights.java | 2 + .../lib/appservice/AzureAppService.java | 1 + .../azure-toolkit-auth-lib/pom.xml | 4 -- .../lib/auth/TokenCredentialManager.java | 23 +---------- .../azure-toolkit-common-lib/pom.xml | 4 ++ .../azure/toolkit/lib/AzureService.java | 38 +++++++++++++++++++ .../lib/mysql/MySqlManagerFactory.java | 2 + .../toolkit/redis/RedisManagerFactory.java | 2 + .../lib/springcloud/AzureSpringCloud.java | 1 + .../sqlserver/SqlServerManagerFactory.java | 7 ++++ .../lib/storage/StorageManagerFactory.java | 2 + 11 files changed, 61 insertions(+), 25 deletions(-) diff --git a/azure-toolkit-libs/azure-toolkit-applicationinsights-lib/src/main/java/com/microsoft/azure/toolkit/lib/applicationinsights/ApplicationInsights.java b/azure-toolkit-libs/azure-toolkit-applicationinsights-lib/src/main/java/com/microsoft/azure/toolkit/lib/applicationinsights/ApplicationInsights.java index 61a6dc6df3..ffd66b7c81 100644 --- a/azure-toolkit-libs/azure-toolkit-applicationinsights-lib/src/main/java/com/microsoft/azure/toolkit/lib/applicationinsights/ApplicationInsights.java +++ b/azure-toolkit-libs/azure-toolkit-applicationinsights-lib/src/main/java/com/microsoft/azure/toolkit/lib/applicationinsights/ApplicationInsights.java @@ -109,11 +109,13 @@ private ApplicationInsightsManager getApplicationInsightsManager(String subscrip final AzureProfile azureProfile = new AzureProfile(tenantId, subscriptionId, account.getEnvironment()); // todo: migrate resource provider related codes to common library final Providers providers = ResourceManager.configure() + .withHttpClient(AzureService.getDefaultHttpClient()) .withPolicy(getUserAgentPolicy(userAgent)) .authenticate(account.getTokenCredential(subscriptionId), azureProfile) .withSubscription(subscriptionId).providers(); return ApplicationInsightsManager .configure() + .withHttpClient(AzureService.getDefaultHttpClient()) .withLogOptions(logOptions) .withPolicy(getUserAgentPolicy(userAgent)) .withPolicy(new ProviderRegistrationPolicy(providers)) // add policy to auto register resource providers diff --git a/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/AzureAppService.java b/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/AzureAppService.java index 7e7f9b27c0..6135169a54 100644 --- a/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/AzureAppService.java +++ b/azure-toolkit-libs/azure-toolkit-appservice-lib/src/main/java/com/microsoft/azure/toolkit/lib/appservice/AzureAppService.java @@ -214,6 +214,7 @@ public AppServiceManager getAppServiceManager(String sid) { final HttpLogDetailLevel logLevel = Optional.ofNullable(config.getLogLevel()).map(HttpLogDetailLevel::valueOf).orElse(HttpLogDetailLevel.NONE); final AzureProfile azureProfile = new AzureProfile(null, sid, account.getEnvironment()); return AppServiceManager.configure() + .withHttpClient(AzureService.getDefaultHttpClient()) .withLogLevel(logLevel) .withPolicy(getUserAgentPolicy(userAgent)) // set user agent with policy .authenticate(account.getTokenCredential(sid), azureProfile); diff --git a/azure-toolkit-libs/azure-toolkit-auth-lib/pom.xml b/azure-toolkit-libs/azure-toolkit-auth-lib/pom.xml index 54010d0dcd..4d0f6549f7 100644 --- a/azure-toolkit-libs/azure-toolkit-auth-lib/pom.xml +++ b/azure-toolkit-libs/azure-toolkit-auth-lib/pom.xml @@ -11,10 +11,6 @@ azure-toolkit-auth-lib - - com.azure - azure-core-http-netty - com.azure azure-core diff --git a/azure-toolkit-libs/azure-toolkit-auth-lib/src/main/java/com/microsoft/azure/toolkit/lib/auth/TokenCredentialManager.java b/azure-toolkit-libs/azure-toolkit-auth-lib/src/main/java/com/microsoft/azure/toolkit/lib/auth/TokenCredentialManager.java index 10bfd4843b..9b46c2938f 100644 --- a/azure-toolkit-libs/azure-toolkit-auth-lib/src/main/java/com/microsoft/azure/toolkit/lib/auth/TokenCredentialManager.java +++ b/azure-toolkit-libs/azure-toolkit-auth-lib/src/main/java/com/microsoft/azure/toolkit/lib/auth/TokenCredentialManager.java @@ -6,8 +6,6 @@ package com.microsoft.azure.toolkit.lib.auth; import com.azure.core.credential.TokenCredential; -import com.azure.core.http.ProxyOptions; -import com.azure.core.http.netty.NettyAsyncHttpClientBuilder; import com.azure.core.http.policy.FixedDelay; import com.azure.core.http.policy.HttpPipelinePolicy; import com.azure.core.http.policy.RetryPolicy; @@ -17,10 +15,9 @@ import com.azure.resourcemanager.resources.ResourceManager; import com.azure.resourcemanager.resources.models.Tenant; import com.microsoft.azure.toolkit.lib.Azure; -import com.microsoft.azure.toolkit.lib.AzureConfiguration; +import com.microsoft.azure.toolkit.lib.AzureService; import com.microsoft.azure.toolkit.lib.common.model.Subscription; import com.microsoft.azure.toolkit.lib.common.utils.Utils; -import io.netty.resolver.DefaultAddressResolverGroup; import lombok.Getter; import lombok.Setter; import org.apache.commons.lang3.StringUtils; @@ -28,7 +25,6 @@ import reactor.core.publisher.Mono; import reactor.core.scheduler.Schedulers; -import java.net.InetSocketAddress; import java.time.Duration; import java.util.ArrayList; import java.util.Collection; @@ -104,24 +100,9 @@ private ResourceManager.Authenticated createAzureClient(AzureEnvironment env) { * TODO: share the same code for creating ResourceManager.Configurable */ private static ResourceManager.Configurable configureAzure() { - reactor.netty.http.client.HttpClient nettyHttpClient = - reactor.netty.http.client.HttpClient.create() - .resolver(DefaultAddressResolverGroup.INSTANCE); - NettyAsyncHttpClientBuilder builder = new NettyAsyncHttpClientBuilder(nettyHttpClient); - final AzureConfiguration config = Azure.az().config(); - if (StringUtils.isNotBlank(config.getProxySource())) { - final ProxyOptions proxyOptions = new ProxyOptions(ProxyOptions.Type.HTTP, - new InetSocketAddress(config.getHttpProxyHost(), config.getHttpProxyPort()) - ); - if (StringUtils.isNoneBlank(config.getProxyUsername(), config.getProxyPassword())) { - proxyOptions.setCredentials(config.getProxyUsername(), config.getProxyPassword()); - } - builder.proxy(proxyOptions); - } - // disable retry for getting tenant and subscriptions return ResourceManager.configure() - .withHttpClient(builder.build()) + .withHttpClient(AzureService.getDefaultHttpClient()) .withPolicy(createUserAgentPolicy()) .withRetryPolicy(new RetryPolicy(new FixedDelay(0, Duration.ofSeconds(0)))); } diff --git a/azure-toolkit-libs/azure-toolkit-common-lib/pom.xml b/azure-toolkit-libs/azure-toolkit-common-lib/pom.xml index 571de32b43..baa433b3b9 100644 --- a/azure-toolkit-libs/azure-toolkit-common-lib/pom.xml +++ b/azure-toolkit-libs/azure-toolkit-common-lib/pom.xml @@ -12,6 +12,10 @@ azure-toolkit-common-lib + + com.azure + azure-core-http-netty + com.networknt json-schema-validator diff --git a/azure-toolkit-libs/azure-toolkit-common-lib/src/main/java/com/microsoft/azure/toolkit/lib/AzureService.java b/azure-toolkit-libs/azure-toolkit-common-lib/src/main/java/com/microsoft/azure/toolkit/lib/AzureService.java index 9622a0607f..ec3aa127ba 100644 --- a/azure-toolkit-libs/azure-toolkit-common-lib/src/main/java/com/microsoft/azure/toolkit/lib/AzureService.java +++ b/azure-toolkit-libs/azure-toolkit-common-lib/src/main/java/com/microsoft/azure/toolkit/lib/AzureService.java @@ -5,6 +5,9 @@ package com.microsoft.azure.toolkit.lib; +import com.azure.core.http.HttpClient; +import com.azure.core.http.ProxyOptions; +import com.azure.core.http.netty.NettyAsyncHttpClientBuilder; import com.azure.core.http.policy.HttpLogDetailLevel; import com.azure.core.http.policy.HttpPipelinePolicy; import com.azure.core.management.profile.AzureProfile; @@ -20,8 +23,10 @@ import com.microsoft.azure.toolkit.lib.common.exception.AzureToolkitRuntimeException; import com.microsoft.azure.toolkit.lib.common.model.Region; import com.microsoft.azure.toolkit.lib.common.model.Subscription; +import io.netty.resolver.DefaultAddressResolverGroup; import org.apache.commons.lang3.StringUtils; +import java.net.InetSocketAddress; import java.util.ArrayList; import java.util.List; import java.util.stream.Collectors; @@ -61,10 +66,12 @@ default ResourceManager getResourceManager(String subscriptionId) { final AzureProfile azureProfile = new AzureProfile(account.getEnvironment()); final Providers providers = ResourceManager.configure() + .withHttpClient(getDefaultHttpClient()) .withPolicy(getUserAgentPolicy(userAgent)) .authenticate(account.getTokenCredential(subscriptionId), azureProfile) .withSubscription(subscriptionId).providers(); return ResourceManager.configure() + .withHttpClient(getDefaultHttpClient()) .withLogLevel(logDetailLevel) .withPolicy(getUserAgentPolicy(userAgent)) // set user agent with policy .withPolicy(new ProviderRegistrationPolicy(providers)) // add policy to auto register resource providers @@ -79,4 +86,35 @@ static HttpPipelinePolicy getUserAgentPolicy(String userAgent) { return httpPipelineNextPolicy.process(); }; } + + class HttpClientHolder { + private static HttpClient defaultHttpClient = null; + + private static synchronized HttpClient createHttpClient() { + if (defaultHttpClient != null) { + return defaultHttpClient; + } + + reactor.netty.http.client.HttpClient nettyHttpClient = + reactor.netty.http.client.HttpClient.create() + .resolver(DefaultAddressResolverGroup.INSTANCE); + NettyAsyncHttpClientBuilder builder = new NettyAsyncHttpClientBuilder(nettyHttpClient); + final AzureConfiguration config = Azure.az().config(); + if (StringUtils.isNotBlank(config.getProxySource())) { + final ProxyOptions proxyOptions = new ProxyOptions(ProxyOptions.Type.HTTP, + new InetSocketAddress(config.getHttpProxyHost(), config.getHttpProxyPort()) + ); + if (StringUtils.isNoneBlank(config.getProxyUsername(), config.getProxyPassword())) { + proxyOptions.setCredentials(config.getProxyUsername(), config.getProxyPassword()); + } + builder.proxy(proxyOptions); + } + defaultHttpClient = builder.build(); + return defaultHttpClient; + } + } + + static HttpClient getDefaultHttpClient() { + return HttpClientHolder.createHttpClient(); + } } diff --git a/azure-toolkit-libs/azure-toolkit-mysql-lib/src/main/java/com/microsoft/azure/toolkit/lib/mysql/MySqlManagerFactory.java b/azure-toolkit-libs/azure-toolkit-mysql-lib/src/main/java/com/microsoft/azure/toolkit/lib/mysql/MySqlManagerFactory.java index 73652c1c4a..aa7255a45c 100644 --- a/azure-toolkit-libs/azure-toolkit-mysql-lib/src/main/java/com/microsoft/azure/toolkit/lib/mysql/MySqlManagerFactory.java +++ b/azure-toolkit-libs/azure-toolkit-mysql-lib/src/main/java/com/microsoft/azure/toolkit/lib/mysql/MySqlManagerFactory.java @@ -11,6 +11,7 @@ import com.azure.resourcemanager.mysql.MySqlManager; import com.microsoft.azure.toolkit.lib.Azure; import com.microsoft.azure.toolkit.lib.AzureConfiguration; +import com.microsoft.azure.toolkit.lib.AzureService; import com.microsoft.azure.toolkit.lib.auth.Account; import com.microsoft.azure.toolkit.lib.auth.AzureAccount; import com.microsoft.azure.toolkit.lib.common.cache.Cacheable; @@ -30,6 +31,7 @@ public static MySqlManager create(String subscriptionId) { final HttpLogDetailLevel logLevel = Optional.ofNullable(config.getLogLevel()).map(HttpLogDetailLevel::valueOf).orElse(HttpLogDetailLevel.NONE); final AzureProfile azureProfile = new AzureProfile(null, subscriptionId, account.getEnvironment()); return MySqlManager.configure() + .withHttpClient(AzureService.getDefaultHttpClient()) .withLogOptions(new HttpLogOptions().setLogLevel(logLevel)) .withPolicy(getUserAgentPolicy(userAgent)) .authenticate(account.getTokenCredential(subscriptionId), azureProfile); diff --git a/azure-toolkit-libs/azure-toolkit-redis-lib/src/main/java/com/microsoft/azure/toolkit/redis/RedisManagerFactory.java b/azure-toolkit-libs/azure-toolkit-redis-lib/src/main/java/com/microsoft/azure/toolkit/redis/RedisManagerFactory.java index df62013548..2cbe3b447b 100644 --- a/azure-toolkit-libs/azure-toolkit-redis-lib/src/main/java/com/microsoft/azure/toolkit/redis/RedisManagerFactory.java +++ b/azure-toolkit-libs/azure-toolkit-redis-lib/src/main/java/com/microsoft/azure/toolkit/redis/RedisManagerFactory.java @@ -11,6 +11,7 @@ import com.azure.resourcemanager.redis.RedisManager; import com.microsoft.azure.toolkit.lib.Azure; import com.microsoft.azure.toolkit.lib.AzureConfiguration; +import com.microsoft.azure.toolkit.lib.AzureService; import com.microsoft.azure.toolkit.lib.auth.Account; import com.microsoft.azure.toolkit.lib.auth.AzureAccount; import com.microsoft.azure.toolkit.lib.common.cache.Cacheable; @@ -30,6 +31,7 @@ public static RedisManager create(String subscriptionId) { final HttpLogDetailLevel logLevel = Optional.ofNullable(config.getLogLevel()).map(HttpLogDetailLevel::valueOf).orElse(HttpLogDetailLevel.NONE); final AzureProfile azureProfile = new AzureProfile(null, subscriptionId, account.getEnvironment()); return RedisManager.configure() + .withHttpClient(AzureService.getDefaultHttpClient()) .withLogLevel(logLevel) .withPolicy(getUserAgentPolicy(userAgent)) .authenticate(account.getTokenCredential(subscriptionId), azureProfile); diff --git a/azure-toolkit-libs/azure-toolkit-springcloud-lib/src/main/java/com/microsoft/azure/toolkit/lib/springcloud/AzureSpringCloud.java b/azure-toolkit-libs/azure-toolkit-springcloud-lib/src/main/java/com/microsoft/azure/toolkit/lib/springcloud/AzureSpringCloud.java index f1091c7f86..5bc8f95c04 100644 --- a/azure-toolkit-libs/azure-toolkit-springcloud-lib/src/main/java/com/microsoft/azure/toolkit/lib/springcloud/AzureSpringCloud.java +++ b/azure-toolkit-libs/azure-toolkit-springcloud-lib/src/main/java/com/microsoft/azure/toolkit/lib/springcloud/AzureSpringCloud.java @@ -117,6 +117,7 @@ protected SpringServices getClient(final String subscriptionId) { final HttpLogDetailLevel logLevel = Optional.ofNullable(config.getLogLevel()).map(HttpLogDetailLevel::valueOf).orElse(HttpLogDetailLevel.NONE); final AzureProfile azureProfile = new AzureProfile(null, subscriptionId, account.getEnvironment()); return AppPlatformManager.configure() + .withHttpClient(AzureService.getDefaultHttpClient()) .withLogLevel(logLevel) .withPolicy(getUserAgentPolicy(userAgent)) // set user agent with policy .authenticate(account.getTokenCredential(subscriptionId), azureProfile) diff --git a/azure-toolkit-libs/azure-toolkit-sqlserver-lib/src/main/java/com/microsoft/azure/toolkit/lib/sqlserver/SqlServerManagerFactory.java b/azure-toolkit-libs/azure-toolkit-sqlserver-lib/src/main/java/com/microsoft/azure/toolkit/lib/sqlserver/SqlServerManagerFactory.java index e4c219e915..322f6041df 100644 --- a/azure-toolkit-libs/azure-toolkit-sqlserver-lib/src/main/java/com/microsoft/azure/toolkit/lib/sqlserver/SqlServerManagerFactory.java +++ b/azure-toolkit-libs/azure-toolkit-sqlserver-lib/src/main/java/com/microsoft/azure/toolkit/lib/sqlserver/SqlServerManagerFactory.java @@ -1,3 +1,8 @@ +/* + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + */ + package com.microsoft.azure.toolkit.lib.sqlserver; import com.azure.core.http.policy.HttpLogDetailLevel; @@ -6,6 +11,7 @@ import com.azure.resourcemanager.sql.SqlServerManager; import com.microsoft.azure.toolkit.lib.Azure; import com.microsoft.azure.toolkit.lib.AzureConfiguration; +import com.microsoft.azure.toolkit.lib.AzureService; import com.microsoft.azure.toolkit.lib.auth.Account; import com.microsoft.azure.toolkit.lib.auth.AzureAccount; import com.microsoft.azure.toolkit.lib.common.cache.Cacheable; @@ -25,6 +31,7 @@ public static SqlServerManager create(String subscriptionId) { final HttpLogDetailLevel logLevel = Optional.ofNullable(config.getLogLevel()).map(HttpLogDetailLevel::valueOf).orElse(HttpLogDetailLevel.NONE); final AzureProfile azureProfile = new AzureProfile(null, subscriptionId, account.getEnvironment()); return SqlServerManager.configure() + .withHttpClient(AzureService.getDefaultHttpClient()) .withLogLevel(logLevel) .withPolicy(getUserAgentPolicy(userAgent)) .authenticate(account.getTokenCredential(subscriptionId), azureProfile); diff --git a/azure-toolkit-libs/azure-toolkit-storage-lib/src/main/java/com/microsoft/azure/toolkit/lib/storage/StorageManagerFactory.java b/azure-toolkit-libs/azure-toolkit-storage-lib/src/main/java/com/microsoft/azure/toolkit/lib/storage/StorageManagerFactory.java index 6af5ffab41..7cb3e6a370 100644 --- a/azure-toolkit-libs/azure-toolkit-storage-lib/src/main/java/com/microsoft/azure/toolkit/lib/storage/StorageManagerFactory.java +++ b/azure-toolkit-libs/azure-toolkit-storage-lib/src/main/java/com/microsoft/azure/toolkit/lib/storage/StorageManagerFactory.java @@ -11,6 +11,7 @@ import com.azure.resourcemanager.storage.StorageManager; import com.microsoft.azure.toolkit.lib.Azure; import com.microsoft.azure.toolkit.lib.AzureConfiguration; +import com.microsoft.azure.toolkit.lib.AzureService; import com.microsoft.azure.toolkit.lib.auth.Account; import com.microsoft.azure.toolkit.lib.auth.AzureAccount; import com.microsoft.azure.toolkit.lib.common.cache.Cacheable; @@ -30,6 +31,7 @@ public static StorageManager create(String subscriptionId) { final HttpLogDetailLevel logLevel = Optional.ofNullable(config.getLogLevel()).map(HttpLogDetailLevel::valueOf).orElse(HttpLogDetailLevel.NONE); final AzureProfile azureProfile = new AzureProfile(null, subscriptionId, account.getEnvironment()); return StorageManager.configure() + .withHttpClient(AzureService.getDefaultHttpClient()) .withLogLevel(logLevel) .withPolicy(getUserAgentPolicy(userAgent)) .authenticate(account.getTokenCredential(subscriptionId), azureProfile); From 7540ed0f3650512adfae0ad4b3bc32a844d2a20e Mon Sep 17 00:00:00 2001 From: andxu Date: Tue, 28 Sep 2021 16:47:18 +0800 Subject: [PATCH 123/126] update proper version for netty --- azure-toolkit-libs/pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/azure-toolkit-libs/pom.xml b/azure-toolkit-libs/pom.xml index 94601d0b3d..3b5e7801ef 100644 --- a/azure-toolkit-libs/pom.xml +++ b/azure-toolkit-libs/pom.xml @@ -85,7 +85,7 @@ 12.11.1 12.9.1 12.5.1 - 1.11.0 + 1.9.2 1.9.7.M3 3.3.0 1.15 @@ -118,7 +118,7 @@ 1.1.1 0.9.1 0.9.12 - 1.0.11 + 1.0.6 1.9.2 9.15 3.1.0 From a22a7b71e69d2ac178f423044ba13ccf7542af0f Mon Sep 17 00:00:00 2001 From: andxu Date: Tue, 28 Sep 2021 21:47:02 +0800 Subject: [PATCH 124/126] Provide different resolver depending on whether proxy is present --- .../azure/toolkit/lib/AzureService.java | 20 +++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/azure-toolkit-libs/azure-toolkit-common-lib/src/main/java/com/microsoft/azure/toolkit/lib/AzureService.java b/azure-toolkit-libs/azure-toolkit-common-lib/src/main/java/com/microsoft/azure/toolkit/lib/AzureService.java index ec3aa127ba..a844d0fa72 100644 --- a/azure-toolkit-libs/azure-toolkit-common-lib/src/main/java/com/microsoft/azure/toolkit/lib/AzureService.java +++ b/azure-toolkit-libs/azure-toolkit-common-lib/src/main/java/com/microsoft/azure/toolkit/lib/AzureService.java @@ -23,12 +23,15 @@ import com.microsoft.azure.toolkit.lib.common.exception.AzureToolkitRuntimeException; import com.microsoft.azure.toolkit.lib.common.model.Region; import com.microsoft.azure.toolkit.lib.common.model.Subscription; +import io.netty.resolver.AddressResolverGroup; import io.netty.resolver.DefaultAddressResolverGroup; +import io.netty.resolver.NoopAddressResolverGroup; import org.apache.commons.lang3.StringUtils; import java.net.InetSocketAddress; import java.util.ArrayList; import java.util.List; +import java.util.Optional; import java.util.stream.Collectors; import static com.microsoft.azure.toolkit.lib.Azure.az; @@ -95,20 +98,25 @@ private static synchronized HttpClient createHttpClient() { return defaultHttpClient; } - reactor.netty.http.client.HttpClient nettyHttpClient = - reactor.netty.http.client.HttpClient.create() - .resolver(DefaultAddressResolverGroup.INSTANCE); - NettyAsyncHttpClientBuilder builder = new NettyAsyncHttpClientBuilder(nettyHttpClient); + AddressResolverGroup resolverGroup; + ProxyOptions proxyOptions = null; final AzureConfiguration config = Azure.az().config(); if (StringUtils.isNotBlank(config.getProxySource())) { - final ProxyOptions proxyOptions = new ProxyOptions(ProxyOptions.Type.HTTP, + proxyOptions = new ProxyOptions(ProxyOptions.Type.HTTP, new InetSocketAddress(config.getHttpProxyHost(), config.getHttpProxyPort()) ); if (StringUtils.isNoneBlank(config.getProxyUsername(), config.getProxyPassword())) { proxyOptions.setCredentials(config.getProxyUsername(), config.getProxyPassword()); } - builder.proxy(proxyOptions); + resolverGroup = NoopAddressResolverGroup.INSTANCE; + } else { + resolverGroup = DefaultAddressResolverGroup.INSTANCE; } + reactor.netty.http.client.HttpClient nettyHttpClient = + reactor.netty.http.client.HttpClient.create() + .resolver(resolverGroup); + NettyAsyncHttpClientBuilder builder = new NettyAsyncHttpClientBuilder(nettyHttpClient); + Optional.ofNullable(proxyOptions).map(proxy -> builder.proxy(proxy)); defaultHttpClient = builder.build(); return defaultHttpClient; } From f438c0a3f1dfbf3431bbb1439c884fd91f6f1682 Mon Sep 17 00:00:00 2001 From: andxu Date: Wed, 29 Sep 2021 09:24:56 +0800 Subject: [PATCH 125/126] Fix null version issue in sql server entity. --- .../azure/toolkit/lib/sqlserver/model/SqlServerEntity.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/azure-toolkit-libs/azure-toolkit-sqlserver-lib/src/main/java/com/microsoft/azure/toolkit/lib/sqlserver/model/SqlServerEntity.java b/azure-toolkit-libs/azure-toolkit-sqlserver-lib/src/main/java/com/microsoft/azure/toolkit/lib/sqlserver/model/SqlServerEntity.java index aec5e6bc09..88098f3948 100644 --- a/azure-toolkit-libs/azure-toolkit-sqlserver-lib/src/main/java/com/microsoft/azure/toolkit/lib/sqlserver/model/SqlServerEntity.java +++ b/azure-toolkit-libs/azure-toolkit-sqlserver-lib/src/main/java/com/microsoft/azure/toolkit/lib/sqlserver/model/SqlServerEntity.java @@ -75,6 +75,11 @@ public String getState() { return remoteOptional().map(SqlServer::state).orElse(null); } + @Override + public String getVersion() { + return remoteOptional().map(SqlServer::version).orElse(null); + } + private Optional remoteOptional() { return Optional.ofNullable(this.remote); } From 14d33370e5fae3a3813268fd5fef52138bd7eb97 Mon Sep 17 00:00:00 2001 From: Hanxiao Liu Date: Wed, 29 Sep 2021 15:43:09 +0800 Subject: [PATCH 126/126] Change IAzureResource to IAzureBaseResource --- .../microsoft/azure/toolkit/lib/common/action/Action.java | 6 +++--- .../toolkit/lib/common/operation/AzureOperationAspect.java | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/azure-toolkit-libs/azure-toolkit-common-lib/src/main/java/com/microsoft/azure/toolkit/lib/common/action/Action.java b/azure-toolkit-libs/azure-toolkit-common-lib/src/main/java/com/microsoft/azure/toolkit/lib/common/action/Action.java index 32f590a092..45a090a141 100644 --- a/azure-toolkit-libs/azure-toolkit-common-lib/src/main/java/com/microsoft/azure/toolkit/lib/common/action/Action.java +++ b/azure-toolkit-libs/azure-toolkit-common-lib/src/main/java/com/microsoft/azure/toolkit/lib/common/action/Action.java @@ -6,7 +6,7 @@ package com.microsoft.azure.toolkit.lib.common.action; import com.microsoft.azure.toolkit.lib.common.bundle.AzureString; -import com.microsoft.azure.toolkit.lib.common.entity.IAzureResource; +import com.microsoft.azure.toolkit.lib.common.entity.IAzureBaseResource; import com.microsoft.azure.toolkit.lib.common.operation.AzureOperation; import com.microsoft.azure.toolkit.lib.common.operation.IAzureOperation; import com.microsoft.azure.toolkit.lib.common.task.AzureTask; @@ -109,8 +109,8 @@ public void handle(D source, Object e) { } protected void handle(D source, Object e, BiConsumer handler) { - if (source instanceof IAzureResource) { - AzureTelemetry.getActionContext().setProperty("subscriptionId", ((IAzureResource) source).subscriptionId()); + if (source instanceof IAzureBaseResource) { + AzureTelemetry.getActionContext().setProperty("subscriptionId", ((IAzureBaseResource) source).subscriptionId()); AzureTelemetry.getActionContext().setProperty("resourceType", source.getClass().getSimpleName()); } handler.accept(source, e); diff --git a/azure-toolkit-libs/azure-toolkit-common-lib/src/main/java/com/microsoft/azure/toolkit/lib/common/operation/AzureOperationAspect.java b/azure-toolkit-libs/azure-toolkit-common-lib/src/main/java/com/microsoft/azure/toolkit/lib/common/operation/AzureOperationAspect.java index 5466920830..8dce594e55 100644 --- a/azure-toolkit-libs/azure-toolkit-common-lib/src/main/java/com/microsoft/azure/toolkit/lib/common/operation/AzureOperationAspect.java +++ b/azure-toolkit-libs/azure-toolkit-common-lib/src/main/java/com/microsoft/azure/toolkit/lib/common/operation/AzureOperationAspect.java @@ -5,7 +5,7 @@ package com.microsoft.azure.toolkit.lib.common.operation; -import com.microsoft.azure.toolkit.lib.common.entity.IAzureResource; +import com.microsoft.azure.toolkit.lib.common.entity.IAzureBaseResource; import com.microsoft.azure.toolkit.lib.common.event.AzureEventBus; import com.microsoft.azure.toolkit.lib.common.event.AzureOperationEvent; import com.microsoft.azure.toolkit.lib.common.task.AzureTaskContext; @@ -72,8 +72,8 @@ public void afterThrowing(JoinPoint point, Throwable e) throws Throwable { final AzureOperationEvent event = new AzureOperationEvent(target, operation, AzureOperationEvent.Stage.ERROR); AzureEventBus.emit(operation.getName(), event); } - if (source instanceof IAzureResource) { - ((IAzureResource) source).refresh(); + if (source instanceof IAzureBaseResource) { + ((IAzureBaseResource) source).refresh(); } if (!(e instanceof RuntimeException)) { throw e; // do not wrap checked exception