Skip to content
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

allow -target to accept globs #2182

Open
tamsky opened this issue Jun 2, 2015 · 56 comments
Open

allow -target to accept globs #2182

tamsky opened this issue Jun 2, 2015 · 56 comments

Comments

@tamsky
Copy link
Contributor

tamsky commented Jun 2, 2015

Suppose one declares several concurrent environments in a single tf config.

To limit cli actions to a single environment at a time, it would be convenient if a way existed, via -target to glob-match modules, module_paths, resource_types and resource_names:

terraform apply -target=aws*.staging* # target aws* resource_types

or similarly, for all modules:

terraform apply -target=*.*.staging* # target all modules and resource_types

or similarly, for all module_paths:

terraform apply -target=**.staging* # star star = target all modules and submodules

@scalp42
Copy link
Contributor

scalp42 commented Jun 2, 2015

👍 would love to be able to use as opposed to writing CLIs to wrap Terraform

@KZachariassen

This comment has been minimized.

@elocnatsirt

This comment has been minimized.

@joshmullis
Copy link

There are other requests I've seen for "exclude" logic, so it may be useful to have this use regex instead of glob to take care of both requests.

@mario21ic
Copy link

Where is the issue for "exclude" logic? that it'll resolve me many problems 👍, maybe like target:
$ terraform plan -exclude=mymodule.resource_not_important

@kwent

This comment has been minimized.

@pkieszcz

This comment has been minimized.

@ryandeivert

This comment has been minimized.

@ljsommer
Copy link

ljsommer commented Oct 3, 2017

Wow this is a very old request for a very useful feature.
Great idea, our use case would be to use target to specify the creation of template resources to create fully populated python files for Lambdas which have interpolated their vars from terraform so that we can do local unit and lint testing before interacting with the AWS API.

@ezalejski

This comment has been minimized.

@idjaw
Copy link

idjaw commented Nov 11, 2017

Would it be correct to relate with Issue #2253

The feature request is for a different option parameter, but the nature of the feature to have an "exclude" pattern instead of just "apply" could be interesting.

Considering they are both trying to achieve somewhat similar results. By supporting also the exclude and this pattern feature, it would make it that much more flexible and powerful.

@chunyong-lin

This comment has been minimized.

@kcighon

This comment has been minimized.

@maxblaze

This comment has been minimized.

2 similar comments
@tolgaingenc

This comment has been minimized.

@cytar

This comment has been minimized.

@apparentlymart
Copy link
Member

Please do not post "+1" comments here, since it creates noise for others watching the issue and ultimately doesn't influence our prioritization because we can't actually report on these. Instead, react to the original issue comment with 👍, which we can and do report on.

@JnMik
Copy link

JnMik commented Nov 19, 2018

Not only the option target, the "Data" ressource block as well should be able to target a ressource name="prefix-*". Ressources often needs to have dynamic name to be able to spawn in parallel to have zero downtime with lifecycle "create_before_destroy", it makes them pretty hard to target sometimes.

@vincentkwok
Copy link
Contributor

Any schedule on this feature? It helps on managing multiple modules. E.g. modify resources under specific module instead of all resources among modules

@sdickhoven
Copy link

sdickhoven commented Jun 5, 2019

we are managing 700+ domains (plus records) with terraform in cloudflare. our resource naming is perfect for prefix wildcarding (if that's easier to implement than full-on globbing):

terraform apply -target=cloudflare_record.my_domain_com__*

some zones have hundreds of records so it would be incredibly tedious to list them all as targets. but all the records are prefixed with the zone name.

so definitely 👍 on this feature.

@rightaway

This comment has been minimized.

@teamterraform
Copy link
Contributor

Please do not post "+1" comments here, since it creates noise for others watching the issue and ultimately doesn't influence our prioritization because we can't actually report on these. Instead, react to the original issue comment with +1, which we can and do report on.

@jomeier
Copy link

jomeier commented Aug 16, 2019

Hi,

this request is almost four years old and seems to be rather important. Any progress on that?

Thanks and best regards,

Josef

@alexlevinta
Copy link

Returning to this after a while, would being able to "Tag" or group resources be another way to help? I'm thinking of building a canary group for deployments but to make deploying this easier you could prefix all the resources in a canary group with a common name that can then be targeted.

The same could be achieved with a grouping convention. This could help with any staged deployments as you could deploy certain artifacts in groups with manual triggers between them.

It would work for groupings that you define ahead of time, but we generally face this issue when something needs to be changed on some long list of production hosts but not on others. The tagging would resolve staged deployments or groupings that you know before running into issues. The regex target and exclusion would help in many more cases.

@stacybird
Copy link

It would appear this is still relevant years later. Did the thumbsup to the initial issue comment.
Context: Got here looking for a better way to find terraform plan -target=module.FeatureName.aws_thing_here*.* without having to specify each target. I see there are cli workarounds, those would have to be integrated with atlantis workflows, which is possible, I'll check them out. Here's hoping regex becomes a more desirable feature. Still relevant years later. Thanks for all you do.

@rightaway
Copy link

What workarounds are people using? Because this is a very important feature.

@schneidexe
Copy link

schneidexe commented Feb 17, 2021

There were at least two implemented/mentioned by @phzietsman and me a few comments above. But I guess there is more out there in the wild...

@majormoses
Copy link
Contributor

Not sure as of what version but you can terraform plan -target=module.my-module which will plan for all resources within the module. Not quite the same thing but its at least a step in the right direction. This did solve most of my use cases and can live with until there is more featureful pattern matching.

@schneidexe
Copy link

That only gets you so far though. Imagine you have a complex setup containing modules for k8s clusters on AWS with lambdas, ELBs, databases, DNS records, etc. and just wanna update your ELBs. Then you need scope it to something like terraform plan -target=**.aws_elb.*. In such a case you'd now need to search for all aws_elb entries in your state and then add them as individual -targets which can become quite cumbersome.

@majormoses
Copy link
Contributor

I hear, at work we use CI (jenkins) to help alleviate some of the tedious bits associated. A state list job allows an optional grep term to filter. Our plan jobs allows a comma separated target list. Not perfect, a bit of CI glue can reduce the pain until its enhanced.

@schneidexe
Copy link

Yeah, exactly that was also my approach and it's pretty much what my little wrapper project does (see above).

@whiskeysierra
Copy link

@schneidexe Instead of parsing the human-readable console output of terraform plan, you could render the plan to a file and then use terraform show on it. With some jq magic, you'd have something less brittle. Although the terraform output is most likely not going to change anytime soon.

@alahijani
Copy link

Here's my low-tech workaround. Add this function to your .bashrc:

terraform-targets () {
  sed 's/\x1b\[[0-9;]*m//g' | grep -o '# [^( ]* ' | sed " s/^# /-target '/; s/ $/'/; "
}

You can use it it in a variety of ways:

terraform plan | terraform-targets
terraform plan | terraform-targets | grep 'some pattern'
terraform plan | terraform-targets | grep 'some pattern' | xargs -r terraform apply

(The -r flag to xargs means don't run the command if the list is empty.)

@iramello
Copy link

Thanks @alahijani . I've added an additional grep to the line because we have bash scripts with comments, and those comments are incorrectly shown as -target otherwise.

terraform-targets () {
  sed 's/\x1b\[[0-9;]*m//g' | grep -o '# [^( ]* ' | grep '\.' | sed " s/^# /-target '/; s/ $/'/; "
}

@DanPhonovation
Copy link

@alahijani

terraform plan | terraform-targets | grep 'some pattern' | xargs -r terraform apply

When I try your last command for the "yes" prompt, something else gets passed and I get action cancelled. Am I doing something wrong?

@GeorgiKarapetrov
Copy link

@alahijani

terraform plan | terraform-targets | grep 'some pattern' | xargs -r terraform apply

When I try your last command for the "yes" prompt, something else gets passed and I get action cancelled. Am I doing something wrong?

I run terraform plan | terraform-targets | grep 'some pattern' | xargs -r terraform apply -auto-approve when I am positive it's what I want.

@suryastef
Copy link

suryastef commented Sep 9, 2022

I have another workaround for this, but I think this will apply only for resource that already in state

for i in $(terraform state list | grep "some-pattern");
do
  terraform apply -target=$i -auto-approve;
done

note: be careful with -auto-approve, do terraform plan first insteaad of terraform apply directly

@schneidexe
Copy link

@suryastef keep in mind that will run a separate plan/apply for each resource matching which could take a while esp. if you have e.g. a big remote state file in s3. Also in some cases the state might chnage and resources in the list would be removed as dependecies to others... so it would be beneficial to chain the -target .... -target for each $i and run the command only once.

@suryastef
Copy link

@schneidexe thank you for your concern, I didn't think that way before

Also in some cases the state might chnage

@wwalker
Copy link

wwalker commented Sep 14, 2022

The problem is the lock acquisition and release time for each call, and if they were route53 targets every call could take 3 minutes. (grumble about route53 (not terraform) taking so long to do ANYTHING...). so if I wanted to destroy 120 route53 entries
(which I actually do at least weekly), the loop method could take up to 6 hours!!!

I have another workaround for this, but I think this will apply only for resource that already in state

for i in $(terraform state list | grep "some-pattern");
do
  terraform apply -target=$i -auto-approve;
done

note: be careful with -auto-approve, do terraform plan first insteaad of terraform apply directly

@rubber-ant
Copy link

+1

@cusspvz
Copy link

cusspvz commented Jan 10, 2023

Based on the solution provided by @suryastef at #2182 (comment), I think this makes more sense as it only makes use of one terraform call. (terraform allows us to define multiple targets at the same apply call)

targets=$(for x in `terraform state list | grep -e "azurerm_key_vault*.*"`; do echo "-target=$x "; done);
echo $targets | xargs terraform apply -var-file=... # add here your own options;

@schneidexe
Copy link

Unfort. that does not cover for targets that were not yet deployed and hence do not yet exist in the state...

@cusspvz
Copy link

cusspvz commented Jan 10, 2023

@schneidexe figured that out after commenting it in here. 😬

@baurmatt
Copy link
Contributor

Getting the approval prompt with xargs can be accomplished with --open-tty:

terraform plan | terraform-targets | grep 'some pattern' | xargs -r --open-tty terraform apply

@silopolis
Copy link

8 years and a half later... I hardly believe such a widespread need remains unconsidered! :|

Adding to the list of alternatives: https://github.com/future-architect/tftarget

@DevOpsJon
Copy link

Wow almost a decade of terraform pain and this isn't done yet. Yeah, so Pulumi then...

@rogerioefonseca
Copy link

Hmmmm.... still not there.
It would clean up my code in a really fashion way!

@rifuller
Copy link

rifuller commented Feb 27, 2024

I wanted to use this as a workaround for the lack of support for dynamically configuring providers per-resource-instance. Essentially, provision the dependency explicitly in one apply pass, fetch the resources' properties manually, and then generating the provider blocks. I am again disappointed in Terraform and continue to not recommend it to everyone I speak to.

@vanvuvuong
Copy link

vanvuvuong commented Mar 5, 2024

I know this issue hadn't been resolved for long time, but maybe this will help someone. This is another low-level option for my case, terraform apply for multiple target based on *tf file

How I used it with terraform/terragrunt:

terraform apply $(get_target "aws_subnet,aws_vpc" "module.network.")
terragrunt apply $(get_target "aws_subnet,aws_vpc" "module.network.")
get_target() {
    # $1: pattern of target resource you want to filter(based on your terraform files), e.g: aws_subnet
    # $2: prefix that you want to add to -target, e.g: module.test.
    # result: -target module.test.aws_subnet.subnet_name
    if [ $# -ne 2 ]; then
        printf "Please run this function like this example\n- general: \t\t\t get_target \"pattern\" \"prefix\"\n- 1 pattern resource:\t\t get_target \"aws_s3\" \"module.frontend.\"\n- multiple pattern resource:\t get_target \"aws_s3,aws_subnet,aws_route\" \"module.frontend.\" "
        return 1
    fi
    array_pattern=($(echo "$1" | tr ',' '\n'))
    prefix=$2
    output_pattern=""
    apply_targets=""
    for pattern in "${array_pattern[@]}"; do
        output_pattern="^resource.*$pattern|$output_pattern"
    done
    output_pattern=${output_pattern%?}
    echo $output_pattern
    for target in $(grep -hRE "$output_pattern" | sed -e 's/resource "//g' | sed 's/" {//g' | sed 's/" "/./g'); do apply_targets="$apply_targets -target $prefix$target"; done
    echo $apply_targets
}

updated function for multiple pattern in 15/4/2024

@mchigit
Copy link

mchigit commented May 6, 2024

Why is there still no progress on this issue? It's been reported since 2015, almost a decade later and still no updates? Clearly people want this feature based on the number of comments on this thread.

Also stop sending people from newer issues to an older issue that you don't ever plan on working on. If this isn't a feature worth your time to develop, just tell folks you won't ever support it and we will find alternatives instead of jumping through issues.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests