-
-
Notifications
You must be signed in to change notification settings - Fork 998
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 ${var.} in terragrunt config #132
Comments
Sharing variables between Terragrunt and Terraform has come up before, but to be honest, I'm not sure we know the best way to handle it. The problem is that Terraform can load variables from many places:
We could certainly read and parse all the variables in the If someone has ideas on a clean solution to this, I'm open to ideas. |
I think I'm more interested in variables in the terragrunt file being available to terraform. The workaround is break them out and specify a couple
This pretty strongly implies that non-terragrunt variables are passed to terraform, which doesn't seem to be the case in |
Are you still putting your configs in |
I'm putting variables in terraform.tfvars. You're correct that variables in
that file are being picked up, but *not* variables in my terraform.tfvars
file that is getting `include`-ed. If this isn't expected to be the case
I'll send over something that will reproduce it later this weekend.
On Feb 18, 2017 9:10 AM, "Yevgeniy Brikman" <notifications@github.com> wrote:
I think I'm more interested in variables in the terragrunt file being
available to terraform.
Are you still putting your configs in .terragrunt or are you using a
terraform.tfvars file? If it's the latter, then Terraform *will* read
variables from that file. If you are using a .tfvars file with some other
name (e.g. foo.tfvars), then you have to pass that to Terraform explicitly
using the -var-file argument, as documented here
<https://github.com/gruntwork-io/terragrunt#config-file-search-paths>.
—
You are receiving this because you commented.
Reply to this email directly, view it on GitHub
<#132 (comment)>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/ABnTd9jVxO15VfT5OcRRs9_ZZmo3tXrGks5rdvu8gaJpZM4MD8T0>
.
|
Ah, I see what you're saying. Yes, I'd welcome a PR to clarify the docs around this. |
Great, will do! Is the expected workaround to use a var file passed on the
command line? This works but is a bit awkward due to the precedence rules:
those will override variables in the child terraform.tfvars.
Anyway, great tool and thanks for writing and sharing it!
…On Feb 18, 2017 9:22 AM, "Yevgeniy Brikman" ***@***.***> wrote:
Ah, I see what you're saying. Yes, include just pulls in the terragrunt =
{ ... } block from the parent file, so it only affects Terragrunt and has
no effect on Terraform at all. That's definitely confusing.
I'd welcome a PR to clarify the docs around this.
—
You are receiving this because you commented.
Reply to this email directly, view it on GitHub
<#132 (comment)>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/ABnTd7vo_RQLaFPLhASINOBO84ip4TGiks5rdv67gaJpZM4MD8T0>
.
|
Yes, you can pass the parent |
This approach is workable, but unintuitive to new users. It would be nice to be able to daisy chain terraform.tfvars together automatically. Maybe using find_in_parent_folders() function in each terraform.tfvars file found in parent directories? This would allow users to keep the env vars laid out in a way that make sense to their project. Example:
The env vars declared in root terraform.tfvars would merged with /myenv/terraform.tfvars and any repeated vars in the latter would overwrite the former vars and so on. BTW, I want to thank you for putting together a great tool! Terragrunt allowed for easy simplification of an unmanageable terraform project quickly. |
Automatically ("magically") inheriting from parent
Therefore, I prefer to keep config explicit, such as adding Using terragrunt = {
terraform {
extra_arguments "parent-configs" {
arguments = [
"-var-file=${find_in_parent_folders()}"
]
commands = [
"apply",
"plan",
"import",
"push",
"refresh"
]
}
}
} We may even want to extend |
Is
|
@JohnEmhoff That sounds like a potential bug. Could you file a separate issue for it? |
This is definitely not the can of worms 🐛 I expected to find for wanting such a simple thing: that if a Regarding
The other plan I thought of was to just use But this was confusing, since I still needed to use
Am I missing anything? |
Using
Apply returns, |
I'm still finding extra_arguments "variables" approach hard as well. The following example works, but only because its using relative paths with terraform {
source = "../../../..//modules/app"
extra_arguments "vars" {
arguments = ["-var-file=../../env/dev/environment.tfvars"]
commands = ["apply", "plan", "refresh", "output"]
}
} |
Two thoughts:
|
I still think there is merit to using Convention over Configuration (think Java before Maven convention). Possible convention rules:
Concerns mentioned:
Shooting for 80/20 rule, 80% customers should be up running using the convention, the other 20% might require some form of configuration. |
OK folks, I'll try to reply to the flurry of questions one at a time. First up, @notbrain.
This is an unexpected side effect we got from merging However, things aren't so simple. First of all, Terraform doesn't support interpolations in variable definitions or Second, while interpolating the value of In short, supporting I'm open to ideas here. My two best thoughts so far are:
On the other hand, Terraform 0.9 is looming around the corner, and that should add support for
As mentioned above, we don't currently read any Terraform variables, so this won't really help.
|
Next up, @dhoer
Ah, good point. That helper might have to execute before everything is copied to a tmp folder in order for this to work. A bit messy, but probably doable. |
This is a very clever idea, but I don't think it'll work. When setting a value for a Terraform variable (e.g. in a There is also a weird chicken-and-egg problem here: we need to run Terraform to get it to return the value of a variable, but Terragrunt doesn't necessarily know what Terraform code to run and with which settings until it has the value of those variables. |
Up and downstream? So you'd pick up Also, you prefer every project to have two files, a
It would help debugging the problem, but not avoiding it in the first place.
My point here is that when you're explicit in your code, you can look at that code, and know exactly what it includes. You don't need to have any conventions memorized. If it includes some file in a parent folder, the code will say so explicitly, and you'll know to look in that parent folder. If you have conventions, then you have to know to look in special places (e.g. all folders above and below), which is non-obvious, especially as teams grow larger and not everyone has spent hours reading the Terragrunt docs.
Not at all. Imagine we have our Terraform code in a repo called |
Thanks for the lesson, and thanks for being so methodical about this--could get ugly quickly, especially with new terraform stuff on the way. I was unclear that I am now running into the problem @dhoer mentioned when using another repo to hold the terraform modules; I can't seem to figure out a non-explicit absolute path since the execution is happening inside the temp folder inside Given the things brought up in this discussion is there a current recommendation for how to proceed with this? Minimal duplication inside .tfvars files aside, how can I point terraform to my parent
(Naming convention not set, might need to go back to terraform.tfvars -- but would be much nicer to be able to reduce the number of same-named files all over the hierarchy). |
if you are using spin-up, yes. But only in that case, otherwise current directory and above
No, just one, whatever the convention says it will be pulled in.
IMHO the convention would be easier than the steps I had to do to deal with env vars.
You have to read the docs to do basic stuff today.
I think this is a good thing to allow flexibility. The above example would fail under suggested convention if it didn't have state and lock defined. I removed a convention item that mentioned only one state and lock can exist, otherwise, fail. That might be a way to manage that... The bottom line here is that terragrunt currently makes keeping configurations DRY hard. It does an amazing job with state, locking, and cleaning up module clutter and that is why I choose this tool.
It is easy to do this if I repeat the env vars in each terraform.tfvars that sources a module, but I would like to have this defined once under the
Using relative paths works, but it can lead to dangerous cut and paste errors since the environment name is included:
The convention over configuration example was to an attempt to solve repeating product, customer, and environment variables to keep it DRY. |
Ooh, I hadn't seen that yet. Very exciting!
Actually it looks like the backend configuration will not initially support variables (hashicorp/terraform#12067) but no doubt they'll get there at some point, so I think your conclusion still stands. |
I agree. I think the question is to figure out how to improve that in a way that doesn't introduce a bunch of new problems. With Terraform 0.9 right around the corner, I think I'd prefer to see what impact that has before making major changes to Terragrunt. |
@shaharmor Not currently possible. That's why this issue is still open :) I have a proposal for a solution here: #147 (comment). I may not be able to get to it for a week or two though. In the meantime, feedback and PRs very welcome. |
It looks like the linked comment above was describing a solution to two different issues, and was abandoned in favor of a solution that only fixed the other issue and not this issue - is that a fair assessment? We're running into problems organizing our terragrunt code where we would really like to use variables for the |
@apottere Which comment are you referring to? Also, what would your ideal solution to this problem look like? |
I was referencing this comment: #147 (comment). Later on in that same thread (#147 (comment)) is where the solution changed to no longer work for this issue. I would be happy with something as simple as being able to specify variables for terragrunt only (that don't have to pass on to terraform), either in the |
@apottere To make sure I'm understanding, is your goal to be able to define some common variables in, say, a root # infra/terraform.tfvars
terragrunt = {
foo = "bar"
} And to be able to reference those variables in some child # infra/stage/my-app/terraform.tfvars
terragrunt = {
foo = "${variable_from_parent("foo")}"
} |
I was thinking the other way around - for example if I wanted database and app tfstate files stored in different buckets (contrived):
|
Oh, I see, thanks for the clarification. Heh, that's yet another new use case :) The |
Would it be possible to merge variables like the |
Here's a more realistic example of what I'd love to be able to accomplish with terragrunt:
Right now it doesn't seem like there's a good way in terragrunt or terraform to store the remote-state in the region you're configuring without duplicating configurations, which means that if the S3 region that has your remote state goes down it'll impact terraforming all other regions. |
Have not contrib to terraform code or terragrunt code - this could be utter rubbish: I am digging the new locals {} and recently did a k8s plan that did not use tfvars at all. I used config.tf with locals that built the config from env vars and git refs. I used symlinks from common.tf to various plans. It was fairly slick an dry. What if instead of using only tfvars, terragrunt could use locals. The terragrunt locals could reference other locals to compute values. Terraform could use the same locals to compute the same values. Terragrunt would need to be able to interpolate locals, presumably using the same libs that Terraform does, and would take a first pass at computing its values before passing the computed values to terraform to avoid the chicken/egg situation. #tg config local
locals {
terragrunt = {
remote_state {
backend = "s3"
config {
bucket = "${local.backend_name}"
dynamodb_table = "${local.backend_name}"
}
}
backend_name="prak-${get_env("env", "exp")}-${local.region}-${get_aws_account_id()}"
}
#other locals
locals {
region=${var.region}
}
# some plan
provider "aws" {
region = "${local.region}"
} |
It's an interesting idea, but I suspect extracting or re-implementing how Terraform processes |
"very, very non-trivial" - what I nice way to say it :D TF is pretty hot, I get the moving target issue. My terragrunt config is likely to be much more conservative than my tf plans and some lag will prob be ok. Import the tf config.go https://github.com/hashicorp/terraform/blob/master/config/config.go (not re-implement, but implement) ? |
Hehe, you're welcome to give it a shot, but from last I looked at it, Terraform builds a fairly complicated dependency graph and navigates it according to a very specific lifecycle to process variables. Replicating all of that in Terragrunt, even by using Terraform's code under the hood, is, uh, well, very, very non-trivial :) |
+1 |
Would it be possible to reduce the scope of this issue? I'm trying to setup a version pinning system: I've made breaking changes to my modules and need to tell existing stacks to keep using the old code, but the only way I've found to pass a value is via ENV, which is less than ideal (can't commit the ENV vars to git :/ ). If I could use arbitrary variables within the context of terragrunt blocks only I'd be happy, no need to share the module version with Terraform. I could do this:
and then in the parent directory...
|
I'd like to see something to allow version pinning also by specifying a top-level var. This is a work around I'm using - would love to see a better way though In
In the component dir say
Where
Ideally this one liner script would be in the run cmd but I couldn't figure out the escaping. Ugly but let's me specify the version of the modules dir in each env. |
I think this issue is huge and should be divided in smaller scopes. My use case is a bit different. repository - infra-repo |prod - prod contains remote state + prod_variables which I provide the other folders bellow it Example: create_master_role/tfvars contains:
module/role/main.tf
I only use module/role to pass variables to the terraform-modules. Some of the variables use outputs from other modules... some use data..... What I would love to have is:
|
This issue has indeed gotten huge and hard to follow. Terragrunt nowadays has support for: Hopefully, between all of these, most of the use-cases mentioned in this issue are covered, so I'm going to close it. If there's anything missing, please file a new issue. |
Hi,
I have a lot of environments that all havs it's own .tfvars file for setting up base infrastructure vars like:
I define my environment in a variable called
environment_name
and i dont really want to define that more that one time, but my problem is that I want to reuse that variable in the terragrunt config as a path to my state in consulThe text was updated successfully, but these errors were encountered: