-
-
Notifications
You must be signed in to change notification settings - Fork 997
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
Use signals
not only for error-handling
#3618
Comments
Hey @norman-zon , Folks typically use Is there a reason you wouldn't just use |
Yes, there is a reason. I use state and plan encryption, so I can't process the plan-file with other tools than |
Sorry, I haven't played with state encryption yet, so I might be missing some important context here. Are you not able to have tofu emit the JSON representation of your plan like this? # main.tf
resource "local_file" "example" {
filename = "example.txt"
content = "Hello, World!"
}
output "example" {
value = local_file.example.content
}
# terragrunt.hcl
# Intentionally empty. $ terragrunt plan -out plan.out
...
$ terragrunt show -json plan.out | jq
{
"format_version": "1.2",
"terraform_version": "1.8.5",
"planned_values": {
"outputs": {
"example": {
"sensitive": false,
"type": "string",
"value": "Hello, World!"
}
},
"root_module": {
"resources": [
{
"address": "local_file.example",
"mode": "managed",
"type": "local_file",
"name": "example",
"provider_name": "registry.opentofu.org/hashicorp/local",
"schema_version": 0,
"values": {
"content": "Hello, World!",
"content_base64": null,
"directory_permission": "0777",
"file_permission": "0777",
"filename": "example.txt",
"sensitive_content": null,
"source": null
},
"sensitive_values": {
"sensitive_content": true
}
}
]
}
},
"resource_changes": [
{
"address": "local_file.example",
"mode": "managed",
"type": "local_file",
"name": "example",
"provider_name": "registry.opentofu.org/hashicorp/local",
"change": {
"actions": [
"create"
],
"before": null,
"after": {
"content": "Hello, World!",
"content_base64": null,
"directory_permission": "0777",
"file_permission": "0777",
"filename": "example.txt",
"sensitive_content": null,
"source": null
},
"after_unknown": {
"content_base64sha256": true,
"content_base64sha512": true,
"content_md5": true,
"content_sha1": true,
"content_sha256": true,
"content_sha512": true,
"id": true
},
"before_sensitive": false,
"after_sensitive": {
"sensitive_content": true
}
}
}
],
"output_changes": {
"example": {
"actions": [
"create"
],
"before": null,
"after": "Hello, World!",
"after_unknown": false,
"before_sensitive": false,
"after_sensitive": false
}
},
"prior_state": {
"format_version": "1.0",
"terraform_version": "1.8.5",
"values": {
"outputs": {
"example": {
"sensitive": false,
"value": "Hello, World!",
"type": "string"
}
},
"root_module": {}
}
},
"configuration": {
"provider_config": {
"local": {
"name": "local",
"full_name": "registry.opentofu.org/hashicorp/local"
}
},
"root_module": {
"outputs": {
"example": {
"expression": {
"references": [
"local_file.example.content",
"local_file.example"
]
}
}
},
"resources": [
{
"address": "local_file.example",
"mode": "managed",
"type": "local_file",
"name": "example",
"provider_config_key": "local",
"expressions": {
"content": {
"constant_value": "Hello, World!"
},
"filename": {
"constant_value": "example.txt"
}
},
"schema_version": 0
}
]
}
},
"relevant_attributes": [
{
"resource": "local_file.example",
"attribute": [
"content"
]
}
],
"timestamp": "2024-12-04T14:30:48Z",
"errored": false
} I don't think anything about state encryption should prevent you from having tofu write out the plan in json format like that for processing with another tool. The convenient way to have this always happen with Terragrunt would be to set this up: # terragrunt.hcl
terraform{
extra_arguments "write_to_out" {
commands = ["plan"]
arguments = ["-out=plan.out"]
}
after_hook "show_plan_as_json" {
commands = ["plan"]
execute = ["bash", "-c", "$TG_CTX_TF_PATH show -json plan.out > plan.json"]
}
after_hook "detect_actions" {
commands = ["plan"]
# If you only care about one kind of action:
# execute = ["bash", "-c", "jq '.resource_changes[] | select(.change.actions[] | contains(\"create\")) | .address' < plan.json > creates.txt"]
# If you care about all actions:
execute = ["bash", "-c", "jq '.resource_changes[] | select(.change.actions[]) | { action: .change.actions[0], address: .address }' plan.json > changes.json"]
}
} In my testing, it results in this {
"action": "create",
"address": "local_file.example"
} I wrote this up quickly and tested minimally. You might have to do more tweaking to get it to do what you want. |
Yes, that would work, but my intention of using state encryption is to not have any unencrypted state in my CI logs at all. I have to ponder wether directly piping into Thanks a lot for the jq-query by the way! This is really handy. |
Hey @norman-zon , what do you think about this enhancement? Should we still pursue it? One thing I didn't see described is how it would integrate with the existing signals system in the errors block. Would that be deprecated in favor of a dedicated signals block that also hooks into errors? |
I think it would be a helpful feature for CI in general, despite my first idea of an use case might better be handled like you described above. And yes, I would see it as a separate system, that can also hook into errors. |
In that case, I would like to see the proposal fleshed out a bit more with an RFC, as it would be a significant new feature in Terragrunt. Considerations like the following would be important there:
|
Title: Enhance Terragrunt's Summary: Motivation: Detailed Design:
Example of Output Structure in JSON with Capture Groups: When a {
"signals": {
"plan_changes": true
},
"matches": [
{
"pattern": "^Plan:.*\\b([1-9][0-9]*)\\b to add\\b",
"matched_text": "Plan: 2 to add, 0 to change, 0 to destroy",
"capture_groups": {
"1": "2"
}
},
{
"pattern": "^Plan:.*\\b([1-9][0-9]*)\\b to change\\b",
"matched_text": null,
"capture_groups": {}
},
{
"pattern": "^Plan:.*\\b([1-9][0-9]*)\\b to destroy\\b",
"matched_text": null,
"capture_groups": {}
}
],
"message": "Plan indicates infrastructure changes."
} Implementation Steps:
Backward Compatibility: Drawbacks:
Alternatives:
Unresolved Questions
|
Describe the enhancement
I really like the idea of the new
error
block. Especially thesignals
attribute for usage in automated CI environments.My request is to expand the usage of
signals
to more than just error handling, but to be able to handle any context.One use case that comes immediately to mind is to have a signal for the
plan
result, to the CI can react differently on 0-diff, changes and/or deletions.I would imagine a usage like this:
Additional context
I cannot tell how much of an performance impact it would be to regex-match the whole stream instead of only the error-stream.
Alternatively, for this exact use-case the plan output could be written to a JSON file directly. But expanding the usage of signals is much more flexible.
RFC Not Needed
The text was updated successfully, but these errors were encountered: