hashicorp / terraform

Terraform enables you to safely and predictably create, change, and improve infrastructure. It is a source-available tool that codifies APIs into declarative configuration files that can be shared amongst team members, treated as code, edited, reviewed, and versioned.
https://www.terraform.io/
Other
42.32k stars 9.49k forks source link

Ignore resource if variable set. #2831

Closed gtmtech closed 8 years ago

gtmtech commented 9 years ago

We have a couple of extra terraform resources that need creating under certain conditions. For example we use environmental overrides to create a "dev" and a "qa" environment from the same base terraform resources. However the qa environment needs extra security_group_rules set.

Unless this can already be achieved, (if so how?) it would be useful to be able to set an override variable for the qa case which deactivates (or activates) a resource.

I would consider an implementation to be a top-level field available on every resource such as:

ignore => "${var.some_variable}"

Then we can set a default for "some_variable" of 1, and set to 0 as an override for the qa tf.variables file.

Otherwise I can see no way of having optional resources flagged for inclusion under certain circumstances.

apparentlymart commented 9 years ago

One way to do this today is to use the count attribute on a resource:

variable "number" {
    default = 1
}

resource "any_resource" "foo" {
    count = "${var.number}"
}

You can set count to 0 to prevent any resources being created at all, so by interpolating it with a variable and conditionally setting it to either 1 or 0 you can control whether or not this single resource gets created.

$ terraform plan -var="number=0"
Refreshing Terraform state prior to plan...

No changes. Infrastructure is up-to-date. This means that Terraform
could not detect any differences between your configuration and
the real physical resources that exist. As a result, Terraform
doesn't need to do anything.

$ terraform plan -var="number=1"
Refreshing Terraform state prior to plan...

The Terraform execution plan has been generated and is shown below.
Resources are shown in alphabetical order for quick scanning. Green resources
will be created (or destroyed and then created if an existing resource
exists), yellow resources are being changed in-place, and red resources
will be destroyed.

Note: You didn't specify an "-out" parameter to save this plan, so when
"apply" is called, Terraform can't guarantee this is what will execute.

+ any_resource.foo

Plan: 1 to add, 0 to change, 0 to destroy.
gtmtech commented 9 years ago

Thanks - it feels a bit odd/quirky, but I'll def give it ago :)

thegedge commented 9 years ago

There's also a lot of chatter about conditional logic and ignoring resources over in #1604

phinze commented 8 years ago

@apparentlymart's strategy of count = 0 is the correct way to do this today, and @thegedge is correct that #1604 is the home for future improvements

emoshaya commented 8 years ago

We are using a Jenkins plugin to deploy a service onto AWS instances and created/update 'VERSION' tag for the instance(s). Unfortunately, Terraform deletes this tag unless there's a way to ignore it. Is there a way to ignore just a single tag, e.g. 'VERSION' as opposed to ignoring all tags? I'd really appreciate a response.

Thanks

tobiasmcnulty commented 8 years ago

Won't this method delete those resources rather than ignore them when count = 0?

BogdanSorlea commented 8 years ago

Unfortunately, from what I've experienced, the count = 0 method proves useless when having a resource that depends on another (e.g. a aws_security_group_rule that obviously depends on a aws_security_group). Putting count = 0 on both the SG and the rule would theoretically not create any of them, except that when running (plan, apply, etc.) on that an error like

Error running plan: 1 error(s) occurred:

* Resource 'aws_security_group.it-sg' does not have attribute 'id' for variable 'aws_security_group.it-sg.id'

is returned.

Although I think there's no way out of this (and hence the count = 0 "solution" works only for "leaf" resources), I'm eager to learn of any potential workarounds for the problem I exposed. @gtmtech @apparentlymart @thegedge @phinze

eyalzek commented 8 years ago

I'm having the same problem as @BogdanSorlea, I'm managing a couple of separate environments and some resources aren't required for part of them. So with my current configuration I'm getting an error for the resource that doesn't exist whenever I want to plan/apply anything on one of the aforementioned environments.

MikeyYeahYeah commented 7 years ago

@BogdanSorlea Did you ever find a solution to the problem you mentioned in this issue?

apparentlymart commented 7 years ago

The current "pattern" for depending on a conditional resource is like this:

resource "example" "conditional" {
  count = "${var.enabled ? 1 : 0}"
}

resource "example" "dependent" {
  argument = "${join("", example.conditional.*.attribute)}"
}

Other variants are possible to set defaults, etc, but "joining" the zero-or-one-element list is how to avoid the issue of referring to the zeroth element when there is no such element.

We'll work on making this smoother in future via more language improvements.

rahulkp220 commented 6 years ago

@apparentlymart can you have a look at this problem https://stackoverflow.com/questions/48306089/how-do-i-make-a-field-optional-inside-a-terraform-resource , would be a great help.

ghost commented 4 years ago

I'm going to lock this issue because it has been closed for 30 days ⏳. This helps our maintainers find and focus on the active issues.

If you have found a problem that seems similar to this, please open a new issue and complete the issue template so we can capture all the details necessary to investigate further.