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 · 58 comments
Open

allow -target to accept globs #2182

tamsky opened this issue Jun 2, 2015 · 58 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
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 👍, 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

@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

This comment was marked as duplicate.

@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

This comment was marked as off-topic.

@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

This comment was marked as off-topic.

@rogerioefonseca

This comment was marked as off-topic.

@argium

This comment was marked as abuse.

@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

This comment was marked as off-topic.

@Positronico
Copy link

That's what I came up with, and it's helping me a lot. I'm using regex on resource names from the tf source and state files. Just added an exclude option to skip some of the previously selected targets for finer control.

Single python script, easy to integrate in a pipeline.

https://github.com/Positronico/terratarget

@kimllee
Copy link

kimllee commented Dec 10, 2024

Thank you @Positronico !

Looks like it can't handle the following context :

terratarget  plan -var-file values.tfvars -target="google_logging_project_sink.*"

Warning: No targets matched the wildcard patterns.

Planned command: terraform plan -var-file values.tfvars

Do you want to execute this command? [y/N]: N
Execution aborted by the user.

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