Merge pull request #175 from microsoft/hanli/stacks

Migrate to stacks API in gradle plugin
This commit is contained in:
Hanxiao Liu 2024-01-10 10:33:06 +08:00 коммит произвёл GitHub
Родитель 0df864abdb 842d33b3d1
Коммит 5902c7744d
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
18 изменённых файлов: 125 добавлений и 103 удалений

Просмотреть файл

@ -1,6 +1,7 @@
# Change Log
All notable changes to the "Azure Function Plugin for Gradle" will be documented in this file.
- [Change Log](#change-log)
- [1.15.0](#1150)
- [1.11.0](#1110)
- [1.10.0](#1100)
- [1.9.0](#190)
@ -14,6 +15,9 @@ All notable changes to the "Azure Function Plugin for Gradle" will be documented
- [1.1.0](#110)
- [1.0.0](#100)
## 1.15.0
- Migrate to use `stacks` API to get and validate function app runtime stacks
## 1.11.0
- Support Java 17 for Function App
- Improve stability/reliability of Authentication

Просмотреть файл

@ -21,7 +21,7 @@
# SOFTWARE.
group = com.microsoft.azure
version = 1.14.0
version = 1.15.0
pluginId = com.microsoft.azure.azurefunctions
pluginShortName = azurefunctions

Просмотреть файл

@ -18,7 +18,6 @@ import com.microsoft.azure.toolkit.lib.common.exception.AzureToolkitRuntimeExcep
import org.apache.commons.lang3.BooleanUtils;
import org.apache.commons.lang3.StringUtils;
import org.gradle.api.Project;
import org.gradle.api.tasks.Input;
import javax.annotation.Nullable;
import java.io.File;

Просмотреть файл

@ -8,18 +8,22 @@ package com.microsoft.azure.plugin.functions.gradle.handler;
import com.azure.core.management.AzureEnvironment;
import com.google.common.base.Preconditions;
import com.microsoft.azure.gradle.configuration.GradleRuntimeConfig;
import com.microsoft.azure.gradle.temeletry.TelemetryAgent;
import com.microsoft.azure.plugin.functions.gradle.GradleFunctionContext;
import com.microsoft.azure.toolkit.lib.Azure;
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.entity.FunctionEntity;
import com.microsoft.azure.toolkit.lib.appservice.function.AzureFunctions;
import com.microsoft.azure.toolkit.lib.appservice.function.FunctionApp;
import com.microsoft.azure.toolkit.lib.appservice.function.FunctionAppBase;
import com.microsoft.azure.toolkit.lib.appservice.function.FunctionsServiceSubscription;
import com.microsoft.azure.toolkit.lib.appservice.function.core.AzureFunctionsAnnotationConstants;
import com.microsoft.azure.toolkit.lib.appservice.model.FunctionDeployType;
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.*;
import com.microsoft.azure.toolkit.lib.appservice.plan.AppServicePlan;
import com.microsoft.azure.toolkit.lib.appservice.task.CreateOrUpdateFunctionAppTask;
import com.microsoft.azure.toolkit.lib.auth.AzureAccount;
import com.microsoft.azure.toolkit.lib.common.bundle.AzureString;
@ -27,6 +31,7 @@ import com.microsoft.azure.toolkit.lib.common.exception.AzureToolkitRuntimeExcep
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.operation.OperationContext;
import com.microsoft.azure.toolkit.lib.common.utils.Utils;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
@ -36,6 +41,7 @@ import reactor.core.scheduler.Schedulers;
import reactor.util.retry.Retry;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.io.File;
import java.lang.management.ManagementFactory;
import java.time.Duration;
@ -44,6 +50,7 @@ import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;
import static com.microsoft.azure.toolkit.lib.appservice.model.FunctionAppLinuxRuntime.*;
import static com.microsoft.azure.toolkit.lib.appservice.utils.AppServiceConfigUtils.fromAppService;
import static com.microsoft.azure.toolkit.lib.appservice.utils.AppServiceConfigUtils.mergeAppServiceConfig;
@ -95,7 +102,6 @@ public class DeployHandler {
private static final int LIST_TRIGGERS_RETRY_PERIOD_IN_SECONDS = 10;
private static final String NO_TRIGGERS_FOUNDED = "No triggers found in deployed function app, " +
"please try to deploy the project again.";
private static final String EXPANDABLE_JAVA_VERSION_WARNING = "'%s' may not be a valid java version, recommended values are `Java 8`, `Java 11` and `Java 17`";
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, " +
@ -108,8 +114,9 @@ public class DeployHandler {
}
public void execute() {
TelemetryAgent.getInstance().addDefaultProperty(FUNCTION_JAVA_VERSION_KEY, String.valueOf(javaVersion()));
TelemetryAgent.getInstance().addDefaultProperty(DISABLE_APP_INSIGHTS_KEY, String.valueOf(ctx.isDisableAppInsights()));
OperationContext.current().setTelemetryProperty(FUNCTION_JAVA_VERSION_KEY, StringUtils.firstNonBlank(getJavaVersion(), "N/A"));
OperationContext.current().setTelemetryProperty(DISABLE_APP_INSIGHTS_KEY, String.valueOf(ctx.isDisableAppInsights()));
((FunctionsServiceSubscription) ctx.getOrCreateAzureAppServiceClient().getParent()).loadRuntimes();
doValidate();
final FunctionAppBase<?, ?, ?> app = createOrUpdateFunctionApp();
deployArtifact(app);
@ -119,15 +126,19 @@ public class DeployHandler {
}
private RuntimeConfig getRuntimeConfig() {
final GradleRuntimeConfig runtime = ctx.getRuntime();
if (runtime == null) {
final GradleRuntimeConfig config = ctx.getRuntime();
if (config == null) {
return null;
}
final OperatingSystem os = Optional.ofNullable(runtime.os()).map(OperatingSystem::fromString).orElse(null);
final JavaVersion javaVersion = Optional.ofNullable(runtime.javaVersion()).map(JavaVersion::fromString).orElse(null);
return new RuntimeConfig().os(os).javaVersion(javaVersion).webContainer(WebContainer.JAVA_OFF)
.image(runtime.image()).registryUrl(runtime.registryUrl())
.username(runtime.username()).password(runtime.password());
final FunctionsServiceSubscription serviceSubscription = (FunctionsServiceSubscription) Azure.az(AzureFunctions.class)
.forSubscription(ctx.getOrCreateAzureAppServiceClient().getSubscriptionId());
serviceSubscription.loadRuntimes();
final OperatingSystem os = Optional.ofNullable(config.os()).map(OperatingSystem::fromString)
.orElseGet(() -> Optional.ofNullable(getFunctionApp()).map(FunctionApp::getAppServicePlan).map(AppServicePlan::getOperatingSystem).orElse(OperatingSystem.WINDOWS));
final String javaVersion = getJavaVersion();
return new RuntimeConfig().os(os).javaVersion(javaVersion)
.image(config.image()).registryUrl(config.registryUrl())
.username(config.username()).password(config.password());
}
/**
@ -224,10 +235,6 @@ public class DeployHandler {
if (StringUtils.isNotEmpty(runtime.os()) && OperatingSystem.fromString(runtime.os()) == null) {
throw new AzureToolkitRuntimeException(INVALID_OS);
}
// java version
if (StringUtils.isNotEmpty(runtime.javaVersion()) && JavaVersion.fromString(runtime.javaVersion()).isExpandedValue()) {
AzureMessager.getMessager().warning(AzureString.format(EXPANDABLE_JAVA_VERSION_WARNING, runtime.javaVersion()));
}
}
final String pricingTier = ctx.getPricingTier();
@ -310,8 +317,8 @@ public class DeployHandler {
throw new AzureToolkitRuntimeException(e.getMessage(), e);
} finally {
final long endTime = System.currentTimeMillis();
TelemetryAgent.getInstance().addDefaultProperty(String.format("%s-cost", name), String.valueOf(endTime - startTime));
TelemetryAgent.getInstance().addDefaultProperty(JVM_UP_TIME, String.valueOf(ManagementFactory.getRuntimeMXBean().getUptime()));
OperationContext.current().setTelemetryProperty(String.format("%s-cost", name), String.valueOf(endTime - startTime));
OperationContext.current().setTelemetryProperty(JVM_UP_TIME, String.valueOf(ManagementFactory.getRuntimeMXBean().getUptime()));
}
}
@ -333,9 +340,9 @@ public class DeployHandler {
// get java version according to project java version
final FunctionAppConfig result = AppServiceConfig.buildDefaultFunctionConfig(resourceGroup, appName);
final org.gradle.api.JavaVersion localRuntime = org.gradle.api.JavaVersion.current();
final JavaVersion javaVersion = localRuntime.isCompatibleWith(org.gradle.api.JavaVersion.VERSION_17) ? JavaVersion.JAVA_17 :
localRuntime.isJava11Compatible() ? JavaVersion.JAVA_11 : JavaVersion.JAVA_8;
result.runtime().javaVersion(javaVersion);
final Runtime runtime = localRuntime.isCompatibleWith(org.gradle.api.JavaVersion.VERSION_17) ? FUNCTION_JAVA17 :
localRuntime.isJava11Compatible() ? FUNCTION_JAVA11 : FUNCTION_JAVA8;
result.runtime(new RuntimeConfig().os(runtime.getOperatingSystem()).javaVersion(runtime.getJavaVersionUserText()));
result.subscriptionId(subscriptionId);
return result;
}
@ -357,7 +364,7 @@ public class DeployHandler {
if (runtime.os() == OperatingSystem.DOCKER) {
return;
}
final String javaVersion = Optional.of(runtime).map(RuntimeConfig::javaVersion).map(JavaVersion::getValue).orElse(StringUtils.EMPTY);
final String javaVersion = Optional.ofNullable(getJavaVersion()).orElse(StringUtils.EMPTY);
final File file = this.ctx.getProject().getArtifactFile().toFile();
final int runtimeVersion;
final int artifactCompileVersion;
@ -373,8 +380,9 @@ public class DeployHandler {
}
}
private JavaVersion javaVersion() {
return Objects.isNull(ctx.getRuntime()) ? null : JavaVersion.fromString(ctx.getRuntime().javaVersion());
@Nullable
private String getJavaVersion() {
return Optional.ofNullable(ctx.getRuntime()).map(GradleRuntimeConfig::javaVersion).orElse(null);
}
public FunctionApp getFunctionApp() {

Просмотреть файл

@ -14,21 +14,18 @@ import com.google.common.base.Preconditions;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import com.microsoft.azure.gradle.temeletry.TelemetryAgent;
import com.microsoft.azure.toolkit.lib.common.IProject;
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.operation.OperationContext;
import com.microsoft.azure.toolkit.lib.legacy.function.bindings.Binding;
import com.microsoft.azure.toolkit.lib.legacy.function.bindings.BindingEnum;
import com.microsoft.azure.toolkit.lib.legacy.function.configurations.FunctionConfiguration;
import com.microsoft.azure.toolkit.lib.legacy.function.handlers.AnnotationHandler;
import com.microsoft.azure.toolkit.lib.legacy.function.handlers.AnnotationHandlerImpl;
import com.microsoft.azure.toolkit.lib.legacy.function.handlers.CommandHandler;
import com.microsoft.azure.toolkit.lib.legacy.function.handlers.CommandHandlerImpl;
import com.microsoft.azure.toolkit.lib.legacy.function.handlers.FunctionCoreToolsHandler;
import com.microsoft.azure.toolkit.lib.legacy.function.handlers.FunctionCoreToolsHandlerImpl;
import com.microsoft.azure.toolkit.lib.legacy.function.handlers.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.input.BOMInputStream;
import org.apache.commons.lang3.StringUtils;
@ -43,15 +40,7 @@ import java.net.URL;
import java.nio.charset.Charset;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Scanner;
import java.util.Set;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
@ -114,8 +103,8 @@ public class PackageHandler {
final AnnotationHandler annotationHandler = getAnnotationHandler();
final Set<Method> methods = findAnnotatedMethods(annotationHandler);
if (methods.size() == 0) {
throw new AzureExecutionException(NO_FUNCTIONS);
if (CollectionUtils.isEmpty(methods)) {
throw new AzureToolkitRuntimeException(NO_FUNCTIONS);
}
final Map<String, FunctionConfiguration> configMap = getFunctionConfigurations(annotationHandler, methods);
@ -188,7 +177,7 @@ public class PackageHandler {
final Set<Method> methods) throws AzureExecutionException {
AzureMessager.getMessager().info(LINE_FEED + GENERATE_CONFIG);
final Map<String, FunctionConfiguration> configMap = handler.generateConfigurations(methods);
if (configMap.size() == 0) {
if (CollectionUtils.isEmpty(methods)) {
AzureMessager.getMessager().info(GENERATE_SKIP);
} else {
final String scriptFilePath = getScriptFilePath();
@ -205,7 +194,7 @@ public class PackageHandler {
private void validateFunctionConfigurations(final Map<String, FunctionConfiguration> configMap) {
AzureMessager.getMessager().info(LINE_FEED + VALIDATE_CONFIG);
if (configMap.size() == 0) {
if (MapUtils.isEmpty(configMap)) {
AzureMessager.getMessager().info(VALIDATE_SKIP);
} else {
configMap.values().forEach(FunctionConfiguration::validate);
@ -217,7 +206,7 @@ public class PackageHandler {
private void writeFunctionJsonFiles(final ObjectWriter objectWriter,
final Map<String, FunctionConfiguration> configMap) throws IOException {
AzureMessager.getMessager().info(LINE_FEED + SAVE_FUNCTION_JSONS);
if (configMap.size() == 0) {
if (MapUtils.isEmpty(configMap)) {
AzureMessager.getMessager().info(SAVE_SKIP);
} else {
for (final Map.Entry<String, FunctionConfiguration> config : configMap.entrySet()) {
@ -243,13 +232,13 @@ public class PackageHandler {
AzureMessager.getMessager().info(SAVE_SUCCESS + hostJsonFile.getAbsolutePath());
}
private void copyLocalSettingJsonFile() throws AzureExecutionException, IOException {
private void copyLocalSettingJsonFile() throws IOException {
AzureMessager.getMessager().info(LINE_FEED + SAVE_LOCAL_SETTINGS_JSON);
final File localSettingJsonTargetFile = Paths.get(this.deploymentStagingDirectoryPath, LOCAL_SETTINGS_JSON)
.toFile();
final File localSettingJsonSrcFile = new File(project.getBaseDirectory().toFile(), LOCAL_SETTINGS_JSON);
if (localSettingJsonSrcFile.exists() && localSettingJsonSrcFile.length() == 0) {
throw new AzureExecutionException("The " + localSettingJsonSrcFile.getAbsolutePath() +
throw new AzureToolkitRuntimeException("The " + localSettingJsonSrcFile.getAbsolutePath() +
" file is empty, please check the document at" + DOCS_LINK);
} else {
copyFilesWithDefaultContent(localSettingJsonSrcFile, localSettingJsonTargetFile, DEFAULT_LOCAL_SETTINGS_JSON);
@ -368,6 +357,6 @@ public class PackageHandler {
.sorted()
.distinct()
.collect(Collectors.toList());
TelemetryAgent.getInstance().addDefaultProperty(TRIGGER_TYPE, StringUtils.join(bindingTypeSet, ","));
OperationContext.current().setTelemetryProperty(TRIGGER_TYPE, StringUtils.join(bindingTypeSet, ","));
}
}

Просмотреть файл

@ -11,6 +11,7 @@ import com.microsoft.azure.plugin.functions.gradle.GradleFunctionContext;
import com.microsoft.azure.plugin.functions.gradle.handler.DeployHandler;
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.OperationContext;
import com.microsoft.azure.toolkit.lib.common.proxy.ProxyManager;
import org.gradle.api.DefaultTask;
import org.gradle.api.GradleException;
@ -42,10 +43,10 @@ public class DeployTask extends DefaultTask implements IFunctionTask {
public void deploy() throws GradleException {
try {
ProxyManager.getInstance().applyProxy();
TelemetryAgent.getInstance().addDefaultProperty(PROXY, String.valueOf(ProxyManager.getInstance().isProxyEnabled()));
OperationContext.current().setTelemetryProperty(PROXY, String.valueOf(ProxyManager.getInstance().isProxyEnabled()));
TelemetryAgent.getInstance().trackTaskStart(this.getClass());
final GradleFunctionContext ctx = new GradleFunctionContext(getProject(), this.getFunctionsExtension());
TelemetryAgent.getInstance().addDefaultProperties(ctx.getTelemetryProperties());
OperationContext.current().setTelemetryProperties(ctx.getTelemetryProperties());
final DeployHandler deployHandler = new DeployHandler(ctx);
deployHandler.execute();
TelemetryAgent.getInstance().trackTaskSuccess(this.getClass());

Просмотреть файл

@ -18,9 +18,11 @@ import org.gradle.api.tasks.Exec;
import org.gradle.api.tasks.Nested;
import org.gradle.api.tasks.TaskAction;
import org.gradle.api.tasks.options.Option;
import org.gradle.process.ExecResult;
import javax.annotation.Nullable;
import java.io.File;
import java.util.Optional;
public class LocalRunTask extends Exec implements IFunctionTask {
@ -77,7 +79,7 @@ public class LocalRunTask extends Exec implements IFunctionTask {
this.setWorkingDir(new File(stagingFolder));
this.setIgnoreExitValue(true);
super.exec();
final int code = this.getExecResult().getExitValue();
final int code = Optional.ofNullable(getExecResult()).map(ExecResult::getExitValue).orElse(-1);
for (final Long validCode : CommandUtils.getValidReturnCodes()) {
if (validCode != null && validCode.intValue() == code) {
TelemetryAgent.getInstance().trackTaskSuccess(this.getClass());

Просмотреть файл

@ -9,6 +9,7 @@ import com.microsoft.azure.plugin.functions.gradle.AzureFunctionsExtension;
import com.microsoft.azure.plugin.functions.gradle.GradleFunctionContext;
import com.microsoft.azure.plugin.functions.gradle.handler.PackageHandler;
import com.microsoft.azure.toolkit.lib.common.operation.AzureOperation;
import com.microsoft.azure.toolkit.lib.common.operation.OperationContext;
import org.apache.commons.io.FileUtils;
import org.gradle.api.DefaultTask;
import org.gradle.api.GradleException;
@ -40,7 +41,7 @@ public class PackageTask extends DefaultTask implements IFunctionTask {
try {
TelemetryAgent.getInstance().trackTaskStart(this.getClass());
final GradleFunctionContext ctx = new GradleFunctionContext(getProject(), this.getFunctionsExtension());
TelemetryAgent.getInstance().addDefaultProperties(ctx.getTelemetryProperties());
OperationContext.current().setTelemetryProperties(ctx.getTelemetryProperties());
final File stagingFolder = new File(ctx.getDeploymentStagingDirectoryPath());
// package task will start from a empty staging folder
if (stagingFolder.exists()) {

Просмотреть файл

@ -18,7 +18,6 @@ import org.zeroturnaround.zip.ZipUtil;
import javax.annotation.Nullable;
import java.io.File;
import java.io.IOException;
public class PackageZipTask extends DefaultTask implements IFunctionTask {
private static final String PACKAGE_ZIP_FAILURE = "Cannot build zip for azure functions due to error: ";
@ -38,7 +37,7 @@ public class PackageZipTask extends DefaultTask implements IFunctionTask {
}
@TaskAction
public void buildZip() throws GradleException, IOException {
public void buildZip() throws GradleException {
try {
TelemetryAgent.getInstance().trackTaskStart(this.getClass());
final GradleFunctionContext ctx = new GradleFunctionContext(getProject(), this.getFunctionsExtension());

Просмотреть файл

@ -5,7 +5,7 @@
package com.microsoft.azure.plugin.functions.gradle.util;
import com.microsoft.azure.plugin.functions.gradle.handler.PackageHandler;
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 java.io.File;
@ -17,20 +17,20 @@ public class FunctionUtils {
private static final String HOST_JSON_NOT_FOUND = "File 'host.json' cannot be found at staging directory.";
private static final String LOCAL_SETTINGS_JSON_NOT_FOUND = "File 'local.settings.json' cannot be found at staging directory.";
public static void checkStagingDirectory(String stagingFolder) throws AzureExecutionException {
public static void checkStagingDirectory(String stagingFolder) throws AzureToolkitRuntimeException {
final File file = new File(stagingFolder);
if (!file.exists() || !file.isDirectory()) {
throw new AzureExecutionException(STAGE_DIR_NOT_FOUND);
throw new AzureToolkitRuntimeException(STAGE_DIR_NOT_FOUND);
}
AzureMessager.getMessager().info(STAGE_DIR_FOUND + stagingFolder);
final File hostJson = new File(file, PackageHandler.HOST_JSON);
if (!hostJson.exists() || !hostJson.isFile()) {
throw new AzureExecutionException(HOST_JSON_NOT_FOUND);
throw new AzureToolkitRuntimeException(HOST_JSON_NOT_FOUND);
}
final File localSettingsJson = new File(file, PackageHandler.LOCAL_SETTINGS_JSON);
if (!localSettingsJson.exists() || !localSettingsJson.isFile()) {
throw new AzureExecutionException(LOCAL_SETTINGS_JSON_NOT_FOUND);
throw new AzureToolkitRuntimeException(LOCAL_SETTINGS_JSON_NOT_FOUND);
}
}
}

Просмотреть файл

@ -21,4 +21,4 @@
# SOFTWARE.
group = com.microsoft.azure
version = 1.8.0
version = 1.9.0

Просмотреть файл

@ -6,20 +6,14 @@
package com.microsoft.azure.gradle.auth;
import com.azure.core.management.AzureEnvironment;
import com.microsoft.azure.gradle.temeletry.TelemetryAgent;
import com.microsoft.azure.gradle.temeletry.TelemetryConstants;
import com.microsoft.azure.toolkit.lib.Azure;
import com.microsoft.azure.toolkit.lib.auth.Account;
import com.microsoft.azure.toolkit.lib.auth.AuthConfiguration;
import com.microsoft.azure.toolkit.lib.auth.AuthType;
import com.microsoft.azure.toolkit.lib.auth.AzureAccount;
import com.microsoft.azure.toolkit.lib.auth.AzureCloud;
import com.microsoft.azure.toolkit.lib.auth.AzureEnvironmentUtils;
import com.microsoft.azure.toolkit.lib.auth.AzureToolkitAuthenticationException;
import com.microsoft.azure.toolkit.lib.auth.*;
import com.microsoft.azure.toolkit.lib.common.bundle.AzureString;
import com.microsoft.azure.toolkit.lib.common.exception.InvalidConfigurationException;
import com.microsoft.azure.toolkit.lib.common.messager.AzureMessager;
import com.microsoft.azure.toolkit.lib.common.model.Subscription;
import com.microsoft.azure.toolkit.lib.common.telemetry.AzureTelemeter;
import com.microsoft.azure.toolkit.lib.common.utils.TextUtils;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.ObjectUtils;
@ -85,7 +79,7 @@ public class GradleAuthHelper {
if (StringUtils.isBlank(targetSubscriptionId) && !subscriptions.isEmpty()) {
targetSubscriptionId = subscriptions.stream().map(Subscription::getId).findFirst().orElse(null);
}
TelemetryAgent.getInstance().addDefaultProperty(TelemetryConstants.SUBSCRIPTION_ID_KEY, targetSubscriptionId);
AzureTelemeter.getClient().addDefaultProperty(TelemetryConstants.SUBSCRIPTION_ID_KEY, Optional.ofNullable(targetSubscriptionId).orElse(StringUtils.EMPTY));
return targetSubscriptionId;
}
@ -100,9 +94,9 @@ public class GradleAuthHelper {
AzureMessager.getMessager().info(AzureString.format(USING_AZURE_ENVIRONMENT, environmentName));
}
printCredentialDescription(account, isInteractiveLogin);
TelemetryAgent.getInstance().addDefaultProperty(TelemetryConstants.AUTH_TYPE_KEY, Objects.toString(auth.getType()));
TelemetryAgent.getInstance().addDefaultProperty(TelemetryConstants.AUTH_METHOD_KEY, Objects.toString(account.getType()));
TelemetryAgent.getInstance().addDefaultProperty(TelemetryConstants.AZURE_ENVIRONMENT_KEY, environmentName);
AzureTelemeter.getClient().addDefaultProperty(TelemetryConstants.AUTH_TYPE_KEY, Objects.toString(auth.getType()));
AzureTelemeter.getClient().addDefaultProperty(TelemetryConstants.AUTH_METHOD_KEY, Objects.toString(account.getType()));
AzureTelemeter.getClient().addDefaultProperty(TelemetryConstants.AZURE_ENVIRONMENT_KEY, environmentName);
return account;
}

Просмотреть файл

@ -16,6 +16,7 @@ import org.apache.commons.lang3.exception.ExceptionUtils;
import javax.annotation.Nonnull;
import java.io.*;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.HashMap;
import java.util.Map;
@ -104,7 +105,7 @@ public class TelemetryAgent {
try {
final File configurationFile = new File(CONFIGURATION_PATH);
if (configurationFile.exists()) {
try (InputStream input = new FileInputStream(CONFIGURATION_PATH)) {
try (InputStream input = Files.newInputStream(Paths.get(CONFIGURATION_PATH))) {
prop.load(input);
final String firstRunValue = prop.getProperty(FIRST_RUN_KEY);
if (firstRunValue != null && firstRunValue.equalsIgnoreCase("false")) {
@ -123,7 +124,7 @@ public class TelemetryAgent {
}
private void updateConfigurationFile(Properties prop) {
try (OutputStream output = new FileOutputStream(CONFIGURATION_PATH)) {
try (OutputStream output = Files.newOutputStream(Paths.get(CONFIGURATION_PATH))) {
prop.setProperty(FIRST_RUN_KEY, "false");
prop.store(output, "Azure Gradle Plugin configurations");
} catch (Exception e) {

Просмотреть файл

@ -1,6 +1,7 @@
# Change Log
All notable changes to the "Azure WebApp Plugin for Gradle" will be documented in this file.
- [Change Log](#change-log)
- [1.10.0](#1100)
- [1.6.0](#160)
- [1.5.0](#150)
- [1.4.0](#140)
@ -9,6 +10,9 @@ All notable changes to the "Azure WebApp Plugin for Gradle" will be documented i
- [1.1.0](#110)
- [1.0.0](#100)
## 1.10.0
- Migrate to use `stacks` API to get and validate web app runtime stacks
## 1.6.0
- Improve stability/reliability of Authentication

Просмотреть файл

@ -21,7 +21,7 @@
# SOFTWARE.
group = com.microsoft.azure
version = 1.9.0
version = 1.10.0
pluginId = com.microsoft.azure.azurewebapp
pluginShortName = azurewebapp

Просмотреть файл

@ -246,10 +246,10 @@ public class AzureWebappPluginExtension {
public Map<String, String> getTelemetryProperties() {
final Map<String, String> result = new HashMap<>();
final GradleRuntimeConfig runtime = getRuntime();
final String os = java.util.Optional.ofNullable(runtime).map(GradleRuntimeConfig::os).orElse(null);
final String os = java.util.Optional.ofNullable(runtime).map(GradleRuntimeConfig::os).orElse(StringUtils.EMPTY);
result.put(OS_KEY, os);
result.put(JAVA_VERSION_KEY, java.util.Optional.ofNullable(runtime).map(GradleRuntimeConfig::javaVersion).orElse(null));
result.put(JAVA_WEB_CONTAINER_KEY, java.util.Optional.ofNullable(runtime).map(GradleRuntimeConfig::webContainer).orElse(null));
result.put(JAVA_VERSION_KEY, java.util.Optional.ofNullable(runtime).map(GradleRuntimeConfig::javaVersion).orElse(StringUtils.EMPTY));
result.put(JAVA_WEB_CONTAINER_KEY, java.util.Optional.ofNullable(runtime).map(GradleRuntimeConfig::webContainer).orElse(StringUtils.EMPTY));
result.put(PRICING_TIER_KEY, pricingTier);
result.put(REGION_KEY, region);
if (runtime != null && StringUtils.equalsIgnoreCase(os, OperatingSystem.DOCKER.getValue())) {

Просмотреть файл

@ -13,7 +13,10 @@ import com.microsoft.azure.gradle.temeletry.TelemetryAgent;
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.*;
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.WebAppLinuxRuntime;
import com.microsoft.azure.toolkit.lib.appservice.task.CreateOrUpdateWebAppTask;
import com.microsoft.azure.toolkit.lib.appservice.task.DeployWebAppTask;
import com.microsoft.azure.toolkit.lib.appservice.utils.AppServiceConfigUtils;
@ -21,11 +24,14 @@ import com.microsoft.azure.toolkit.lib.appservice.utils.Utils;
import com.microsoft.azure.toolkit.lib.appservice.webapp.AzureWebApp;
import com.microsoft.azure.toolkit.lib.appservice.webapp.WebApp;
import com.microsoft.azure.toolkit.lib.appservice.webapp.WebAppBase;
import com.microsoft.azure.toolkit.lib.appservice.webapp.WebAppServiceSubscription;
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.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.operation.OperationContext;
import com.microsoft.azure.toolkit.lib.common.proxy.ProxyManager;
import com.microsoft.azure.toolkit.lib.common.validator.SchemaValidator;
import com.microsoft.azure.toolkit.lib.common.validator.ValidationMessage;
@ -38,7 +44,7 @@ import org.gradle.api.DefaultTask;
import org.gradle.api.GradleException;
import org.gradle.api.tasks.TaskAction;
import javax.annotation.Nullable;
import javax.annotation.Nonnull;
import java.io.File;
import java.util.Collections;
import java.util.List;
@ -50,14 +56,13 @@ import java.util.stream.Collectors;
import static com.microsoft.azure.toolkit.lib.appservice.utils.AppServiceConfigUtils.fromAppService;
import static com.microsoft.azure.toolkit.lib.appservice.utils.AppServiceConfigUtils.mergeAppServiceConfig;
@Setter
public class DeployTask extends DefaultTask {
private static final String PROXY = "proxy";
private static final String INVALID_PARAMETER_ERROR_MESSAGE = "Invalid values found in configuration, please correct the value with messages below:";
@Setter
private AzureWebappPluginExtension azureWebappExtension;
@Setter
private String artifactFile;
@TaskAction
@ -65,16 +70,19 @@ public class DeployTask extends DefaultTask {
public void deploy() throws GradleException {
try {
ProxyManager.getInstance().applyProxy();
TelemetryAgent.getInstance().addDefaultProperty(PROXY, String.valueOf(ProxyManager.getInstance().isProxyEnabled()));
TelemetryAgent.getInstance().addDefaultProperties(azureWebappExtension.getTelemetryProperties());
OperationContext.current().setTelemetryProperty(PROXY, String.valueOf(ProxyManager.getInstance().isProxyEnabled()));
OperationContext.current().setTelemetryProperties(azureWebappExtension.getTelemetryProperties());
TelemetryAgent.getInstance().trackTaskStart(this.getClass());
final GradleWebAppConfig config = parseConfiguration();
normalizeConfigValue(config);
validate(config);
config.subscriptionId(GradleAuthHelper.login(azureWebappExtension.getAuth(), config.subscriptionId()));
azureWebappExtension.setSubscription(config.subscriptionId());
((WebAppServiceSubscription) Azure.az(AzureWebApp.class).webApps(config.subscriptionId()).getParent()).loadRuntimes();
validateOnline(config);
final WebAppBase<?, ?, ?> target = createOrUpdateWebapp(config);
deployArtifact(target, config);
AzureMessager.getMessager().info(AzureString.format("Application url: %s", "https://" + target.getHostName()));
TelemetryAgent.getInstance().trackTaskSuccess(this.getClass());
} catch (Exception e) {
AzureMessager.getMessager().error(e);
@ -121,8 +129,14 @@ public class DeployTask extends DefaultTask {
buildDefaultConfig(appServiceConfig.subscriptionId(), appServiceConfig.resourceGroup(), appServiceConfig.appName());
mergeAppServiceConfig(appServiceConfig, defaultConfig);
if (appServiceConfig.pricingTier() == null) {
appServiceConfig.pricingTier(
StringUtils.containsIgnoreCase(Objects.toString(appServiceConfig.runtime().webContainer()), "jboss") ? PricingTier.PREMIUM_P1V3 : PricingTier.PREMIUM_P1V2);
final RuntimeConfig runtime = appServiceConfig.runtime();
final OperatingSystem operatingSystem = Optional.ofNullable(runtime).map(RuntimeConfig::os).orElse(null);
final String jboss = WebAppLinuxRuntime.JBOSS7_JAVA17.getContainerName();
if (operatingSystem == OperatingSystem.LINUX && StringUtils.containsIgnoreCase(runtime.webContainer(), jboss)) {
appServiceConfig.pricingTier(PricingTier.PREMIUM_P1V3);
} else {
appServiceConfig.pricingTier(PricingTier.PREMIUM_P1V2);
}
}
CreateOrUpdateWebAppTask task = new CreateOrUpdateWebAppTask(appServiceConfig);
task.setSkipCreateAzureResource(skipCreate);
@ -132,8 +146,7 @@ public class DeployTask extends DefaultTask {
private AppServiceConfig buildDefaultConfig(String subscriptionId, String resourceGroup, String appName) {
final String packaging = FilenameUtils.getExtension(StringUtils.firstNonBlank(this.artifactFile, ""));
// get java version according to project java version
JavaVersion javaVersion = org.gradle.api.JavaVersion.current().isJava8() ? JavaVersion.JAVA_8 : JavaVersion.JAVA_11;
return AppServiceConfigUtils.buildDefaultWebAppConfig(subscriptionId, resourceGroup, appName, packaging, javaVersion);
return AppServiceConfigUtils.buildDefaultWebAppConfig(subscriptionId, resourceGroup, appName, packaging);
}
private AppServiceConfig convert(GradleWebAppConfig config) {
@ -147,21 +160,28 @@ public class DeployTask extends DefaultTask {
.deploymentSlotConfigurationSource(config.deploymentSlotConfigurationSource())
.pricingTier(Optional.ofNullable(config.pricingTier()).map(PricingTier::fromString).orElse(null))
.region(Optional.ofNullable(config.region()).map(Region::fromName).orElse(null))
.runtime(convert(config.runtime()))
.runtime(getRuntimeConfig(config))
.servicePlanName(config.servicePlanName())
.appSettings(config.appSettings());
}
private RuntimeConfig convert(@Nullable GradleRuntimeConfig configNullable) {
return Optional.ofNullable(configNullable).map(config -> new RuntimeConfig()
.os(Optional.ofNullable(config.os()).map(OperatingSystem::fromString).orElse(null))
.webContainer(Optional.ofNullable(config.webContainer()).map(WebContainer::fromString).orElse(null))
.javaVersion(Optional.ofNullable(config.javaVersion()).map(JavaVersion::fromString).orElse(null))
.registryUrl(config.registryUrl())
.image(config.image())
.username(config.username())
.password(config.password())
.startUpCommand(config.startUpCommand())).orElse(null);
private RuntimeConfig getRuntimeConfig(@Nonnull GradleWebAppConfig webAppConfig) {
final GradleRuntimeConfig config = webAppConfig.runtime();
if (Objects.isNull(config)) {
return null;
}
final OperatingSystem os = Optional.ofNullable(config.os()).map(OperatingSystem::fromString).orElse(null);
final String javaVersion = Optional.of(config.javaVersion()).filter(StringUtils::isNotEmpty).orElse(null);
final String webContainer = Optional.of(config.webContainer()).filter(StringUtils::isNotEmpty).orElse(null);
return new RuntimeConfig()
.os(os)
.webContainer(webContainer)
.javaVersion(javaVersion)
.registryUrl(config.registryUrl())
.image(config.image())
.username(config.username())
.password(config.password())
.startUpCommand(config.startUpCommand());
}
private GradleWebAppConfig parseConfiguration() {
@ -194,7 +214,7 @@ public class DeployTask extends DefaultTask {
}
private void normalizeConfigValue(GradleWebAppConfig config) {
if (StringUtils.isNotBlank(config.region()) && Region.fromName(config.region()) != null) {
if (StringUtils.isNotBlank(config.region())) {
config.region(Region.fromName(config.region()).getName());
}
}

Просмотреть файл

@ -33,7 +33,7 @@ subprojects {
targetCompatibility = 1.8
ext {
azureToolkitVersion = "0.38.0"
azureToolkitVersion = "0.40.0"
}
checkstyle {