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

Failure on Windows with paths that include a single quote (') #200

Open
1 task done
KyleKotowick opened this issue Mar 18, 2023 · 3 comments
Open
1 task done

Failure on Windows with paths that include a single quote (') #200

KyleKotowick opened this issue Mar 18, 2023 · 3 comments
Labels

Comments

@KyleKotowick
Copy link

Terraform CLI and Provider Versions

Terraform v1.4.2
on windows_amd64
+ provider registry.terraform.io/hashicorp/external v2.3.1

Terraform Configuration

data "external" "run" {
  program = [
    "powershell.exe",
    "foo ' bar.ps1",
  ]
}

output "run" {
  value = data.external.run.result
}

Expected Behavior

Single quotes are valid in file/folder names on Windows. This should execute the given script file as expected.

Actual Behavior

data.external.run: Reading...
╷
│ Error: External Program Execution Failed
│
│   with data.external.run,
│   on main.tf line 2, in data "external" "run":2:   program = [
│    3:     "powershell.exe",
│    4:     "foo ' bar.ps1",
│    5:   ]
│
│ The data source received an unexpected error while attempting to execute the program.
│
│ Program: C:\WINDOWS\System32\WindowsPowerShell\v1.0\powershell.exe
│ Error Message: The string is missing the terminator: '.+ CategoryInfo          : ParserError: (:) [], ParentContainsErrorRecordException
│     + FullyQualifiedErrorId : TerminatorExpectedAtEndOfString
│
│
│ State: exit status 1

Steps to Reproduce

  1. terraform apply

How much impact is this issue causing?

High

Logs

No response

Additional Information

I've tried escaping the single quote with both a backtick and a backslash, neither fix the issue.

Code of Conduct

  • I agree to follow this project's Code of Conduct
@austinvalle
Copy link
Member

austinvalle commented Mar 23, 2023

Hi @KyleKotowick 👋🏻 , thanks for submitting the issue and sorry you're running into trouble here.

Can you try surrounding the single quote with double quotes (you'll need to escape them in your terraform config) and see if that solves it?

data "external" "run" {
  program = [
    "powershell.exe",
    "foo \"'\" bar.ps1",
  ]
}

output "run" {
  value = data.external.run.result
}

I've made an attempt recreating the issue with a gist with an example of quoting/escaping: https://gist.github.com/austinvalle/5305fd995a8e7e8d4ceb6067773592e1

@KyleKotowick
Copy link
Author

Hi @austinvalle, thanks for the reply. Yes, quoting it does work. The problem is that the file path in our system is dynamically specified, and as far as I'm aware, there's no Terraform function that could automatically do that kind of quoting.

In our module, we use the abspath function to get the path to the script file because we want the working directory to be user-selectable. It works something like so:

variable "working_dir" {
  type = string
}

data "external" "run" {
  working_dir = var.working_dir
  program = [
    "powershell.exe",
    "${abspath(path.module)}/script.ps1"
  ]
}

output "run" {
  value = data.external.run.result
}

This allows us to build a module that runs our script, but allows the user to run it in whatever working directory they like. For reference, this is for our fairly popular Invicton-Labs/shell-data/external and Invicton-Labs/shell-resource/external modules.

The issue arises if the user's Terraform directory (that uses our module) has a ' anywhere in the path. abspath(path.module) will then return a string with the single quote in it, which causes the reported error.

We could try doing a replace(abspath(path.module), "'", "\"'\""), but we all know that things start getting messy real quick when you try to do path escaping with simple search-and-replace. It might work for this particular example, but if I tried to embed that adjusted path into any other command that is itself in double quotes (e.g. included in a shell script), it will be quite unreliable.

@austinvalle
Copy link
Member

austinvalle commented Mar 24, 2023

Thanks for the additional info! You'll have to bear with me as I'm not super proficient with Powershell 😄

If the main goal is to invoke a Powershell script from a path that may or may not contain fun characters, are you able to utilize the -File argument instead of the defaulted -Command argument?

Looking at https://stackoverflow.com/a/45762288 they differ in how the file paths are processed and it may alleviate the quote handling.

I created an example in a folder called /fun '&'^@(%~, folder with the following config:

main.tf

locals {
  curr_path = "${abspath(path.module)}/script.ps1"
}

data "external" "run_file" {
  program = [ 
    "powershell.exe",
    "-File",
    "${local.curr_path}"
   ]
}

output "run_file" {
  value = data.external.run_file.result
}

output "local_curr_path" {
  value = local.curr_path
}

script.ps1

Write-Output @{ result = "hello" } | ConvertTo-Json

result

image

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

No branches or pull requests

2 participants