/* * Copyright 2016 Google LLC. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ package com.google.cloud.tools.gradle.appengine.core; import com.google.cloud.tools.appengine.operations.cloudsdk.CloudSdkNotFoundException; import com.google.cloud.tools.managedcloudsdk.BadCloudSdkVersionException; import com.google.cloud.tools.managedcloudsdk.ManagedCloudSdk; import com.google.cloud.tools.managedcloudsdk.UnsupportedOsException; import com.google.cloud.tools.managedcloudsdk.components.SdkComponent; import org.gradle.api.GradleException; import org.gradle.api.Project; import org.gradle.util.GradleVersion; /** * Core plugin for App Engine, contains common tasks like deploy and show configuration Also * instantiates the "tools" extension to specify the cloud sdk path. */ public class AppEngineCorePluginConfiguration { public static final GradleVersion GRADLE_MIN_VERSION = GradleVersion.version("3.4.1"); public static final String LOGIN_TASK_NAME = "appengineCloudSdkLogin"; public static final String DEPLOY_TASK_NAME = "appengineDeploy"; public static final String DEPLOY_CRON_TASK_NAME = "appengineDeployCron"; public static final String DEPLOY_DISPATCH_TASK_NAME = "appengineDeployDispatch"; public static final String DEPLOY_DOS_TASK_NAME = "appengineDeployDos"; public static final String DEPLOY_INDEX_TASK_NAME = "appengineDeployIndex"; public static final String DEPLOY_QUEUE_TASK_NAME = "appengineDeployQueue"; public static final String DEPLOY_ALL_TASK_NAME = "appengineDeployAll"; public static final String SHOW_CONFIG_TASK_NAME = "appengineShowConfiguration"; public static final String DOWNLOAD_CLOUD_SDK_TASK_NAME = "downloadCloudSdk"; public static final String CHECK_CLOUD_SDK_TASK_NAME = "checkCloudSdk"; public static final String APPENGINE_EXTENSION = "appengine"; private Project project; private DeployExtension deployExtension; private ToolsExtension toolsExtension; private CloudSdkOperations cloudSdkOperations; private ManagedCloudSdk managedCloudSdk; private boolean requiresAppEngineJava; private String taskGroup; /** Configure core tasks for appengine app.yaml and appengine-web.xml based project plugins. */ public void configureCoreProperties( Project project, AppEngineCoreExtensionProperties appEngineCoreExtensionProperties, String taskGroup, boolean requiresAppEngineJava) { checkGradleVersion(); this.project = project; this.taskGroup = taskGroup; this.toolsExtension = appEngineCoreExtensionProperties.getTools(); this.deployExtension = appEngineCoreExtensionProperties.getDeploy(); this.requiresAppEngineJava = requiresAppEngineJava; configureFactories(); createDownloadCloudSdkTask(); createCheckCloudSdkTask(); createLoginTask(); createDeployTask(); createDeployCronTask(); createDeployDispatchTask(); createDeployDosTask(); createDeployIndexTask(); createDeployQueueTask(); createDeployAllTask(); createShowConfigurationTask(); } private void configureFactories() { project.afterEvaluate( projectAfterEvaluated -> { try { if (toolsExtension.getCloudSdkHome() == null) { managedCloudSdk = new ManagedCloudSdkFactory(toolsExtension.getCloudSdkVersion()).newManagedSdk(); toolsExtension.setCloudSdkHome(managedCloudSdk.getSdkHome().toFile()); } } catch (UnsupportedOsException ex) { throw new RuntimeException(ex.getMessage(), ex); } catch (BadCloudSdkVersionException ex) { throw new RuntimeException( "Failed to auto-configure Cloud Sdk at cloudSdkVersion = '" + toolsExtension.getCloudSdkVersion() + "': " + ex.getMessage(), ex); } try { cloudSdkOperations = new CloudSdkOperations( toolsExtension.getCloudSdkHome(), toolsExtension.getServiceAccountKeyFile()); } catch (CloudSdkNotFoundException ex) { // this should never happen, not found exception only occurs when auto-discovery fails, // but we don't use that mechanism anymore. throw new AssertionError("Failed when attempting to discover SDK: ", ex); } deployExtension.setDeployTargetResolver(new DeployTargetResolver(cloudSdkOperations)); }); } private void createDownloadCloudSdkTask() { project .getTasks() .create( DOWNLOAD_CLOUD_SDK_TASK_NAME, DownloadCloudSdkTask.class, downloadCloudSdkTask -> { downloadCloudSdkTask.setGroup(taskGroup); downloadCloudSdkTask.setDescription("Download the Cloud SDK"); // make sure we download our required components if (requiresAppEngineJava) { downloadCloudSdkTask.requiresComponent(SdkComponent.APP_ENGINE_JAVA); } project.afterEvaluate( p -> { if (managedCloudSdk != null) { downloadCloudSdkTask.setManagedCloudSdk(managedCloudSdk); if (p.getGradle().getStartParameter().isOffline()) { p.getLogger().debug("Skipping DownloadCloudSdk in --offline mode."); return; } p.getTasks() .matching(task -> task.getName().startsWith("appengine")) .forEach(task -> task.dependsOn(downloadCloudSdkTask)); } }); }); } private void createCheckCloudSdkTask() { project .getTasks() .create( CHECK_CLOUD_SDK_TASK_NAME, CheckCloudSdkTask.class, checkCloudSdkTask -> { checkCloudSdkTask.setGroup(taskGroup); checkCloudSdkTask.setDescription("Validates the Cloud SDK"); project.afterEvaluate( p -> { if (managedCloudSdk == null && toolsExtension.getCloudSdkVersion() != null) { checkCloudSdkTask.setVersion(toolsExtension.getCloudSdkVersion()); checkCloudSdkTask.setCloudSdk(cloudSdkOperations.getCloudSdk()); checkCloudSdkTask.requiresAppEngineJava(requiresAppEngineJava); p.getTasks() .matching(task -> task.getName().startsWith("appengine")) .forEach(task -> task.dependsOn(checkCloudSdkTask)); } }); }); } private void createLoginTask() { injectGcloud(CloudSdkLoginTask.class); project .getTasks() .create( LOGIN_TASK_NAME, CloudSdkLoginTask.class, loginTask -> { loginTask.setGroup(taskGroup); loginTask.setDescription("Login and set the Cloud SDK common configuration user"); project.afterEvaluate( project -> { if (toolsExtension.getServiceAccountKeyFile() != null) { loginTask.doLast( task -> project .getLogger() .warn( "WARNING: ServiceAccountKeyFile is configured and will be" + " used instead of Cloud SDK auth state")); } }); }); } private void createDeployTask() { injectGcloud(DeployTask.class); project .getTasks() .create( DEPLOY_TASK_NAME, DeployTask.class, deployTask -> { deployTask.setGroup(taskGroup); deployTask.setDescription("Deploy an App Engine application"); // deployConfig is set in AppEngineStandardPlugin and AppEngineAppYamlPlugin }); } private void createDeployCronTask() { injectGcloud(DeployCronTask.class); project .getTasks() .create( DEPLOY_CRON_TASK_NAME, DeployCronTask.class, deployTask -> { deployTask.setGroup(taskGroup); deployTask.setDescription("Deploy Cron configuration"); project.afterEvaluate( project -> { deployTask.setDeployExtension(deployExtension); }); }); } private void createDeployDispatchTask() { injectGcloud(DeployDispatchTask.class); project .getTasks() .create( DEPLOY_DISPATCH_TASK_NAME, DeployDispatchTask.class, deployTask -> { deployTask.setGroup(taskGroup); deployTask.setDescription("Deploy Dispatch configuration"); project.afterEvaluate( project -> { deployTask.setDeployExtension(deployExtension); }); }); } private void createDeployDosTask() { injectGcloud(DeployDosTask.class); project .getTasks() .create( DEPLOY_DOS_TASK_NAME, DeployDosTask.class, deployTask -> { deployTask.setGroup(taskGroup); deployTask.setDescription("Deploy Dos configuration"); project.afterEvaluate( project -> { deployTask.setDeployExtension(deployExtension); }); }); } private void createDeployIndexTask() { injectGcloud(DeployIndexTask.class); project .getTasks() .create( DEPLOY_INDEX_TASK_NAME, DeployIndexTask.class, deployTask -> { deployTask.setGroup(taskGroup); deployTask.setDescription("Deploy Index configuration"); project.afterEvaluate( project -> { deployTask.setDeployExtension(deployExtension); }); }); } private void createDeployQueueTask() { injectGcloud(DeployQueueTask.class); project .getTasks() .create( DEPLOY_QUEUE_TASK_NAME, DeployQueueTask.class, deployTask -> { deployTask.setGroup(taskGroup); deployTask.setDescription("Deploy Queue configuration"); project.afterEvaluate( project -> { deployTask.setDeployExtension(deployExtension); }); }); } private void createDeployAllTask() { injectGcloud(DeployAllTask.class); project .getTasks() .create( DEPLOY_ALL_TASK_NAME, DeployAllTask.class, deployAllTask -> { deployAllTask.setGroup(taskGroup); deployAllTask.setDescription( "Deploy an App Engine application and all of its config files"); // deployConfig is set in AppEngineStandardPlugin and AppEngineAppYamlPlugin }); } private void createShowConfigurationTask() { project .getTasks() .create( SHOW_CONFIG_TASK_NAME, ShowConfigurationTask.class, showConfigurationTask -> { showConfigurationTask.setGroup(taskGroup); showConfigurationTask.setDescription("Show current App Engine plugin configuration"); showConfigurationTask.setExtensionId(APPENGINE_EXTENSION); }); } private void checkGradleVersion() { if (GRADLE_MIN_VERSION.compareTo(GradleVersion.current()) > 0) { throw new GradleException( "Detected " + GradleVersion.current() + ", but the appengine-gradle-plugin requires " + GRADLE_MIN_VERSION + " or higher."); } } private void injectGcloud(Class<? extends GcloudTask> gcloudTask) { project .getTasks() .withType(gcloudTask) .whenTaskAdded( task -> project.afterEvaluate(project -> task.setGcloud(cloudSdkOperations.getGcloud()))); } }