terraform-provider-local icon indicating copy to clipboard operation
terraform-provider-local copied to clipboard

local_file creates / overwrites file if content changes; does not follow `ignore` lifecycle.

Open craigmonson opened this issue 1 year ago • 2 comments

Terraform CLI and Provider Versions

Terraform v1.6.2 on darwin_amd64

  • provider registry.terraform.io/hashicorp/local v2.4.0

Terraform Configuration

resource "local_file" "test" {
  filename = "test.txt"
  content  = "This is my test content"

  lifecycle {
    ignore_changes = all
  }
}

Expected Behavior

When the file is not in state, it correctly creates the file. If I change the content in test.txt, because of ignore_changes, it should not update the contents of the file.

Actual Behavior

If I change the content of test.txt after it's been created, it will simply overwrite the file doing a create. This ignores the lifecycle rule.

Steps to Reproduce

  1. terraform apply
  2. `echo "foo" >> test.txt
  3. terraform plan

How much impact is this issue causing?

High

Logs

https://gist.github.com/craigmonson/1a54c16e50e85e2fe78cafb20891dadf

Additional Information

The context: I've created a boilerplate module that can generate files for me. A prime example of this would be outputting a README.md file that's got a simple: # project name at the top. Once I've created the file the first time, I should be able to go in and fill in the readme, without it being overwritten by using ignore_changes.

Code of Conduct

  • [X] I agree to follow this project's Code of Conduct

craigmonson avatar Nov 01 '23 14:11 craigmonson

Updated title cause it was quite awful... sorry bout that.

craigmonson avatar May 09 '24 20:05 craigmonson

This resource type has an interesting rule in its "read" implementation where it checks if the file contents have changed and pretends that the file has been deleted if so:

https://github.com/hashicorp/terraform-provider-local/blob/f55a8422b5718ace86e68c4e90e0df3ae45ebce1/internal/provider/resource_local_file.go#L255-L272

I have a faint memory that this was working around some quirk of a very old version of Terraform that was current when originally writing this provider, but I don't think this approach should be needed anymore. With more modern Terraform we could take the following approach instead:

  • Read just updates the file contents and associated checksums in the state. If reading the file returns an error that makes os.IsNotExist return true then only in this case would we indicate that the object has been deleted outside of Terraform.
  • During planning, use a plan modifier to take a checksum of the desired content and set all of the checksum attributes in the planned new value to match the new content, or set them all to unknown if the desired content isn't known.

Terraform Core should then notice that the attributes in the plan have different values than the corresponding attributes in the desired state (updated by the read step) and so propose to update the file in-place.

I don't think it's necessary to delete the file first, but if we identify a reason why we need to do that then the existing plan modifier that marks changes to the content attribute as requiring replacement could be preserved and would then cause Terraform to report that it's going to replace the file rather than updating it in-place.

apparentlymart avatar May 20 '24 20:05 apparentlymart