Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Open
1 task done
craigmonson opened this issue Nov 1, 2023 · 2 comments
Labels

Comments

@craigmonson
Copy link

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

  • I agree to follow this project's Code of Conduct
@craigmonson craigmonson added the bug label Nov 1, 2023
@craigmonson craigmonson changed the title local_file creates file if filename content changes; does not update. local_file creates / overwrites file if content changes; does not follow ignore lifecycle. May 9, 2024
@craigmonson
Copy link
Author

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

@apparentlymart
Copy link
Contributor

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:

// Verify that the content of the destination file matches the content we
// expect. Otherwise, the file might have been modified externally, and we
// must reconcile.
outputContent, err := os.ReadFile(outputPath)
if err != nil {
resp.Diagnostics.AddError(
"Read local file error",
"An unexpected error occurred while reading the file\n\n+"+
fmt.Sprintf("Original Error: %s", err),
)
return
}
outputChecksum := sha1.Sum(outputContent)
if hex.EncodeToString(outputChecksum[:]) != state.ID.ValueString() {
resp.State.RemoveResource(ctx)
return
}

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants