terraform-provider-local
terraform-provider-local copied to clipboard
local_file creates / overwrites file if content changes; does not follow `ignore` lifecycle.
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
-
terraform apply
- `echo "foo" >> test.txt
-
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
Updated title cause it was quite awful... sorry bout that.
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 makesos.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.