-
-
Notifications
You must be signed in to change notification settings - Fork 994
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
Upgrading to Terraform 0.12: separate configuration file for Terragrunt? #466
Comments
Hi @apparentlymart! First, a big thank you for checking in to make sure there's a migration path for Terragrunt! 🍺 Second, could you provide more details on what HCL and Terraform changes are coming? Terragrunt exists as a quick way to fill in gaps in Terraform, but as Terraform fills in those gaps itself, we're only too happy to reduce the need for Terragrunt, and hopefully have it go away entirely in the future. Once that's clear, we can think about whether changing the config format or moving to a different config file makes more sense. |
Hi @brikis98! We will have a comprehensive summary of all of the planned configuration changes coming soon. This is in progress but is waiting for the early preview release to be more complete before we finalize it so we can ensure we're describing its true scope/behavior. I wanted to get this conversation started early in case some adjustments need to be made either to Terraform itself (prior to the final release) or to Terragrunt. However, I can say that the focus of this release is on configuration changes rather than workflow changes, and so I believe all of Terragrunt's use-cases continue to make sense for the moment. Once the configuration language is in good shape we are planning to divert our attention to workflow for a while, at which point we'll definitely be interested in discussing if some or all of Terragrunt's features make sense for incorporation into Terraform. There'll be at least one more major release cycle before any changes that might reduce the scope of Terragrunt, and so I think it's worthwhile to ensure there's a viable path forward . If you'd rather pause this conversation until we have the more complete digest of changes ready, I'm happy to do so. I know it's hard to discuss a hypothetical situation. We're working on getting the new configuration language implementation integrated right now, and once we're at a point where we're back to feature-complete (bugs notwithstanding) I'll be able to run some real Terragrunt configurations through it and get a more concrete sense of how it behaves and whether some more surgical fixes might be possible. My main motivation with this proposal was to try to minimize the need for tight co-ordination between the Terraform release and any Terragrunt changes, and that was why I lent towards a separate file as a way to leave Terragrunt in control of its own destiny with regards to its configuration parsing, rather than having a single file that needs to be understandable both to Terraform's new parser (based on HCL2) and Terragrunt's existing parser (based on the original HCL implementation). |
Understood. Thx for providing the context.
The main concern I have with a separate file is that it will double the number of files necessary to use Terragrunt. One of the main complaints we have is that there are already too many files/folders to manage, so I'm a bit hesitant to make it worse. I'm going to take a minute to think out loud and throw out some ideas:
|
fwiw, I know I'd have no problem using a separate config file. I rather like the clarity of separating the two more cleanly. Personally, I don't use terraform.tfvars with terragrunt to also define terraform variables anyway, since I like maintaining the separation of concerns. Instead, I use a separate file And technically, a separate config file wouldn't necessarily double the number of files, since terraform.tfvars would no longer be required... How about a poll, maybe just using reactions on the issue, or perhaps publishing a poll through the newsletter? |
How so? You still need to configure Terragrunt, so that's one file. I suppose if your module needed no variables, then there wouldn't be a second, but that doesn't seem like a common use case. |
Pass the vars inside the terragrunt config, using |
Ah, I gotcha. That's something worth considering, I suppose. Terragrunt as it's own, completely separate format for (a) downloading Terraform configurations from somewhere, (b) configuring remote state for them, and (c) running Then we're decoupled entirely from Terraform's |
Thanks for sharing that extra context, @brikis98! I didn't fully understand the "remote Terraform configurations" workflow on my first pass, but I think I have a better handle on what's going on there now, and can see why a Terragrunt-specific file would -- without other changes -- lead to needing two separate files, where only one is needed today. The idea of including an extra map of variables inside the Terragrunt file sounds like a potential compromise, though we'd need to think through what the configuration migration tool should do here in order to leave the user with a valid Terragrunt configuration. That is, should it (when a Some additional background on the situation with interpolations in the The new "HCL2" implementation has interpolation built into the core language, rather than treating it as a separate processing pass (with the HIL library) on the strings produced by the HCL parser. A consequence of this is that interpolations are parsed during the initial parsing step, and so the AST for them (but not the value) is built much earlier than it would've been under the prior implementation. An unintended consequence of this is that the foo = "bar"
bar = "${ 1 + 2 }"
# HCL2 also allows "naked" expressions, without the interpolation markers
baz = 1 + 2 However, Terraform must still evaluate these at a stage where no variables or functions are available, so in practice the interpolations are limited to just basic computations on literal values. I think in practice there's little reason to use expressions in these files, and so users are unlikely to make use of this capability, but it's just a natural consequence of the design of the new parser. # this will produce a "variables are not allowed here" error message
baz = "${any.variable}" Because of this, the migration tool will need to conservatively escape any Another important consequence of the earlier handling of these is that Terraform will evaluate the given expression early in its initialization, when it produces the map of available input variables, since expression evaluation is how attribute values are read in HCL2. This means that a "function calls are not allowed here" message would be produced if given an unescaped Terragrunt configuration with the Terragrunt-specific function calls in it. |
I've been thinking about this a bit more and moving to a separate file, along with some changes to Terragrunts "ergonomics", may make sense. Here's a rough idea of what a typical "child" # Include all the settings from another Terragrunt config
include = "${find_in_parent_folders()}"
# The Terraform code to use. If not specified, it's assumed the code is in pwd.
source = "git::git@github.com:foo/modules.git//app?ref=v0.0.3"
# Variables to pass to the Terraform code
inputs = {
instance_type = "t2.micro"
instance_count = 5
# A new helper to get output variables from other Terragrunt / Terraform modules
# This implicitly creates dependencies that will be respected by the apply-all command
vpc_id = "${get_output("../vpc", "vpc_id")}"
# A new helper to get input variables from other Terragrunt HCL files to help keep things DRY
account_id = "${get_input("../account.hcl", "account_id")}"
}
# Keep your CLI flags DRY
extra_arguments = {
retry_lock = {
commands = ["${get_terraform_commands_that_need_locking()}"]
arguments = ["-lock-timeout=20m"]
}
}
# Keep your remote state config DRY
remote_state {
backend = "s3"
config {
bucket = "my-terraform-bucket"
region = "us-east-1"
key = "${path_relative_to_include()}/terraform.tfstate"
}
} The main changes are:
Note that this requires code changes in Terragrunt itself. We don't need all of these for it to be useful, but at the very least, what file it reads, and the structure of that file would need to be available immediately. The new helpers could come later. I'd love to hear feedback from any Terragrunt users. Also, @apparentlymart, would we be able to use the HCL2 parser to parse the new format above? Would it parse the "interpolations" and give us back a reasonable AST? |
@apparentlymart What is the rough timeline for HCL2? |
Seems reasonable to me! I suppose the new "hooks" feature would be specified something like
|
Ah, right, I left out |
That looks great to me, @brikis98! The HCL2 parser should be able to accept that format, though I'd make some small adjustments to some details for "idiomatic" HCL2: # No need to wrap a single expression in interpolation
include = find_in_parent_folders()
source = "git::git@github.com:foo/modules.git//app?ref=v0.0.3"
# Fixed elements (part of the structure of the format) tend to be defined as blocks rather than
# attributes, so no = sign here.
inputs {
instance_type = "t2.micro"
instance_count = 5
vpc_id = get_output("../vpc", "vpc_id")
account_id = get_input("../account.hcl", "account_id")
}
extra_arguments {
retry_lock {
commands = get_terraform_commands_that_need_locking()
arguments = ["-lock-timeout=20m"]
}
}
remote_state {
backend = "s3"
config {
bucket = "my-terraform-bucket"
region = "us-east-1"
key = "${path_relative_to_include()}/terraform.tfstate"
}
}
# Not exactly sure about these, but their structure suggests something I'd model
# with repeated nested blocks rather than single attributes.
hook_after "foo" {
commands = [ ... ]
execute = [ ... ]
}
hook_before "abc" {
commands = [ ... ]
execute = [ ... ]
} We're not promising compatibility for the HCL2 package APIs until some time after Terraform is released using it, in case we find design flaws during implementation in Terraform. With that said, we've already completed most of the work in Terraform that interacts with the HCL2 parsing APIs, and so in practice significant changes from here on out are not very likely. The structure here seems rigid enough that it could probably be processed using the higher-level gohcl package, which uses Go's We are currently in the process of updating Terraform Core to support HCL2's new type system, and so getting to the other end of that is the main blocker for us releasing the initial preview release, and there's still quite a lot of work to do here. How long it'll be until the final release after that depends on what sort of feedback we get from that preview release, but making time for the usual beta and release candidate process we do for any major release means that it'll be another couple months at least before we'll be final here. (The work is driving the schedule rather than the other way around, so unfortunately I can't be more precise at this stage.) |
Thanks for the feedback @apparentlymart. The new syntax looks really nice, especially for simple expressions/interpolations 👍 I think I'm on board with moving to this format. We're a bit overloaded now, so probably won't be able to dig into this for at least a few more weeks, but it sounds like Terraform moving to HCL2 is still a little ways down the road, so I think we have time. Two more questions for you:
|
The planned migration tool is primarily for updating The original HCL parser did, as you noted, have a few issues with the generation portion. For HCL2, given the increased complexity of handling both structural and expression parsing in both HCL native and JSON syntaxes, we decided not to build writing support into the main API. Instead, we have a separate package For the sake of the migration helper tool, we are planning to generate HCL2 syntax output in a more template-ish way, rather than generating it with the |
A question on the |
Good question. Currently, Terragrunt only allows you to
An interesting idea. I hadn't thought through what the syntax would be likely to reference |
Oh I was under the impression you could have more than a single layer of includes. Is that not what this test does? |
just as @lorengordon explained, i also separate the concerns by making sure any variable required by my modules are placed in separate files pulled by terragrunt using
Having all the variables in a terragrunt/terraform-logic-free separate file enables a clear separation between the modules code and the variables and eases their use by ops users on a day-to-day basis (read: I build modules and set up overall solutions <--> end-users fine-tunes the variables) So i won't use the new Reading the lines in this thread, i expect this won't be impacted much by the proposed changes so I have no concerns to use a separate terragrunt config file. Now, regarding the new helper I guess the separation of concerns postulate would dictate along these lines not to interfere with terraform files anymore, then it would be more a question of an additional feature to add to terraform's core, and the proposed terragrunt implementation should be seen as an interim solution until then. Thoughts? |
@ebarault I'd love to see some interpolation in |
as of now, i use terragrunt hooks to interpolate "remote" vars in I'm yet not quite sure how much terraform's next major release will break this. |
Has there been any progress on this? It sounds like TF 0.12 will be released within the next month or so. It would be great to have a migration path for continuing to use Terragrunt with it. |
No progress yet. |
Terraform 0.12 will go through an alpha release, at least one beta release, and at least one release candidate before final, which'll add up to at least a month and a half of release process, so please don't worry about it just surprisingly appearing one day! The terragrunt-specific configuration migration mechanism we discussed in this thread is unlikely to make it in before the alpha, because the focus of the alpha is in getting early feedback from maintainers of re-usable modules we don't have access to (because they are in private repositories), but the Terraform side of this is definitely still on our radar and likely to go in during a beta, assuming what we discussed above still seems approximately right (we can make small tweaks before final, of course). |
Looks like there is a new, and pretty stable beta release of tf 0.12. Probably at a good place to start testing whether any changes might be needed to terragrunt itself. |
While we are here, would it be possible to allow to specify path to terraform binary in |
Alright, #731 is merged. Please give https://github.com/gruntwork-io/terragrunt/releases/tag/v0.19.0 a try (the new binaries should show up in a few minutes)! |
Thanks to make terragrunt ready for terraform 0.12 But I got error:
Update 1Seems the README and migration guide have been updated: https://github.com/gruntwork-io/terragrunt#quick-start We need prepare a new Update 2A real sample to deploy terraform 0.12 with terragrunt 0.19 https://github.com/gruntwork-io/terragrunt-infrastructure-live-example Now it makes sense for me. Really appreciated. |
@ozbillwang Glad to hear you got it sorted! |
And I can confirm now, I run on a complex terraform stack with 7 terraform modules, the part to do |
@brikis98 While declaring an empty remote state in a way:
I'm getting:
Content of directory
Content of root
Edit: So apparently it tries to parse terragrunt.hcl too, that's why there's an error. After commenting out terraform block from terragrunt.hcl it works. |
You still have a |
The only file that's called
|
And does it have a |
No. For some weird reason the error is related to |
That error is from Terraform itself, not Terragrunt... Are you passing |
Nevermind, I had leftover environment variables set... Excuse my stupidity. |
No prob! Thx for following up. |
Hi @brikis98, I cant find any guide on below link... please help |
@shivamheller Try https://github.com/gruntwork-io/terragrunt/blob/v0.19.0/_docs/migration_guides/upgrading_to_terragrunt_0.19.x.md The docs have been revamped on |
Hi! I'm one of the engineers at HashiCorp who works on Terraform Core.
As you might be aware, we've been working for some time now on various improvements to the Terraform configuration language, to address a number of usability problems that have been reported over the years. The new changes are broadly compatible with existing configurations, and particularly those using the common idioms reflected in the Terraform documentation.
Unfortunately resolving some of these problems required tightening up some things that were previously rather loose. Current and previous versions of Terraform ignore certain things that are considered invalid, often producing surprising results, and so to improve usability the new implementation has some more error checking in order to catch mistakes and produce error messages that are hopefully more actionable.
We're planning to include a migration helper tool in the next release in order to help detect and fix some of these rough edges. The details of what this tool does will be largely informed by real-world usage, and so we're planning to release an early preview of the new implementation as soon as it is in a usable state in the hope that we can gather as many examples as possible of patterns in the wild that the migration helper tool should be looking for.
With all of that context in mind, we know that there are lots of users wrapping Terraform with Terragrunt, and so we want to make sure there's a good upgrade path. I'm opening this issue to discuss a specific problem I've noticed, but I'd like to discuss any other potential hurdles too, in whatever forum makes sense.
Terragrunt currently uses an extension of the
terraform.tfvars
file as its own configuration file, relying on the fact that Terraform itself ignores definitions in that file that are not defined as variables, and then using a special variable nameterragrunt
whose value is not, by Terraform's rules, valid: it includes mixed-typed nested structures, has nested blocks, etc.The new implementation has a few differences that will cause friction here if we proceed naively:
${
are interpreted in all contexts, with the difference now being whether variables and functions are available, rather than whether interpolations are possible at all.Looking at the "live infrastructure" example, a naive syntax-level pass of migration would produce the following rewritten version:
Since Terragrunt is using the HCL parser directly to process its configuration file today, it has the freedom to interpret the tree of HCL AST objects inside here as desired, and so I expect there are expectations here that are different than how Terraform generally deals with HCL structures it has no specific schema for. Also, due to the fact that interpolation syntax is now accepted in all quoted strings (variables and functions are just not available in some contexts), the naive migration tool will escape the
${
sequences under the assumption that the user intended them to be treated literally, since that was Terraform's own interpretation of a.tfvars
file before this change.Therefore it feels to me like the most practical path to take here is for our migration tool to have a special case for a variable called
terragrunt
(possibly activated only if there is novariable "terragrunt"
block in configuration) which can then have some light understanding of Terragrunt's configuration structure and make some allowances for it so that we can avoid unintentional breakage of the Terragrunt configuration.Terragrunt is currently relying on syntax features that are considered invalid in the new implementation, so leaving the configuration untouched by the migration tool would inevitably lead to syntax errors during parsing.
In order to avoid conflicts between Terraform's and Terragrunt's interpretation of the same file, I'd like to propose having Terragrunt look for a Terragrunt-specific configuration filename (e.g.
terragrunt.conf
) in preference toterraform.tfvars
, and then Terraform would entirely ignore this file and leave Terragrunt's own parser to deal with it. Terragrunt could continue to use the original implementation of HCL, avoiding the need to deal with any of the new processing rules from the new implementation.If we were to go down this path, we could build the configuration migration tool so that its special case for the
terragrunt
variable name is to migrate the contents out into aterragrunt.conf
file that retains the block structure and original-HCL syntax that Terragrunt is expecting, and then deletes this value from theterraform.tfvars
file altogether so that Terraform itself won't try to parse it.I understand that this is a pretty drastic shift in the design and usage of Terragrunt, so I wanted to start talking about this early so we have some time to think through the implications and any other alternative approaches. I hope that together we can find a reasonable path forward!
The text was updated successfully, but these errors were encountered: