Skip to content

Commit

Permalink
Autodownload tf versions. Add --default-tf-version.
Browse files Browse the repository at this point in the history
This changeset has two features:
1. We now automatically download the version of terraform specified in
atlantis.yaml configs if we don't already have that version available
locally.

2. Add a new --default-tf-version flag that allows users to set a
default version of Terraform that we will also download if it's not on
disk.

These mean that users don't need to build custom Docker images to just
add terraform versions. It also means that upgrading the version of
terraform that is packaged with the Atlantis Docker image won't cause
issues for existing users because as long as they're running with
--default-tf-version, Atlantis will always use that version.
  • Loading branch information
lkysow committed Mar 14, 2019
1 parent 81a8735 commit 41603ed
Show file tree
Hide file tree
Showing 13 changed files with 460 additions and 68 deletions.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ go-generate: ## Run go generate in all packages
#echo "this doesn't work anymore: go generate \$\$(go list ./... | grep -v e2e | grep -v vendor | grep -v static)"

test: ## Run tests
@go test -race -short $(PKG)
@go test -short $(PKG)

test-all: ## Run tests including integration
@go test $(PKG)
Expand Down
15 changes: 11 additions & 4 deletions cmd/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ const (
ConfigFlag = "config"
CheckoutStrategyFlag = "checkout-strategy"
DataDirFlag = "data-dir"
DefaultTFVersionFlag = "default-tf-version"
GHHostnameFlag = "gh-hostname"
GHTokenFlag = "gh-token"
GHUserFlag = "gh-user"
Expand Down Expand Up @@ -192,6 +193,11 @@ var stringFlags = []stringFlag{
" Only set if using TFE as a backend." +
" Should be specified via the ATLANTIS_TFE_TOKEN environment variable for security.",
},
{
name: DefaultTFVersionFlag,
description: "Terraform version to default to (ex. v0.12.0). Will download if not yet on disk." +
" If not set, Atlantis uses the terraform binary in its PATH.",
},
}
var boolFlags = []boolFlag{
{
Expand Down Expand Up @@ -383,10 +389,11 @@ func (s *ServerCmd) run() error {

// Config looks good. Start the server.
server, err := s.ServerCreator.NewServer(userConfig, server.Config{
AllowForkPRsFlag: AllowForkPRsFlag,
AllowRepoConfigFlag: AllowRepoConfigFlag,
AtlantisURLFlag: AtlantisURLFlag,
AtlantisVersion: s.AtlantisVersion,
AllowForkPRsFlag: AllowForkPRsFlag,
AllowRepoConfigFlag: AllowRepoConfigFlag,
AtlantisURLFlag: AtlantisURLFlag,
AtlantisVersion: s.AtlantisVersion,
DefaultTFVersionFlag: DefaultTFVersionFlag,
})
if err != nil {
return errors.Wrap(err, "initializing server")
Expand Down
14 changes: 14 additions & 0 deletions cmd/server_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -341,6 +341,7 @@ func TestExecute_Defaults(t *testing.T) {
Equals(t, dataDir, passedConfig.DataDir)

Equals(t, "branch", passedConfig.CheckoutStrategy)
Equals(t, "", passedConfig.DefaultTFVersion)
Equals(t, "github.com", passedConfig.GithubHostname)
Equals(t, "token", passedConfig.GithubToken)
Equals(t, "user", passedConfig.GithubUser)
Expand Down Expand Up @@ -446,6 +447,7 @@ func TestExecute_Flags(t *testing.T) {
cmd.BitbucketWebhookSecretFlag: "bitbucket-secret",
cmd.CheckoutStrategyFlag: "merge",
cmd.DataDirFlag: "/path",
cmd.DefaultTFVersionFlag: "v0.11.0",
cmd.GHHostnameFlag: "ghhostname",
cmd.GHTokenFlag: "token",
cmd.GHUserFlag: "user",
Expand Down Expand Up @@ -477,6 +479,7 @@ func TestExecute_Flags(t *testing.T) {
Equals(t, "bitbucket-secret", passedConfig.BitbucketWebhookSecret)
Equals(t, "merge", passedConfig.CheckoutStrategy)
Equals(t, "/path", passedConfig.DataDir)
Equals(t, "v0.11.0", passedConfig.DefaultTFVersion)
Equals(t, "ghhostname", passedConfig.GithubHostname)
Equals(t, "token", passedConfig.GithubToken)
Equals(t, "user", passedConfig.GithubUser)
Expand Down Expand Up @@ -509,6 +512,7 @@ bitbucket-user: "bitbucket-user"
bitbucket-webhook-secret: "bitbucket-secret"
checkout-strategy: "merge"
data-dir: "/path"
default-tf-version: "v0.11.0"
gh-hostname: "ghhostname"
gh-token: "token"
gh-user: "user"
Expand Down Expand Up @@ -544,6 +548,7 @@ tfe-token: my-token
Equals(t, "bitbucket-secret", passedConfig.BitbucketWebhookSecret)
Equals(t, "merge", passedConfig.CheckoutStrategy)
Equals(t, "/path", passedConfig.DataDir)
Equals(t, "v0.11.0", passedConfig.DefaultTFVersion)
Equals(t, "ghhostname", passedConfig.GithubHostname)
Equals(t, "token", passedConfig.GithubToken)
Equals(t, "user", passedConfig.GithubUser)
Expand Down Expand Up @@ -576,6 +581,7 @@ bitbucket-user: "bitbucket-user"
bitbucket-webhook-secret: "bitbucket-secret"
checkout-strategy: "merge"
data-dir: "/path"
default-tf-version: "v0.11.0"
gh-hostname: "ghhostname"
gh-token: "token"
gh-user: "user"
Expand Down Expand Up @@ -607,6 +613,7 @@ tfe-token: my-token
"BITBUCKET_WEBHOOK_SECRET": "override-bitbucket-secret",
"CHECKOUT_STRATEGY": "branch",
"DATA_DIR": "/override-path",
"DEFAULT_TF_VERSION": "v0.12.0",
"GH_HOSTNAME": "override-gh-hostname",
"GH_TOKEN": "override-gh-token",
"GH_USER": "override-gh-user",
Expand Down Expand Up @@ -642,6 +649,7 @@ tfe-token: my-token
Equals(t, "override-bitbucket-secret", passedConfig.BitbucketWebhookSecret)
Equals(t, "branch", passedConfig.CheckoutStrategy)
Equals(t, "/override-path", passedConfig.DataDir)
Equals(t, "v0.12.0", passedConfig.DefaultTFVersion)
Equals(t, "override-gh-hostname", passedConfig.GithubHostname)
Equals(t, "override-gh-token", passedConfig.GithubToken)
Equals(t, "override-gh-user", passedConfig.GithubUser)
Expand Down Expand Up @@ -674,6 +682,7 @@ bitbucket-user: "bitbucket-user"
bitbucket-webhook-secret: "bitbucket-secret"
checkout-strategy: "merge"
data-dir: "/path"
default-tf-version: "v0.11.0"
gh-hostname: "ghhostname"
gh-token: "token"
gh-user: "user"
Expand Down Expand Up @@ -705,6 +714,7 @@ tfe-token: my-token
cmd.BitbucketWebhookSecretFlag: "override-bitbucket-secret",
cmd.CheckoutStrategyFlag: "branch",
cmd.DataDirFlag: "/override-path",
cmd.DefaultTFVersionFlag: "v0.12.0",
cmd.GHHostnameFlag: "override-gh-hostname",
cmd.GHTokenFlag: "override-gh-token",
cmd.GHUserFlag: "override-gh-user",
Expand Down Expand Up @@ -734,6 +744,7 @@ tfe-token: my-token
Equals(t, "override-bitbucket-secret", passedConfig.BitbucketWebhookSecret)
Equals(t, "branch", passedConfig.CheckoutStrategy)
Equals(t, "/override-path", passedConfig.DataDir)
Equals(t, "v0.12.0", passedConfig.DefaultTFVersion)
Equals(t, "override-gh-hostname", passedConfig.GithubHostname)
Equals(t, "override-gh-token", passedConfig.GithubToken)
Equals(t, "override-gh-user", passedConfig.GithubUser)
Expand Down Expand Up @@ -768,6 +779,7 @@ func TestExecute_FlagEnvVarOverride(t *testing.T) {
"BITBUCKET_WEBHOOK_SECRET": "bitbucket-secret",
"CHECKOUT_STRATEGY": "merge",
"DATA_DIR": "/path",
"DEFAULT_TF_VERSION": "v0.11.0",
"GH_HOSTNAME": "gh-hostname",
"GH_TOKEN": "gh-token",
"GH_USER": "gh-user",
Expand Down Expand Up @@ -807,6 +819,7 @@ func TestExecute_FlagEnvVarOverride(t *testing.T) {
cmd.BitbucketWebhookSecretFlag: "override-bitbucket-secret",
cmd.CheckoutStrategyFlag: "branch",
cmd.DataDirFlag: "/override-path",
cmd.DefaultTFVersionFlag: "v0.12.0",
cmd.GHHostnameFlag: "override-gh-hostname",
cmd.GHTokenFlag: "override-gh-token",
cmd.GHUserFlag: "override-gh-user",
Expand Down Expand Up @@ -838,6 +851,7 @@ func TestExecute_FlagEnvVarOverride(t *testing.T) {
Equals(t, "override-bitbucket-secret", passedConfig.BitbucketWebhookSecret)
Equals(t, "branch", passedConfig.CheckoutStrategy)
Equals(t, "/override-path", passedConfig.DataDir)
Equals(t, "v0.12.0", passedConfig.DefaultTFVersion)
Equals(t, "override-gh-hostname", passedConfig.GithubHostname)
Equals(t, "override-gh-token", passedConfig.GithubToken)
Equals(t, "override-gh-user", passedConfig.GithubUser)
Expand Down
2 changes: 1 addition & 1 deletion runatlantis.io/docs/atlantis-yaml-reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ workflow: myworkflow
| dir | string | none | yes | The directory of this project relative to the repo root. Use `.` for the root. For example if the project was under `./project1` then use `project1` |
| workspace | string | default | no | The [Terraform workspace](https://www.terraform.io/docs/state/workspaces.html) for this project. Atlantis will switch to this workplace when planning/applying and will create it if it doesn't exist. |
| autoplan | [Autoplan](atlantis-yaml-reference.html#autoplan) | none | no | A custom autoplan configuration. If not specified, will use the default algorithm. See [Autoplanning](autoplanning.html). |
| terraform_version | string | none | no | A specific Terraform version to use when running commands for this project. Requires there to be a binary in the Atlantis `PATH` with the name `terraform{VERSION}`, ex. `terraform0.11.0` |
| terraform_version | string | none | no | A specific Terraform version to use when running commands for this project. Atlantis automatically downloads this version to `{datadir}/bin/terraform{version}`. |
| apply_requirements | array[string] | [] | no | Requirements that must be satisfied before `atlantis apply` can be run. Currently the only supported requirements are `approved` and `mergeable`. See [Apply Requirements](apply-requirements.html) for more details. |
| workflow | string | none | no | A custom workflow. If not specified, Atlantis will use its default workflow. |

Expand Down
4 changes: 2 additions & 2 deletions runatlantis.io/docs/deployment.md
Original file line number Diff line number Diff line change
Expand Up @@ -383,14 +383,14 @@ Once you're done, see [Next Steps](#next-steps).
Atlantis has an [official](https://hub.docker.com/r/runatlantis/atlantis/) Docker image: `runatlantis/atlantis`.
#### Customization
If you need to modify the Docker image that we provide, for instance to add a specific version of Terraform, you can do something like this:
If you need to modify the Docker image that we provide, for instance to add the terragrunt binary, you can do something like this:
1. Create a custom docker file
```dockerfile
FROM runatlantis/atlantis:{latest version}
# copy a terraform binary of the version you need
COPY terraform /usr/local/bin/terraform
COPY terragrunt /usr/local/bin/terrgrunt
```
1. Build your Docker image
Expand Down
18 changes: 13 additions & 5 deletions runatlantis.io/docs/requirements.md
Original file line number Diff line number Diff line change
Expand Up @@ -83,11 +83,19 @@ an `atlantis.yaml` file to tell it to use `-var-file={YOUR_FILE}`.
See [atlantis.yaml Use Cases](/guide/atlantis-yaml-use-cases.html#using-tfvars-files) for more details.

## Terraform Versions
By default, Atlantis will use the `terraform` executable that is in its path.
To use a specific version of Terraform:
1. Install the desired version of Terraform into the `$PATH` of where Atlantis is
running and name it `terraform{version}`, ex. `terraform0.8.8`.
2. Create an `atlantis.yaml` file for your repo and set the `terraform_version` key.
Atlantis supports all Terraform versions (including 0.12).

By default, Atlantis will use the version of `terraform` in its PATH,
however it's recommended to set the `--default-tf-version` flag to ensure
Atlantis always uses the same default version.

::: tip
Setting `--default-tf-version` is highly recommended if you're using the `runatlantis/atlantis` Docker image.
If you upgrade the Atlantis Docker image, it might contain a newer version of Terraform,
however if you're setting this flag, you won't be affected.
:::

To use different version of Terraform per repo/project, create an `atlantis.yaml` file and set the `terraform_version` key.
See [atlantis.yaml Use Cases](/guide/atlantis-yaml-use-cases.html#terraform-versions) for more details.

## Next Steps
Expand Down
11 changes: 7 additions & 4 deletions runatlantis.io/guide/atlantis-yaml-use-cases.md
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,11 @@ workflows:
- run: terragrunt apply -no-color $PLANFILE
```

::: warning
Atlantis will need to have the `terragrunt` binary in its PATH.
If you're using Docker you can build your own image, see [Customization](/docs/deployment.html#customization).
:::

## Running custom commands
Atlantis supports running custom commands. In this example, we want to run
a script after every `apply`:
Expand Down Expand Up @@ -255,7 +260,7 @@ isn't set, Atlantis will use the default plan workflow which is what we want in

## Terraform Versions
If you'd like to use a different version of Terraform than what is in Atlantis'
`PATH` then set the `terraform_version` key:
`PATH` or is set by the `--default-tf-version` flag, then set the `terraform_version` key:

```yaml
version: 2
Expand All @@ -264,9 +269,7 @@ projects:
terraform_version: 0.10.0
```

Atlantis will then execute all Terraform commands with `terraform0.10.0` instead
of `terraform`. This requires that the 0.10.0 binary is in Atlantis's `PATH` with the
name `terraform0.10.0`.
Atlantis will automatically download and use this version.

## Requiring Approvals For Production
In this example, we only want to require `apply` approvals for the `production` directory.
Expand Down
Loading

0 comments on commit 41603ed

Please sign in to comment.