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

Cant pass a list as a command line argument #17032

Closed
red8888 opened this issue Jan 4, 2018 · 18 comments
Closed

Cant pass a list as a command line argument #17032

red8888 opened this issue Jan 4, 2018 · 18 comments
Labels
cli documentation enhancement powershell Issues that seem to be specific to launching Terraform from PowerShell v0.11 Issues (primarily bugs) reported against v0.11 releases windows

Comments

@red8888
Copy link

red8888 commented Jan 4, 2018

Terraform Version

Terraform v0.11.1
+ provider.aws v1.6.0

Terraform Configuration Files

    // my tf file:
    variable "myvar" {type = "list"}
    
    module "my-module" {
      blah = "${var.myvar}"
      source = "path/to/module"
    }

various command line attempts (powershell)

    terraform plan -var myvar="zzzz"
    should be type list, got string
    
    terraform plan -var myvar=["zzzz"]
    invalid value "myvar=[zzzz]" for flag -var: Cannot parse value for variable ("[zzzz]") as valid HCL: At 1:6: unexpected token while parsing list: IDENT

    terraform plan -var 'myvar=["zzzz"]'
    invalid value "myvar=[zzzz]" for flag -var: Cannot parse value for variable ("[zzzz]") as valid HCL: At 1:6: unexpected token while parsing list: IDENT
@jbardin
Copy link
Member

jbardin commented Jan 4, 2018

Hi @red8888,

Your last example is correct (and works) for most unix shells.
It appears that PowerShell is stripping the double quotes from the value before terraform can evaluate it. There's not much Terraform can do in this case, so we need to find a way to get the exact string to the process.

Does it work if you escape the double quotes with backticks? (though IIRC, PowerShell should preserve double quotes within single quote, so I'm not sure where the quotes are going in this case)

terraform plan -var 'myvar=[`"zzzz`"]'

@red8888
Copy link
Author

red8888 commented Jan 4, 2018

nope:
invalid value "myvar=[zzzz]" for flag -var: Cannot parse value for variable ("[zzzz]") as valid HCL: At 1:6: illegal char

btw this doesn't work for cmd either.

PS has a literal escape thing that should work but this doesn't work either:
terraform --% plan -var 'myvar=["zzzz"]'
invalid value "'myvar=[zzzz]'" for flag -var: Cannot parse value for variable ("[zzzz]'") as valid HCL: At 1:6: unexpected token while parsing list: IDENT

for some reason it keeps putting the quotes on the outside of the brackets it seems

@red8888
Copy link
Author

red8888 commented Jan 4, 2018

could this be a bug with the windows exe?

@jbardin
Copy link
Member

jbardin commented Jan 4, 2018

Can you run the command with TF_LOG=trace? One of the first few lines will be the exact output of the CLI args as passed in by the OS, and then later as they are passed to the command function. This will at least verify whether terraform is seeing the quotes at all.

@red8888
Copy link
Author

red8888 commented Jan 4, 2018

ok!

2018/01/03 19:35:40 [INFO] Terraform version: 0.11.1  a42fdb08a43c7fabb8898fe8c286b793bbaa4835+CHANGES
2018/01/03 19:35:40 [INFO] Go runtime version: go1.9
2018/01/03 19:35:40 [INFO] CLI args: []string{"c:\\terraform\\terraform.exe", "plan", "-var", "myvar=[zzzz]"}
2018/01/03 19:35:40 [DEBUG] Attempting to open CLI config file: C:\Users\meee\AppData\Roaming\terraform.rc
2018/01/03 19:35:40 [DEBUG] File doesn't exist, but doesn't need to. Ignoring.
2018/01/03 19:35:40 [INFO] CLI command args: []string{"plan", "-var", "myvar=[zzzz]"}
invalid value "eb_environment2018/01/03 19:35:40 [DEBUG] plugin: waiting for all plugin processes to complete...
_name=[zzzz]" for flag -var: Cannot parse value for variable ("[zzzz]") as valid HCL: At 1:6: unexpected token while parsing list: IDENT
Usage: terraform plan [options] [DIR-OR-PLAN]

@red8888
Copy link
Author

red8888 commented Jan 4, 2018

well this is horrid, but using that niffy trace seems like this actually works:
terraform plan -var 'eb_environment_name=["""env123"""]'

@red8888
Copy link
Author

red8888 commented Jan 4, 2018

I guess that solves it but I still think the exe itself is doing something funky. --% is a semi new feature that is supposed to pass a totally literal un-escaped string. Thats why I was thinking maybe the exe has some goofy logic baked in to deal with windows awfulness?

@jbardin
Copy link
Member

jbardin commented Jan 4, 2018

Hi @red8888,

I'm sure there's some special escaping logic to deal with windows execution, but that is entirely outside Teraform. There might not be anything we can do about it, but I did just think of one last thing we can check to narrow down the scope.

Can you try setting TF_FORK=0 and seeing if that changes the value of the first CLI command args log line? It might also be worth verifying if the behavior is the same for cmd.exe.

Thanks!

@apparentlymart
Copy link
Member

This reminds me of #11112, which was another issue where PowerShell was not parsing the command line in the way we expected.

Unfortunately when the Terraform team tests on Windows we tend to use cmd.exe rather than PowerShell, so we don't have a lot of experience with the details of its parser. It seems to be different enough from usual Unix shell parsing and cmd.exe-based parsing that unfortunately our documentation examples often don't work quite right with PowerShell.

When working on #11112 I referred to Solve Problems with External Command Lines in PowerShell, which includes some different ways to figure out how PowerShell is parsing a particular command line.

I think @red8888 is correct that there's some additional weirdness here due to the fact that command lines on Windows are not usually pre-tokenized by the shell (when PowerShell isn't in use) and so Go does some extra work on Windows to try to create a "Unix-like" os.Args array. It appears that when PowerShell is in use the command line is first tokenized by PowerShell, then serialized back into a string to launch the process, which Go then accesses using GetCommandLine before applying the logic linked earlier. Go apparently attempts to mimic the similar logic used by Microsoft's C runtime library as included in Visual Studio.

I found some useful guidance in PowerShell and external commands done right, which includes an explanation of why the quotes vanished in the original command line described here, and some techniques to mitigate it.

Unfortunately I don't have a lot of hope for a great answer here, since we're at the mercy of PowerShell's logic for re-serializing the parsed command line. 😖 For now, it's probably best to use -var-file instead of -var when passing complex values in PowerShell, though if we can get a good enough handle on what's going on here we could consider adding some PowerShell-specific information to the main Commands documentation page to recommend some specific techniques for passing arguments to Terraform via PowerShell.

Perhaps there is some possibility to write a PowerShell cmdlet than can wrap Terraform and make it more PowerShell-friendly, but this isn't something we (the Terraform Team at HashiCorp) have the expertise to do, so unfortunately we'd need to delegate that to the community. 😞

@thalesac
Copy link

I'm having a similar issue with Linux cli.
terraform plan -var 'myvar=["zzzz"]' indeed works, but the following doesn't:

  • terraform plan -var 'myvar=['zzzz']'
  • terraform plan -var "myvar=['zzzz']"
  • terraform plan -var myvar=['zzzz']

Is there a reason for that?
At my current job we have a tool that generates the terraform/packer parameters out of custom YML files.
The python PYAML library get an entry like:

varlist: 
  - item1
  - item2

and transforms into ['item1', 'item2']
Can we reopen this ticket as a feature request to support that format?
As per of YAML specification and PYAML documentation it seems that this format is the expected.

What are your thoughts on that @apparentlymart ?

The only workaround I could come up is to create a temporarily tfvar file.
Thanks

@apparentlymart
Copy link
Member

Hi @thalesac!

In Unix shells, quotes are interpreted by the shell to override the default behavior of splitting arguments with whitespace, and so the first "level" of quotes is consumed by the shell and thus isn't passed to Terraform at all. The first example works because the ' quotes prevent special interpretation of the inner " quotes and so they are passed by the shell into the command line Terraform sees.

Unfortunately all of these behaviors are built into the shell and Terraform cannot do anything to disable or customize them. Placing the whole argument in single quotes as in your first example is the most robust method.

(Note that Terraform doesn't support single quotes as string delimiters in its expression language, so the quotes passes literally to Terraform must always be double quotes.)

@Ali-TW-London
Copy link

Ali-TW-London commented Nov 12, 2019

I used this ways and works well with latest version of Terraform
terraform plan -var 'availability_zones=["one","two","three"]'

@Sudharma
Copy link

this still does not work for me.. any hints?

@borissnd
Copy link

I had a similar issue when running terraform 0.11 on my Mac.
terraform would not accept spaces between elements in the list.
this works:
-var 'day=["sunday","monday"]'
this does not:
-var 'day=["sunday", "monday"]'

@TechnicallyJoe
Copy link

well this is horrid, but using that niffy trace seems like this actually works:
terraform plan -var 'eb_environment_name=["""env123"""]'

Well, that worked for me. Windows 10, version 2004 - PS version 7.0.3

Ugly, but it works..

@danieldreier danieldreier added the v0.11 Issues (primarily bugs) reported against v0.11 releases label Sep 30, 2020
@kubealex
Copy link

kubealex commented Jan 3, 2021

Still not working in 0.14.3, no way to pass a list of strings from command line.

[root@heisenberg libvirt-resources]# terraform apply -var 'network_cidr=["10.1.1.1/24"]'

Error: Incorrect attribute value type

  on libvirt-resources.tf line 33, in resource "libvirt_network" "kube_network":
  33:   addresses = var.network_cidr
    |----------------
    | var.network_cidr is "[\"10.1.1.1/24\"]"

Inappropriate value for attribute "addresses": list of string required.

[root@heisenberg libvirt-resources]# terraform apply -var 'network_cidr=["lol", "in", "california"]'

Error: Incorrect attribute value type

  on libvirt-resources.tf line 33, in resource "libvirt_network" "kube_network":
  33:   addresses = var.network_cidr
    |----------------
    | var.network_cidr is "[\"lol\", \"in\", \"california\"]"

Inappropriate value for attribute "addresses": list of string required.

MatthiasScholzTW added a commit to MatthiasScholz/terraform-aws-nomad that referenced this issue Jan 3, 2021
Testing SSH access depending on the CIDR block configuration.

Nevertheless due to a bug in the terraform CLI:
- hashicorp/terraform#17032
test execution is not possible until the bug is solved.
@danieldreier
Copy link
Contributor

I want to apologize for the slow response time on this issue, and also let you know that I am bulk-closing all issues exclusively reported against Terraform 0.11.x, including this issue, because we are no longer investigating issues reported against Terraform 0.11.x. In most cases, when we try to reproduce issues reported against 0.11, we either can't reproduce them anymore, or the reporter has moved on, so we believe we can better support the Terraform user community by prioritizing more recent issues.

Terraform 0.12 has been available since May of 2019, and there are really significant benefits to adopting it. I know that migrating from 0.11 to versions past 0.12 can require a bit of effort, but it really is worth it, and the upgrade path is pretty well understood in the community by now. 0.14 is available and stable, and we are quickly approaching an 0.15 release.

We have made a significant effort in the last year to stay on top of bug reports; we have triaged almost all new bug reports within 1-2 weeks for 6+ months now. If you are still experiencing this problem, please submit a new bug report with a reproduction case that works on 0.14.x, link this old issue for context, and we will triage it.

@ghost
Copy link

ghost commented Feb 27, 2021

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.

@ghost ghost locked as resolved and limited conversation to collaborators Feb 27, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
cli documentation enhancement powershell Issues that seem to be specific to launching Terraform from PowerShell v0.11 Issues (primarily bugs) reported against v0.11 releases windows
Projects
None yet
Development

No branches or pull requests