hashicorp / terraform

Terraform enables you to safely and predictably create, change, and improve infrastructure. It is a source-available tool that codifies APIs into declarative configuration files that can be shared amongst team members, treated as code, edited, reviewed, and versioned.
https://www.terraform.io/
Other
42.34k stars 9.49k forks source link

Feature Request: Add flag for state files auto update. #18445

Open hdost opened 6 years ago

hdost commented 6 years ago

Problem When a person uses a new version of Terraform it updates the state files by default.

Why is this a problem? The biggest reason for this it is currently very easy to overwrite your state and not have a backup, or even if you do have it there's not a great way to rollback. Having experienced this recently, if a single person on a team of people updates their version of Terraform including the person just starting with Terraform then it can cause problems with the files be overwritten with the new version.

Suggestion The addition of a flag --update-state=true would act as the current default behavior does today. Without the flag or with --update-state=false when using a newer version of terraform it would either warn that state cannot be updated OR the command returns an error code. Either way the state file should not be updated.

Alternatively, the old state should be preserved by making a backup copy of the file name with the version noted in the file name, and then the new state file retains the standard name and it performs the upgrade as expected. Along with that it might be worth adding an option --backup-state which defaults to true and could be set to --backup-state=false.

It might be a good idea that the same applies to Terraform Providers.

mildwonkey commented 6 years ago

Hi @hdost - I'm sorry you've run across this, and thanks for the feature request.

One way you can avoid this issue is specifying the required version of terraform in your configuration as described here:

terraform {
  required_version = "0.11.8 "
}

Provider versions can be specified as well.

hdost commented 6 years ago

We have actually done precisely that. I now need to verify that doing so prevents the state files from being modified.

apparentlymart commented 6 years ago

Hi @hdost,

As @mildwonkey described, we intend that required_version mechanism as the way for a team to "agree" on which version of Terraform they are all currently using and prevent the issue you're describing by requiring a configuration change (which would, in most organizations, go through code review) to opt in to an upgrade.

Since terraform apply must always update state in order to take any actions at all, the first option you proposed here would effectively disable terraform apply altogether, which I assume isn't really what you were looking for. terraform plan (with no arguments) is always safe to run with a newer version of Terraform in order to test what change an upgraded version of Terraform might make (e.g. as part of testing a change to that terraform_version setting) and will never update the state.

The usual workflow for a Terraform upgrade, then, is:

Some teams handle this in a more formal way by running Terraform in a central automation system where that system controls which version of Terraform is used, which is one way to make this a technology solution rather than a social (via version control) solution, but that's not required.

If more testing is desired, Terraform's workspaces feature is intended as a way to create a temporary "copy" of your infrastructure that can be used to test changes, at the expense of some extra steps. Workspaces are usually correlated roughly with version control branches, so the above process would begin with the extra steps of creating a new branch and new workspace, applying the branch configuration on the old version of Terraform, and then doing the above steps in the branch. At the end, there are extra steps of destroying the temporary workspace along with its associated branch and then merging the change down to the main branch before using it "for real". In practice this is often overkill for a Terraform Core upgrade, but is an option.

The above approaches can also be used with the provider plugin version constraint mechanisms in order to coordinate provider upgrades.


On the subject of state backups: Terraform currently delegates that problem for each backend to solve, though indeed some of them do this better than others.

At this time some backends do not have a facility for historical backups at all. In the short term, it's unfortunately up to users to select one that does if that is important to them. Over time, I expect that we will ensure that there's a plausible backup story for all backends and consider gradually phasing out those few where such a thing would be technically impossible.

Rolling back to an older state is generally a last resort, since it will cause Terraform to lose track of any objects that were created since that state snapshot was created, but it is certainly useful to do this in some cases.


I hope that helps. If I've missed the point of what you're trying to achieve here, please do let me know!

hdost commented 6 years ago

So we are already using a pipeline for application of the terraform templates. Additionally we have not seen issues since we pinned so it may be a moot point. As background we are using azure as the backend.

It may be too heavy handed to have both an argument as well as version pinning.

tcarrio commented 6 years ago

@hdost I'm curious whether the argument could be used for version pinning?

The behavior for the --update-state=false flag being that the current version of Terraform will be pinned to the configuration.

Effectively a short-handed manner of applying the suggested workflow from the CLI.

hdost commented 6 years ago

I like that idea.

@apparentlymart does that make sense given what's already been discussed?

hdost commented 5 years ago

Alright so after working with terraform a bit more. I have what think might be more pragmatic would be to do would be add a warning if there is not a version specified for the required_version. To encourage better practices.

@apparentlymart @mildwonkey What are your thoughts?