Skip to content

Commit

Permalink
test: Added docs and integration test
Browse files Browse the repository at this point in the history
Signed-off-by: Steven Gettys <steven.gettys@gmail.com>
  • Loading branch information
sgettys committed Mar 26, 2024
1 parent 0d6894c commit 66fade1
Show file tree
Hide file tree
Showing 8 changed files with 88 additions and 37 deletions.
66 changes: 43 additions & 23 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,18 +37,32 @@ mixins:
workingDir: myinfra
initFile: providers.tf
```
Or
```yaml
mixins:
- terraform:
clientVersion: 1.0.3
workingDirs:
- infra1
- infra2
initFile: providers.tf
```

### clientVersion
The Terraform client version can be specified via the `clientVersion` configuration when declaring this mixin.

### workingDir
The `workingDir` configuration setting is the relative path to your terraform files. Defaults to "terraform".

### workingDirs
The `workingDirs` configuraiton setting is used when multiple terraform plans are part of a single bundle. When the `workingDirs` setting is specified then the `workingDir` setting is ignored.

### initFile
Terraform providers are installed into the bundle during porter build.
We recommend that you put your provider declarations into a single file, e.g. "terraform/providers.tf".
Then use `initFile` to specify the relative path to this file within workingDir.
This will dramatically improve Docker image layer caching and performance when building, publishing and installing the bundle.
If `workingDirs` is specified instead of `workingDir` then the `initFile` must be the same in all of the terraform plans for the bundle.
> Note: this approach isn't suitable when using terraform modules as those need to be "initilized" as well but aren't specified in the `initFile`. You shouldn't specifiy an `initFile` in this situation.
### User Agent Opt Out
Expand Down Expand Up @@ -77,28 +91,7 @@ You can add your own custom strings to the user agent string by editing your [te

### Let Porter do the heavy lifting

The simplest way to use this mixin with Porter is to let Porter track the Terraform [state](https://www.terraform.io/docs/state/index.html) as actions are executed. This can be done via a parameter of type `file` that has a source of a corresponding output (of the same `file` type). Each time the bundle is executed, the output will capture the updated state file and inject it into the next action via its parameter correlate.

Here is an example setup that works with Porter v0.38:

```yaml
parameters:
- name: tfstate
type: file
# This designates the path within the installer to place the parameter value
path: /cnab/app/terraform/terraform.tfstate
# Here we tell Porter that the value for this parameter should come from the 'tfstate' output
source:
output: tfstate

outputs:
- name: tfstate
type: file
# This designates the path within the installer to read the output from
path: /cnab/app/terraform/terraform.tfstate
```

If you are working with the Porter v1 prerelease, use the new state section:
The simplest way to use this mixin with Porter is to let Porter track the Terraform [state](https://www.terraform.io/docs/state/index.html) as actions are executed. This can be done via the state section:

```yaml
state:
Expand All @@ -108,10 +101,30 @@ state:
path: terraform/terraform.tfvars.json
```

The [TabbyCats Tracker bundle](https://github.com/carolynvs/tabbycat-demo) is a good example of how to use the terraform mixin with the Porter v1 prerelease.
The [TabbyCats Tracker bundle](https://github.com/carolynvs/tabbycat-demo) is a good example of how to use the terraform mixin with Porter v1.

The specified path inside the installer (`/cnab/app/terraform/terraform.tfstate`) should be where Terraform will be looking to read/write its state. For a full example bundle using this approach, see the [basic-tf-example](examples/basic-tf-example).

Any arbitrary file can be added to the state including any files created by terraform during install or upgrade.

When working with multiple different terraform plans in the same bundle make sure to specify the path to the corresponding plans state:

```yaml
state:
- name: infra1-tfstate
path: infra1/terraform.tfstate
- name: infra1-tfvars
path: infra1/terraform.tfvars.json
- name: infra1-file
path: infra1/infra1-file
- name: infra2-tfstate
path: infra2/terraform.tfstate
- name: infra2-tfvars
path: infra2/terraform.tfvars.json
- name: infra2-file
path: infra2/infra2-file
```

### Remote Backends

Alternatively, state can be managed by a remote backend. When doing so, each action step needs to supply the remote backend config via `backendConfig`. In the step examples below, the configuration has key/value pairs according to the [Azurerm](https://www.terraform.io/docs/backends/types/azurerm.html) backend.
Expand Down Expand Up @@ -303,3 +316,10 @@ install:

See the Porter [Outputs documentation](https://porter.sh/wiring/#outputs) on how to wire up
outputs for use in a bundle.


## Multiple Terraform Plans In A Single Bundle

Multiple terraform plans can be specified for a single bundle. When using the mixin with this configuration then every step **MUST** include a `workingDir` configuration setting so that porter can resolve the corresponding plan for that step at runtime.

The `workingDir` and `workingDirs` configuration settings are mutally exclusive. If the `workingDirs` configuration setting is provided then anything set for `workingDir` will be ignored at bundle build time.
2 changes: 1 addition & 1 deletion examples/multiple-mixin-configs/infra1/main.tf
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
resource "local_file" "foo" {
content = var.infra1_var
filename = "${path.module}/infra1"
filename = "${path.module}/infra1-file"
}
2 changes: 1 addition & 1 deletion examples/multiple-mixin-configs/infra2/main.tf
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
resource "local_file" "foo" {
content = var.infra2_var
filename = "${path.module}/infra1"
filename = "${path.module}/infra2-file"
}
14 changes: 14 additions & 0 deletions examples/multiple-mixin-configs/porter.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -78,3 +78,17 @@ outputs:
applyTo:
- 'install'
- 'upgrade'

state:
- name: infra1-tfstate
path: infra1/terraform.tfstate
- name: infra1-tfvars
path: infra1/terraform.tfvars.json
- name: infra1-file
path: infra1/infra1-file
- name: infra2-tfstate
path: infra2/terraform.tfstate
- name: infra2-tfvars
path: infra2/terraform.tfvars.json
- name: infra2-file
path: infra2/infra2-file
3 changes: 1 addition & 2 deletions pkg/terraform/build.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,14 @@ RUN cd $BUNDLE_DIR/{{.}} && \
terraform init -backend=false && \
rm -fr .terraform/providers && \
terraform providers mirror /usr/local/share/terraform/plugins
{{end}}
{{else}}
COPY {{.WorkingDir}}/{{.InitFile}} $BUNDLE_DIR/{{.WorkingDir}}/
RUN cd $BUNDLE_DIR/{{.WorkingDir}} && \
terraform init -backend=false && \
rm -fr .terraform/providers && \
terraform providers mirror /usr/local/share/terraform/plugins
{{end}}
{{end}}
`

// BuildInput represents stdin passed to the mixin for the build command.
Expand Down Expand Up @@ -81,7 +81,6 @@ func (m *Mixin) Build(ctx context.Context) error {
fmt.Fprintf(m.Err, "DEBUG: List of working dirs was provided, using :\n%v\n", input.Config.WorkingDirs)
}
}

tmpl, err := template.New("Dockerfile").Parse(dockerfileLines)
if err != nil {
return errors.Wrapf(err, "error parsing terraform mixin Dockerfile template")
Expand Down
2 changes: 0 additions & 2 deletions pkg/terraform/install.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,6 @@ const defaultTerraformVarsFilename = "terraform.tfvars.json"

// Install runs a terraform apply
func (m *Mixin) Install(ctx context.Context) error {
fmt.Fprintf(m.Err, "\n\nIN INSTALL\n\n")
fmt.Printf("\n\nIN INSTALL\n\n")
action, err := m.loadAction(ctx)
if err != nil {
return err
Expand Down
9 changes: 1 addition & 8 deletions pkg/terraform/terraform.go
Original file line number Diff line number Diff line change
Expand Up @@ -142,18 +142,12 @@ func (m *Mixin) commandPreRun(ctx context.Context, step *Step) error {
if step.LogLevel != "" {
os.Setenv("TF_LOG", step.LogLevel)
}
fmt.Fprintf(m.Err, "\n\nSTEP:\n\n%+v\n\n", step)
fmt.Fprintf(m.Err, "\n\nCONFIG:\n\n%+v\n\n", m.config)
// Determine the working directory for this step.
// If the config has WorkingDirs set then validate that the step has WorkingDir set to one of the values
// in the configs "WorkingDirs"
// TODO: (gettys) this should validate against the mixin config configuration settings
if step.WorkingDir != "" {
stepDir := step.GetWorkingDir()
fmt.Fprintf(m.Err, "\n\nCDing STEP WORKINGDIR to %v\n\n", stepDir)
// Validate that the step working dir is one of the values in the mixin config
m.Chdir(stepDir)
} else {
fmt.Fprintf(m.Err, "\n\nCDing CONFIG to %v\n\n", m.config.WorkingDir)
m.Chdir(m.config.WorkingDir)
}
if m.DebugMode {
Expand All @@ -162,7 +156,6 @@ func (m *Mixin) commandPreRun(ctx context.Context, step *Step) error {

// Initialize Terraform
fmt.Println("Initializing Terraform...")
fmt.Println("HELLO")
err := m.Init(ctx, step.BackendConfig)
if err != nil {
return fmt.Errorf("could not init terraform, %s", err)
Expand Down
27 changes: 27 additions & 0 deletions scripts/test/test-cli.sh
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ function verify-output() {
}


##### Basic Example Test #####
# Copy terraform assets
cp -r ${REPO_DIR}/examples/basic-tf-example/terraform .

Expand Down Expand Up @@ -73,3 +74,29 @@ verify-output "json_encoded_html_string_var" '?new#conn&string$characters~!'
verify-output "complex_object_var" '{"nested_object":{"internal_value":"https://new.connection.com?test&test=$hello"},"top_value":"https://my.updated.service?test=$id<>"}'

${PORTER_HOME}/porter uninstall --debug

rm -rf *

##### Multiple Working Dirs Test #####
# Copy terraform assets
cp -r ${REPO_DIR}/examples/multiple-mixin-configs/ .

${PORTER_HOME}/porter build
${PORTER_HOME}/porter install --verbosity=debug \
--param infra1_var="foo" \
--param infra2_var="bar"

verify-output "infra1_output" "foo"
verify-output "infra2_output" "bar"

${PORTER_HOME}/porter upgrade --verbosity=debug \
--param infra1_var="upgradeFoo" \
--param infra2_var="upgradeBar"

verify-output "infra1_output" "upgradeFoo"
verify-output "infra2_output" "upgradeBar"

${PORTER_HOME}/porter uninstall --verbosity=debug



0 comments on commit 66fade1

Please sign in to comment.