Skip to content

Commit

Permalink
Upgrade to Terraform 0.12
Browse files Browse the repository at this point in the history
To be clear, Atlantis was compatible with 0.12 before this commit, but
this change makes 0.12 the default version *if* users haven't set the
--default-tf-version flag.
  • Loading branch information
lkysow committed May 23, 2019
1 parent 756bf18 commit 8b816dd
Show file tree
Hide file tree
Showing 36 changed files with 391 additions and 78 deletions.
6 changes: 5 additions & 1 deletion .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,11 @@ jobs:
docker:
- image: circleci/golang:1.12
environment:
TERRAFORM_VERSION: 0.11.13
# This version of TF will be downloaded before Atlantis is started.
# We do this instead of setting --default-tf-version because setting
# that flag starts the download asynchronously so we'd have a race
# condition.
TERRAFORM_VERSION: 0.12.0
steps:
- checkout
- run: make build-service
Expand Down
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ FROM runatlantis/atlantis-base:v3.0
LABEL authors="Anubhav Mishra, Luke Kysow"

# install terraform binaries
ENV DEFAULT_TERRAFORM_VERSION=0.11.13
ENV DEFAULT_TERRAFORM_VERSION=0.12.0

# In the official Atlantis image we only have the latest of each Terrafrom version.
RUN AVAILABLE_TERRAFORM_VERSIONS="0.8.8 0.9.11 0.10.8 ${DEFAULT_TERRAFORM_VERSION}" && \
Expand Down
8 changes: 7 additions & 1 deletion scripts/e2e.sh
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,13 @@ ${CIRCLE_WORKING_DIRECTORY}/scripts/e2e-deps.sh
cd "${CIRCLE_WORKING_DIRECTORY}/e2e"

# start atlantis server in the background and wait for it to start
./atlantis server --gh-user="$GITHUB_USERNAME" --gh-token="$GITHUB_PASSWORD" --data-dir="/tmp" --log-level="debug" --repo-whitelist="github.com/runatlantis/atlantis-tests" --allow-repo-config &> /tmp/atlantis-server.log &
./atlantis server \
--gh-user="$GITHUB_USERNAME" \
--gh-token="$GITHUB_PASSWORD" \
--data-dir="/tmp" \
--log-level="debug" \
--repo-whitelist="github.com/runatlantis/atlantis-tests" \
--allow-repo-config &> /tmp/atlantis-server.log &
sleep 2

# start ngrok in the background and wait for it to start
Expand Down
12 changes: 6 additions & 6 deletions server/events/terraform/terraform_client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -218,26 +218,26 @@ func TestRunCommandWithVersion_DLsTF(t *testing.T) {

mockDownloader := mocks.NewMockDownloader()
// Set up our mock downloader to write a fake tf binary when it's called.
baseURL := "https://releases.hashicorp.com/terraform/0.12.0"
expURL := fmt.Sprintf("%s/terraform_0.12.0_%s_%s.zip?checksum=file:%s/terraform_0.12.0_SHA256SUMS",
baseURL := "https://releases.hashicorp.com/terraform/99.99.99"
expURL := fmt.Sprintf("%s/terraform_99.99.99_%s_%s.zip?checksum=file:%s/terraform_99.99.99_SHA256SUMS",
baseURL,
runtime.GOOS,
runtime.GOARCH,
baseURL)
When(mockDownloader.GetFile(filepath.Join(tmp, "bin", "terraform0.12.0"), expURL)).Then(func(params []pegomock.Param) pegomock.ReturnValues {
err := ioutil.WriteFile(params[0].(string), []byte("#!/bin/sh\necho '\nTerraform v0.12.0\n'"), 0755)
When(mockDownloader.GetFile(filepath.Join(tmp, "bin", "terraform99.99.99"), expURL)).Then(func(params []pegomock.Param) pegomock.ReturnValues {
err := ioutil.WriteFile(params[0].(string), []byte("#!/bin/sh\necho '\nTerraform v99.99.99\n'"), 0755)
return []pegomock.ReturnValue{err}
})

c, err := terraform.NewClient(nil, tmp, "", "0.11.10", cmd.DefaultTFVersionFlag, mockDownloader)
Ok(t, err)
Equals(t, "0.11.10", c.DefaultVersion().String())

v, err := version.NewVersion("0.12.0")
v, err := version.NewVersion("99.99.99")
Ok(t, err)
output, err := c.RunCommandWithVersion(nil, tmp, nil, v, "")
Assert(t, err == nil, "err: %s: %s", err, output)
Equals(t, "\nTerraform v0.12.0\n\n", output)
Equals(t, "\nTerraform v99.99.99\n\n", output)
}

// tempSetEnv sets env var key to value. It returns a function that when called
Expand Down
53 changes: 47 additions & 6 deletions server/events_controller_e2e_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,9 @@ import (
"strings"
"testing"

getter "github.com/hashicorp/go-getter"
"github.com/hashicorp/go-version"

"github.com/hashicorp/go-getter"
"github.com/runatlantis/atlantis/server/events/db"
"github.com/runatlantis/atlantis/server/events/yaml/valid"

Expand Down Expand Up @@ -44,6 +46,9 @@ func TestGitHubWorkflow(t *testing.T) {
if testing.Short() {
t.SkipNow()
}
// Ensure we have >= TF 0.12 locally.
ensureRunning012(t)

cases := []struct {
Description string
// RepoDir is relative to testfixtures/test-repos.
Expand Down Expand Up @@ -617,15 +622,15 @@ func assertCommentEquals(t *testing.T, expFile string, act string, repoDir strin
exp, err := ioutil.ReadFile(filepath.Join(absRepoPath(t, repoDir), expFile))
Ok(t, err)

// Replace all 'Creation complete after 1s ID: 1111818181' strings with
// 'Creation complete after *s ID: **********' so we can do a comparison.
idRegex := regexp.MustCompile(`Creation complete after [0-9]+s \(ID: [0-9]+\)`)
act = idRegex.ReplaceAllString(act, "Creation complete after *s (ID: ******************)")
// Replace all 'Creation complete after 0s [id=2135833172528078362]' strings with
// 'Creation complete after *s [id=*******************]' so we can do a comparison.
idRegex := regexp.MustCompile(`Creation complete after [0-9]+s \[id=[0-9]+]`)
act = idRegex.ReplaceAllString(act, "Creation complete after *s [id=*******************]")

// Replace all null_resource.simple{n}: .* with null_resource.simple: because
// with multiple resources being created the logs are all out of order which
// makes comparison impossible.
resourceRegex := regexp.MustCompile(`null_resource\.simple\d?:.*`)
resourceRegex := regexp.MustCompile(`null_resource\.simple(\[\d])?\d?:.*`)
act = resourceRegex.ReplaceAllString(act, "null_resource.simple:")

expStr := string(exp)
Expand Down Expand Up @@ -654,3 +659,39 @@ func assertCommentEquals(t *testing.T, expFile string, act string, repoDir strin
}
}
}

// Will fail test if terraform isn't in path and isn't version >= 0.12
func ensureRunning012(t *testing.T) {
localPath, err := exec.LookPath("terraform")
if err != nil {
t.Log("terraform >= 0.12 must be installed to run this test")
t.FailNow()
}
versionOutBytes, err := exec.Command(localPath, "version").Output() // #nosec
if err != nil {
t.Logf("error running terraform version: %s", err)
t.FailNow()
}
versionOutput := string(versionOutBytes)
match := versionRegex.FindStringSubmatch(versionOutput)
if len(match) <= 1 {
t.Logf("could not parse terraform version from %s", versionOutput)
t.FailNow()
}
localVersion, err := version.NewVersion(match[1])
Ok(t, err)
minVersion, err := version.NewVersion("0.12.0")
Ok(t, err)
if localVersion.LessThan(minVersion) {
t.Logf("must have terraform version >= %s, you have %s", minVersion, localVersion)
t.FailNow()
}
}

// versionRegex extracts the version from `terraform version` output.
// Terraform v0.12.0-alpha4 (2c36829d3265661d8edbd5014de8090ea7e2a076)
// => 0.12.0-alpha4
//
// Terraform v0.11.10
// => 0.11.10
var versionRegex = regexp.MustCompile("Terraform v(.*?)(\\s.*)?\n")
Original file line number Diff line number Diff line change
@@ -1,10 +1,17 @@
Ran Apply for dir: `dir1` workspace: `default`

```diff
null_resource.automerge: Creating...
null_resource.automerge: Creation complete after *s (ID: ******************)
null_resource.automerge[0]: Creating...
null_resource.automerge[0]: Creation complete after *s [id=*******************]

Apply complete! Resources: 1 added, 0 changed, 0 destroyed.

The state of your infrastructure has been saved to the path
below. This state is required to modify and destroy your
infrastructure, so keep it safe. To inspect the complete state
use the `terraform show` command.

State path: terraform.tfstate

```

Original file line number Diff line number Diff line change
@@ -1,10 +1,17 @@
Ran Apply for dir: `dir2` workspace: `default`

```diff
null_resource.automerge: Creating...
null_resource.automerge: Creation complete after *s (ID: ******************)
null_resource.automerge[0]: Creating...
null_resource.automerge[0]: Creation complete after *s [id=*******************]

Apply complete! Resources: 1 added, 0 changed, 0 destroyed.

The state of your infrastructure has been saved to the path
below. This state is required to modify and destroy your
infrastructure, so keep it safe. To inspect the complete state
use the `terraform show` command.

State path: terraform.tfstate

```

20 changes: 16 additions & 4 deletions server/testfixtures/test-repos/automerge/exp-output-autoplan.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ Ran Plan for 2 projects:
1. dir: `dir2` workspace: `default`

### 1. dir: `dir1` workspace: `default`
<details><summary>Show Output</summary>

```diff

An execution plan has been generated and is shown below.
Expand All @@ -12,8 +14,11 @@ Resource actions are indicated with the following symbols:

Terraform will perform the following actions:

+ null_resource.automerge
id: <computed>
# null_resource.automerge[0] will be created
+ resource "null_resource" "automerge" {
+ id = (known after apply)
}

Plan: 1 to add, 0 to change, 0 to destroy.

```
Expand All @@ -23,9 +28,12 @@ Plan: 1 to add, 0 to change, 0 to destroy.
* :put_litter_in_its_place: To **delete** this plan click [here](lock-url)
* :repeat: To **plan** this project again, comment:
* `atlantis plan -d dir1`
</details>

---
### 2. dir: `dir2` workspace: `default`
<details><summary>Show Output</summary>

```diff

An execution plan has been generated and is shown below.
Expand All @@ -34,8 +42,11 @@ Resource actions are indicated with the following symbols:

Terraform will perform the following actions:

+ null_resource.automerge
id: <computed>
# null_resource.automerge[0] will be created
+ resource "null_resource" "automerge" {
+ id = (known after apply)
}

Plan: 1 to add, 0 to change, 0 to destroy.

```
Expand All @@ -45,6 +56,7 @@ Plan: 1 to add, 0 to change, 0 to destroy.
* :put_litter_in_its_place: To **delete** this plan click [here](lock-url)
* :repeat: To **plan** this project again, comment:
* `atlantis plan -d dir2`
</details>

---
* :fast_forward: To **apply** all unapplied plans from this pull request, comment:
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,24 @@
Ran Apply for dir: `production` workspace: `default`

<details><summary>Show Output</summary>

```diff
module.null.null_resource.this: Creating...
module.null.null_resource.this: Creation complete after *s (ID: ******************)
module.null.null_resource.this: Creation complete after *s [id=*******************]

Apply complete! Resources: 1 added, 0 changed, 0 destroyed.

The state of your infrastructure has been saved to the path
below. This state is required to modify and destroy your
infrastructure, so keep it safe. To inspect the complete state
use the `terraform show` command.

State path: terraform.tfstate

Outputs:

var = production

```
</details>

Original file line number Diff line number Diff line change
@@ -1,14 +1,24 @@
Ran Apply for dir: `staging` workspace: `default`

<details><summary>Show Output</summary>

```diff
module.null.null_resource.this: Creating...
module.null.null_resource.this: Creation complete after *s (ID: ******************)
module.null.null_resource.this: Creation complete after *s [id=*******************]

Apply complete! Resources: 1 added, 0 changed, 0 destroyed.

The state of your infrastructure has been saved to the path
below. This state is required to modify and destroy your
infrastructure, so keep it safe. To inspect the complete state
use the `terraform show` command.

State path: terraform.tfstate

Outputs:

var = staging

```
</details>

Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ Ran Plan for 2 projects:
1. dir: `production` workspace: `default`

### 1. dir: `staging` workspace: `default`
<details><summary>Show Output</summary>

```diff

An execution plan has been generated and is shown below.
Expand All @@ -12,8 +14,11 @@ Resource actions are indicated with the following symbols:

Terraform will perform the following actions:

+ module.null.null_resource.this
id: <computed>
# module.null.null_resource.this will be created
+ resource "null_resource" "this" {
+ id = (known after apply)
}

Plan: 1 to add, 0 to change, 0 to destroy.

```
Expand All @@ -23,9 +28,12 @@ Plan: 1 to add, 0 to change, 0 to destroy.
* :put_litter_in_its_place: To **delete** this plan click [here](lock-url)
* :repeat: To **plan** this project again, comment:
* `atlantis plan -d staging`
</details>

---
### 2. dir: `production` workspace: `default`
<details><summary>Show Output</summary>

```diff

An execution plan has been generated and is shown below.
Expand All @@ -34,8 +42,11 @@ Resource actions are indicated with the following symbols:

Terraform will perform the following actions:

+ module.null.null_resource.this
id: <computed>
# module.null.null_resource.this will be created
+ resource "null_resource" "this" {
+ id = (known after apply)
}

Plan: 1 to add, 0 to change, 0 to destroy.

```
Expand All @@ -45,6 +56,7 @@ Plan: 1 to add, 0 to change, 0 to destroy.
* :put_litter_in_its_place: To **delete** this plan click [here](lock-url)
* :repeat: To **plan** this project again, comment:
* `atlantis plan -d production`
</details>

---
* :fast_forward: To **apply** all unapplied plans from this pull request, comment:
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,24 @@
Ran Apply for dir: `production` workspace: `default`

<details><summary>Show Output</summary>

```diff
module.null.null_resource.this: Creating...
module.null.null_resource.this: Creation complete after *s (ID: ******************)
module.null.null_resource.this: Creation complete after *s [id=*******************]

Apply complete! Resources: 1 added, 0 changed, 0 destroyed.

The state of your infrastructure has been saved to the path
below. This state is required to modify and destroy your
infrastructure, so keep it safe. To inspect the complete state
use the `terraform show` command.

State path: terraform.tfstate

Outputs:

var = production

```
</details>

Loading

0 comments on commit 8b816dd

Please sign in to comment.