Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
# Unreleased

* [Issue #344](https://github.com/manheim/terraform-pipeline/issues/344) Add PLAN_ONLY parameter to PlanOnlyPlugin
* **BREAKING CHANGE** This change is a breaking change. Prior to this update, applying the PlanOnlyPlugin would restrict the pipeline to only running `terraform plan`. This update changes behavior to simply providing a `PLAN_ONLY` boolean parameter that can be set to restrict the build behavior. It defaults to `false`.

# v5.15

* [Issue #172](https://github.com/manheim/terraform-pipeline/issues/172) Feature: ConditionalApplyPlugin - can allow apply for specific environments on all branches/PRs.
Expand Down
2 changes: 1 addition & 1 deletion docs/PlanOnlyPlugin.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
## [PlanOnlyPlugin](../src/PlanOnlyPlugin.groovy)

Enable this plugin to change pipeline functionality to `terraform plan`.
Enable this plugin to add a parameter to the build which will restrict pipeline functionality to `terraform plan` only.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This reads much better - thanks.


```
// Jenkinsfile
Expand Down
11 changes: 9 additions & 2 deletions src/PlanOnlyPlugin.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,11 @@ class PlanOnlyPlugin implements TerraformEnvironmentStagePlugin, TerraformPlanCo
public static void init() {
PlanOnlyPlugin plugin = new PlanOnlyPlugin()

BuildWithParametersPlugin.withBooleanParameter([
name: "PLAN_ONLY",
description: 'Run `terraform plan` only, skipping `terraform apply`.'
])

BuildWithParametersPlugin.withBooleanParameter([
name: "FAIL_PLAN_ON_CHANGES",
description: 'Plan run with -detailed-exitcode; ANY CHANGES will cause failure'
Expand All @@ -23,8 +28,10 @@ class PlanOnlyPlugin implements TerraformEnvironmentStagePlugin, TerraformPlanCo

@Override
public void apply(TerraformEnvironmentStage stage) {
stage.decorateAround(CONFIRM, skipStage(CONFIRM))
stage.decorateAround(APPLY, skipStage(APPLY))
if (Jenkinsfile.instance.getEnv().PLAN_ONLY == 'true') {
stage.decorateAround(CONFIRM, skipStage(CONFIRM))
stage.decorateAround(APPLY, skipStage(APPLY))
}
}

@Override
Expand Down
35 changes: 31 additions & 4 deletions test/PlanOnlyPluginTest.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ class PlanOnlyPluginTest {
}

@Test
void addsParameter() {
void addsFailPlanOnChangesParameter() {
PlanOnlyPlugin.init()

def parametersPlugin = new BuildWithParametersPlugin()
Expand All @@ -39,23 +39,50 @@ class PlanOnlyPluginTest {
description: 'Plan run with -detailed-exitcode; ANY CHANGES will cause failure'
]))
}

@Test
void addsPlanOnlyParameter() {
PlanOnlyPlugin.init()

def parametersPlugin = new BuildWithParametersPlugin()
Collection actualParms = parametersPlugin.getBuildParameters()

assertThat(actualParms, hasItem([
$class: 'hudson.model.BooleanParameterDefinition',
name: "PLAN_ONLY",
defaultValue: false,
description: 'Run `terraform plan` only, skipping `terraform apply`.'
]))
}
}

@Nested
public class Apply {

@Test
void decoratesTheTerraformEnvironmentStage() {
void decoratesTheTerraformEnvironmentStageWhenPlanOnlyTrue() {
PlanOnlyPlugin plugin = new PlanOnlyPlugin()
def environment = spy(new TerraformEnvironmentStage())
MockJenkinsfile.withEnv('PLAN_ONLY': 'true')
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() {
void doesNotDecorateTheTerraformEnvironmentStageWhenPlanOnlyTrue() {
PlanOnlyPlugin plugin = new PlanOnlyPlugin()
def environment = spy(new TerraformEnvironmentStage())
MockJenkinsfile.withEnv('PLAN_ONLY': 'false')
plugin.apply(environment)

verify(environment, times(0)).decorateAround(eq(TerraformEnvironmentStage.CONFIRM), any(Closure.class))
verify(environment, times(0)).decorateAround(eq(TerraformEnvironmentStage.APPLY), any(Closure.class))
}

@Test
void addsFailPlanOnChangesArgumentToTerraformPlan() {
PlanOnlyPlugin plugin = new PlanOnlyPlugin()
TerraformPlanCommand command = new TerraformPlanCommand()
MockJenkinsfile.withEnv('FAIL_PLAN_ON_CHANGES': 'true')
Expand All @@ -68,7 +95,7 @@ class PlanOnlyPluginTest {
}

@Test
void doesNotAddArgumentToTerraformPlan() {
void doesNotAddFailPlanOnChangesArgumentToTerraformPlan() {
PlanOnlyPlugin plugin = new PlanOnlyPlugin()
TerraformPlanCommand command = new TerraformPlanCommand()
MockJenkinsfile.withEnv('FAIL_PLAN_ON_CHANGES': 'false')
Expand Down