/* * MIT License * * Copyright (c) 2019 Choko ([email protected]) * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ package org.curioswitch.gradle.plugins.terraform; import com.google.common.collect.ImmutableList; import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.UncheckedIOException; import java.util.List; import org.curioswitch.gradle.plugins.terraform.tasks.ConvertConfigsToJsonTask; import org.curioswitch.gradle.plugins.terraform.tasks.HelmTask; import org.curioswitch.gradle.plugins.terraform.tasks.TargetableTerraformPlanTask; import org.curioswitch.gradle.plugins.terraform.tasks.TargetableTerraformTask; import org.curioswitch.gradle.plugins.terraform.tasks.TerraformImportTask; import org.curioswitch.gradle.plugins.terraform.tasks.TerraformOutputTask; import org.curioswitch.gradle.plugins.terraform.tasks.TerraformTask; import org.curioswitch.gradle.tooldownloader.DownloadedToolManager; import org.curioswitch.gradle.tooldownloader.util.DownloadToolUtil; import org.gradle.api.Plugin; import org.gradle.api.Project; import org.gradle.api.plugins.BasePlugin; import org.gradle.api.tasks.Copy; import org.gradle.api.tasks.TaskProvider; public class TerraformPlugin implements Plugin<Project> { @Override public void apply(Project project) { project.getRootProject().getPlugins().apply(TerraformSetupPlugin.class); project.getPlugins().apply(BasePlugin.class); var config = TerraformExtension.create(project); var convertConfigs = project.getTasks().create(ConvertConfigsToJsonTask.NAME, ConvertConfigsToJsonTask.class); var copyDependencies = project .getTasks() .register("terraformCopyDependencies", Copy.class, t -> t.into("build/terraform")); project.afterEvaluate( unused -> { for (var dependencyPath : config.getDependencies().get()) { var depedendency = project.findProject(dependencyPath); if (depedendency == null) { throw new IllegalStateException( "Could not find dependency project with path " + dependencyPath); } copyDependencies.configure( t -> { t.dependsOn(depedendency.getTasks().withType(ConvertConfigsToJsonTask.class)); t.from( depedendency.file("build/terraform"), copy -> copy.into(depedendency.getName())); }); } }); convertConfigs.dependsOn(BasePlugin.CLEAN_TASK_NAME, copyDependencies); List<TaskProvider<?>> sysadminOutputTasks = project.getPath().contains(":sysadmin") ? ImmutableList.of( createTerraformOutputTask( project, "outputTillerCaCert", "tiller-ca-cert", project.file("build/helm/ca.pem")), createTerraformOutputTask( project, "outputTillerCertKey", "tiller-client-key", project.file("build/helm/key.pem")), createTerraformOutputTask( project, "outputTillerCert", "tiller-client-cert", project.file("build/helm/cert.pem")), project .getTasks() .register( "terraformInitHelm", HelmTask.class, helm -> helm.args("init", "--client-only"))) : ImmutableList.of(); var gcloudInstallComponents = project.getRootProject().getTasks().named("gcloudInstallComponents"); var terraformInit = project .getTasks() .register( "terraformInit", TerraformTask.class, t -> { t.setArgs(ImmutableList.of("init", "-input=false")); t.setExecCustomizer( exec -> exec.environment( "TF_PLUGIN_CACHE_DIR", DownloadedToolManager.get(project) .getCuriostackDir() .resolve("terraform-plugins"))); sysadminOutputTasks.forEach(t::finalizedBy); t.dependsOn(gcloudInstallComponents); }); project .getTasks() .register( "terraformPlan", TargetableTerraformPlanTask.class, t -> { t.setArgs(ImmutableList.of("plan", "-input=false")); t.dependsOn(terraformInit); }); project .getTasks() .register( "terraformApply", TargetableTerraformTask.class, t -> { t.setArgs(ImmutableList.of("apply")); t.dependsOn(terraformInit); }); project .getTasks() .register( "terraformCopyState", TerraformTask.class, t -> { t.setArgs(ImmutableList.of("init", "-input=false", "-force-copy")); t.dependsOn(terraformInit); }); project .getTasks() .register( TerraformImportTask.NAME, TerraformImportTask.class, t -> { t.dependsOn(terraformInit); t.setArgs(ImmutableList.of("import", "-input=false")); }); project .getTasks() .register( TerraformOutputTask.NAME, TerraformOutputTask.class, t -> { t.dependsOn(terraformInit); t.setArgs(ImmutableList.of("output")); }); var setupTerraform = DownloadToolUtil.getSetupTask(project, "terraform"); project .getTasks() .withType(TerraformTask.class) .configureEach(t -> t.dependsOn(setupTerraform, convertConfigs)); project .getTasks() .withType(HelmTask.class) .configureEach(t -> t.dependsOn(DownloadToolUtil.getSetupTask(project, "helm"))); } private static TaskProvider<TerraformOutputTask> createTerraformOutputTask( Project project, String taskName, String outputName, File outputFile) { return project .getTasks() .register( taskName, TerraformOutputTask.class, t -> { t.doFirst(unused -> project.mkdir(outputFile.getParent())); t.setArgs(ImmutableList.of("output", outputName)); t.dependsOn(project.getTasks().getByName("terraformInit")); t.setExecCustomizer( exec -> { exec.setIgnoreExitValue(true); try { exec.setStandardOutput(new FileOutputStream(outputFile)); } catch (FileNotFoundException e) { throw new UncheckedIOException("Could not open file.", e); } }); }); } }