tofu-controller icon indicating copy to clipboard operation
tofu-controller copied to clipboard

[Proposal] Showing plan details

Open chanwit opened this issue 2 years ago • 14 comments

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?)

chanwit avatar Jan 13 '22 04:01 chanwit

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/

phoban01 avatar Jan 14 '22 10:01 phoban01

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?)

chanwit avatar Jan 14 '22 10:01 chanwit

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?

phoban01 avatar Jan 17 '22 11:01 phoban01

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.

chanwit avatar Jan 17 '22 11:01 chanwit

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.

phoban01 avatar Jan 17 '22 12:01 phoban01

Yes, agree.

chanwit avatar Jan 17 '22 12:01 chanwit

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

phoban01 avatar Jan 31 '22 11:01 phoban01

Just started to look into this project as alternative to Atlantis. Is the currently anyway to read the plan?

wilhelmi avatar May 10 '22 21:05 wilhelmi

@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 :-)

chanwit avatar May 11 '22 04:05 chanwit

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 avatar Sep 07 '22 16:09 chanwit

@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?

ericdalling avatar Sep 07 '22 19:09 ericdalling

Never mind, I think I found it... storeReadablePlan: human

ericdalling avatar Sep 07 '22 19:09 ericdalling

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.

chanwit avatar Sep 07 '22 23:09 chanwit

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.

wpbeckwith avatar Sep 08 '22 02:09 wpbeckwith