tofu-controller
tofu-controller copied to clipboard
[Proposal] Showing plan details
Seeing plan details is an very important feature for the plan step. We need to have a mechanism to show plan details somewhere (via a notification? via a PR?)
To me showing the plan in PR comment makes sense. I think this should work nicely with the manual approval feature already in place.
I like the approach of Atlantis: https://www.runatlantis.io/
To implement an Atlantis-like workflow, we need to write back to a different branch, and one of the possible ways is to include the whole readable plan as an extended message of the Git commit.
GitHub for example, will extract the extended message as the body of the PR, when we create it. So the plan will be displayed nicely in the PR. That's a good thing.
Technically, an extended message of Git already allows a very large string to be there. But I'm not sure if it's a way to implement this feature, because the extended message will be inside the Git forever. (Good for the audit process, maybe?)
Interesting idea to use the commit message body; my sense is that this could quickly lead to bloated repositories / slow pulls, particularly with complex plans? Perhaps https://github.com/fluxcd/go-git-providers plus the ability to add the plan in a PR comment would cover our requirements here?
Yeah go-git-provider
solved the problem for us for the commit and push part.
The more difficult problem is an ability to show plan details in a PR, for GitHub, GitLab, etc. I agree that this is the best approach we would take. But I haven't seen a good solution yet. Maybe we would go check how Atlantis is dealing with PRs.
Something like this in the comment could work; using <details>
:
View plan
Terraform used the selected providers to generate the following execution
plan. Resource actions are indicated with the following symbols:
+ create
Terraform will perform the following actions:
# aws_s3_bucket.test will be created
+ resource "aws_s3_bucket" "test" {
+ acceleration_status = (known after apply)
+ acl = "private"
+ arn = (known after apply)
+ bucket = "test-bucket"
+ bucket_domain_name = (known after apply)
+ bucket_regional_domain_name = (known after apply)
+ force_destroy = false
+ hosted_zone_id = (known after apply)
+ id = (known after apply)
+ region = (known after apply)
+ request_payer = (known after apply)
+ tags = {
+ "Application" = "test"
+ "Environment" = "dev"
+ "Owner" = "flux"
}
+ tags_all = {
+ "Application" = "test"
+ "Environment" = "dev"
+ "Owner" = "flux"
}
+ website_domain = (known after apply)
+ website_endpoint = (known after apply)
+ versioning {
+ enabled = (known after apply)
+ mfa_delete = (known after apply)
}
}
Plan: 1 to add, 0 to change, 0 to destroy.
Changes to Outputs:
+ bucket = (known after apply)
+ bucket_arn = (known after apply)
─────────────────────────────────────────────────────────────────────────────
Note: You didn't use the -out option to save this plan, so Terraform can't
guarantee to take exactly these actions if you run "terraform apply" now.
Yes, agree.
I think an API something like the below would be required to implement this feature.
A couple of things to note:
- separate credentials would be required to access the git provider API
- if the PR branch exists should push the changes, otherwise creates the branch
- there's potentially enough logic here to warrant a dedicated controller and CR
apiVersion: infra.contrib.fluxcd.io/v1alpha1
kind: Terraform
metadata:
name: helloworld
namespace: flux-system
spec:
approvePlan: "auto"
path: ./
sourceRef:
kind: GitRepository
name: helloworld
namespace: flux-system
pullRequestAutomation:
provider: github
credentials:
type: oauth | token
secretRef: # note: this must be an oauth credential not a deploy/ssh key
name: provider-credential
git: # similar to flux image update automation
commit:
author:
name: flux-tf-controller
email: [email protected]
messageTemplate: |
An automated update from FluxBot
[ci skip]
signingKey:
secretRef:
name: git-pgp
pullRequest:
baseRef: main # branch to open pull request against
push:
prefix: tf-auto # prefix for PR branch name
deleteOnMerge: true
includePlanOutput: true # includes the terraform plan output in markdown
messageTemplate: message body string
Just started to look into this project as alternative to Atlantis. Is the currently anyway to read the plan?
@wilhelmi yep. One of our use cases is to make it on par with Atlantis.
We got an early release of tfctl
out. It's usable but yeah it's alpha quality.
tfctl plan show <tf-object>
would show the plan of the specified TF object. But UX still needs to be improved.
- the version of terraform binary on your local machine and the supported version must match
- if your location of the terraform binary is not /usr/bin/, you need to tell it like this:
❯ tfctl --terraform=$PWD/terraform plan show -n dev helloworld-tf
Changes to Outputs:
+ hello_world = "Hey ya, tfctl-rc!"
You can apply this plan to save these new output values to the Terraform
state, without changing any real infrastructure.
and yeah no color atm :-)
As of v0.12.0, we support storing human readable plan output in ConfigMaps, like this:
❯ kubectl get configmap/tfplan-default-helloworld-0-tf --template="{{.data.tfplan}}"
Changes to Outputs:
+ hello_world = "hey hey ya, tfctl-rc!"
You can apply this plan to save these new output values to the Terraform
state, without changing any real infrastructure.
@chanwit I upgraded our tf-controller to v0.12.0 but I do not see our plans in ConfigMaps, only in Secrets. Is there a change that I need to make to enable this?
Never mind, I think I found it...
storeReadablePlan: human
yes, @ericdalling
we'll iterate to improve this behavior over time. For now it's storeReadablePlan: none
by default because
-
storeReadablePlan: json
requires an extra secret to store it, while -
storeReadablePlan: human
requires an extra configmap to do so.
While you all work on getting comments on a PR, please support being able to reverse how a comment is posted to a PR. By example, if a plan's output would be so big as to need to be broken up into 3 commit messages, then Atlantis will post them in the following order: 3 - end of the plan output 2 - in the middle of the plan output 1 - beginning of the plan output
So that any person reading the commit needs to scroll to the start of the plan out put at #1, read done the page until it ends, then scroll back up past the start of #1 and find the start of #2 and then read down from the to the end of #2 and finally scroll to the start of #3 to get the rest of the output. This is hella crazy. For our Atlantis install, I checked out the code and reversed the order of PR commit messages to they are posted like: 1 - beginning of the plan output 2 - in the middle of the plan output 3 - end of the plan output
Even if some race condition allowed another commit message to show up in the middle, it would still read better than the default Atlantis handling.