upbound / provider-terraform

A Crossplane provider for Terraform
https://marketplace.upbound.io/providers/upbound/provider-terraform/
Apache License 2.0
150 stars 59 forks source link

An option to run terraform apply only once / on demand #210

Open lewyg opened 1 year ago

lewyg commented 1 year ago

What problem are you facing?

Hi, I am working with a terraform provider and it does terraform apply automatically during each reconciliation. Sometimes I use terraform code as some kind of workaround, for example like here to import resources by name: https://github.com/upbound/provider-terraform/tree/main/examples/importer and in this case, I am interested only in the first run of terraform apply, only to get the resource ID I want to import. After that, I don't need to run my code again in the reconciliation loop to not waste resources when unnecessary.

How could Official Terraform Provider help solve your problem?

Is it possible to have an option to run terraform only once or on demand?

Or maybe you have any other solution how to deal with this example? I was thinking of adding crossplane.io/paused: "true" annotation to the MR, but this needs to be added automatically after resource is Ready.

bobh66 commented 1 year ago

Hi @lewyg - terraform apply is only run on the initial create step and when it is determined that the resource is out of sync and needs to be reconciled. terraform plan is run on every reconciliation cycle to determine if the resource is out of sync., so it's definitely not optimal for one-shot Workspaces but it's not quite as bad as running apply on every cycle.

Now that Composition Functions are available I expect that a lot of the things that were being done with one-shot Workspaces can be replaced with Functions, so I think this issue might become less of a problem.

It might be possible to use the Granular Management Policies to do something like this if you specify just Create and leave out all of the other policies. I don't know if we have implemented support for GMP yet but we can run some tests.

ytsarev commented 1 year ago

I just had a discussion about it with @mergenci . It looks like managementPolicies: ["Create"] will also require "Observe" to succeed and enabling "Observe" will enable the consequent reconciliation loops. So without substantial provider and/or crossplane-runtime modifications, it seems to me that some Function that will set paused annotation on the Workspace if the MR outputs or some arbitrary field is already populated with the value, might be an option here

lewyg commented 1 year ago

@bobh66 thank you for the clarification, "plan" is definitely better than "apply", but still, as you said, not optimal for one-shot workspaces. I would like to learn more about how to use the composition function in this case. Do you have anything specific in mind with available functions, or to develop a new one for this case?

@ytsarev Yes, a new function sounds good to me

bobh66 commented 4 months ago

Another way to solve this using Composition Functions - if the Workspace output is only needed at create time, and the output is presumably stored in another resource input or the composite status, the Composition Function can have logic that creates the Workspace on the first pass through, copies the output when it is available, and then deletes the Workspace since it is no longer needed.

Sample logic:

if .observed.composite.resource.status.workspacedata == "": add Workspace to desired resources

if workspace-key in .observed.composed.resources and output is available: copy workspace output to desired.composite.resource.status.workspacedata

This would result in the Workspace resource being created and maintained as long as the output data has not been copied into the Composite status, and then once that happens the Workspace is no longer part of the desired resources so it will be deleted.