-
Notifications
You must be signed in to change notification settings - Fork 53
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #259 from jleopold28/plan_only
Issue #162: Support "Plan only"
- Loading branch information
Showing
8 changed files
with
209 additions
and
59 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
## [PlanOnlyPlugin](../src/PlanOnlyPlugin.groovy) | ||
|
||
Enable this plugin to change pipeline functionality to `terraform plan`. | ||
|
||
``` | ||
// Jenkinsfile | ||
@Library(['terraform-pipeline@v3.10']) _ | ||
Jenkinsfile.init(this, env) | ||
// This enables the "plan only" functionality | ||
PlanOnlyPlugin.init() | ||
def validate = new TerraformValidateStage() | ||
def destroyQa = new TerraformEnvironmentStage('qa') | ||
def destroyUat = new TerraformEnvironmentStage('uat') | ||
def destroyProd = new TerraformEnvironmentStage('prod') | ||
validate.then(destroyQa) | ||
.then(destroyUat) | ||
.then(destroyProd) | ||
.build() | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
import static TerraformEnvironmentStage.APPLY | ||
import static TerraformEnvironmentStage.CONFIRM | ||
|
||
class PlanOnlyPlugin implements TerraformEnvironmentStagePlugin, TerraformPlanCommandPlugin { | ||
|
||
public static void init() { | ||
PlanOnlyPlugin plugin = new PlanOnlyPlugin() | ||
|
||
Jenkinsfile.instance.addParam([ | ||
$class: 'hudson.model.BooleanParameterDefinition', | ||
name: "FAIL_PLAN_ON_CHANGES", | ||
defaultValue: false, | ||
description: 'Plan run with -detailed-exitcode; ANY CHANGES will cause failure' | ||
]) | ||
|
||
TerraformPlanCommand.addPlugin(plugin) | ||
TerraformEnvironmentStage.addPlugin(plugin) | ||
} | ||
|
||
public Closure skipStage(String stageName) { | ||
return { closure -> | ||
echo "Skipping ${stageName} stage. PlanOnlyPlugin is enabled." | ||
} | ||
} | ||
|
||
@Override | ||
public void apply(TerraformEnvironmentStage stage) { | ||
stage.decorateAround(CONFIRM, skipStage(CONFIRM)) | ||
stage.decorateAround(APPLY, skipStage(APPLY)) | ||
} | ||
|
||
@Override | ||
public void apply(TerraformPlanCommand command) { | ||
if (Jenkinsfile.instance.getEnv().FAIL_PLAN_ON_CHANGES == 'true') { | ||
// set -e: fail on error | ||
// set -o pipefail: return non-zero exit code if any command fails. | ||
// useful when commands are piped together (ie. `terraform plan | landscape`) | ||
command.withPrefix('set -e; set -o pipefail;') | ||
command.withArgument('-detailed-exitcode') | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,104 @@ | ||
import static org.hamcrest.Matchers.containsString | ||
import static org.hamcrest.Matchers.hasItem | ||
import static org.hamcrest.Matchers.instanceOf | ||
import static org.hamcrest.Matchers.not | ||
import static org.junit.Assert.assertThat | ||
import static org.mockito.Mockito.spy; | ||
import static org.mockito.Mockito.verify; | ||
import static org.mockito.Mockito.any; | ||
import static org.mockito.Mockito.eq; | ||
import static org.mockito.Mockito.times; | ||
import static org.mockito.Mockito.when; | ||
import static org.mockito.Mockito.mock; | ||
import org.junit.Test | ||
import org.junit.Before | ||
import org.junit.After | ||
import org.junit.runner.RunWith | ||
import de.bechte.junit.runners.context.HierarchicalContextRunner | ||
|
||
@RunWith(HierarchicalContextRunner.class) | ||
class PlanOnlyPluginTest { | ||
@Before | ||
void resetJenkinsEnv() { | ||
Jenkinsfile.instance = mock(Jenkinsfile.class) | ||
when(Jenkinsfile.instance.getEnv()).thenReturn([:]) | ||
} | ||
|
||
private configureJenkins(Map config = [:]) { | ||
Jenkinsfile.instance = mock(Jenkinsfile.class) | ||
when(Jenkinsfile.instance.getEnv()).thenReturn(config.env ?: [:]) | ||
} | ||
|
||
public class Init { | ||
@After | ||
void resetPlugins() { | ||
TerraformPlanCommand.resetPlugins() | ||
TerraformEnvironmentStage.reset() | ||
} | ||
|
||
@Test | ||
void modifiesTerraformEnvironmentStageCommand() { | ||
PlanOnlyPlugin.init() | ||
|
||
Collection actualPlugins = TerraformEnvironmentStage.getPlugins() | ||
assertThat(actualPlugins, hasItem(instanceOf(PlanOnlyPlugin.class))) | ||
} | ||
|
||
@Test | ||
void addsParameter() { | ||
PlanOnlyPlugin.init() | ||
|
||
Collection actualParms = Jenkinsfile.instance.params | ||
assertThat(actualParms, hasItem([ | ||
$class: 'hudson.model.BooleanParameterDefinition', | ||
name: "FAIL_PLAN_ON_CHANGES", | ||
defaultValue: false, | ||
description: 'Plan run with -detailed-exitcode; ANY CHANGES will cause failure' | ||
])) | ||
} | ||
} | ||
|
||
public class Apply { | ||
|
||
@Test | ||
void decoratesTheTerraformEnvironmentStage() { | ||
PlanOnlyPlugin plugin = new PlanOnlyPlugin() | ||
def environment = spy(new TerraformEnvironmentStage()) | ||
plugin.apply(environment) | ||
|
||
verify(environment, times(1)).decorateAround(eq(TerraformEnvironmentStage.CONFIRM), any(Closure.class)) | ||
verify(environment, times(1)).decorateAround(eq(TerraformEnvironmentStage.APPLY), any(Closure.class)) | ||
} | ||
|
||
@Test | ||
void addsArgumentToTerraformPlan() { | ||
PlanOnlyPlugin plugin = new PlanOnlyPlugin() | ||
TerraformPlanCommand command = new TerraformPlanCommand() | ||
configureJenkins(env: [ | ||
'FAIL_PLAN_ON_CHANGES': 'true' | ||
]) | ||
|
||
plugin.apply(command) | ||
|
||
String result = command.toString() | ||
assertThat(result, containsString("-detailed-exitcode")) | ||
assertThat(result, containsString("set -e; set -o pipefail")) | ||
} | ||
|
||
@Test | ||
void doesNotAddArgumentToTerraformPlan() { | ||
PlanOnlyPlugin plugin = new PlanOnlyPlugin() | ||
TerraformPlanCommand command = new TerraformPlanCommand() | ||
configureJenkins(env: [ | ||
'FAIL_PLAN_ON_CHANGES': 'false' | ||
]) | ||
|
||
plugin.apply(command) | ||
|
||
String result = command.toString() | ||
assertThat(result, not(containsString("-detailed-exitcode"))) | ||
assertThat(result, not(containsString("set -e; set -o pipefail"))) | ||
} | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters