3

I am trying to create a Windows Ec2 instance from AMI and executing a powershell command on that as :

data "aws_ami" "ec2-worker-initial-encrypted-ami" {
    filter {
        name   = "tag:Name"
        values = ["ec2-worker-initial-encrypted-ami"]
    }  
}

resource "aws_instance" "my-test-instance" {
  ami             = "${data.aws_ami.ec2-worker-initial-encrypted-ami.id}"
  instance_type   = "t2.micro"

  tags {
    Name = "my-test-instance"
  }

  provisioner "local-exec" {
    command = "C:\\ProgramData\\Amazon\\EC2-Windows\\Launch\\Scripts\\InitializeInstance.ps1 -Schedule",
    interpreter = ["PowerShell"]
  }

}

and I am facing following error :

  • aws_instance.my-test-instance: Error running command 'C:\ProgramData\Amazon\EC2-Windows\Launch\Scripts\InitializeInstance.ps1 -Schedule': exit status 1. Output: The term 'C:\ProgramData\Amazon\EC2-Windows\Launch\Scripts\InitializeInstance.ps1' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again. At line:1 char:72
  • C:\ProgramData\Amazon\EC2-Windows\Launch\Scripts\InitializeInstance.ps1 <<<< -Schedule
    • CategoryInfo : ObjectNotFound: (C:\ProgramData...izeInstance.ps1:String) [], CommandNotFoundException
    • FullyQualifiedErrorId : CommandNotFoundException
5
  • the file 'C:\ProgramData\Amazon\EC2-Windows\Launch\Scripts\InitializeInstance.ps1' exist? Commented May 30, 2018 at 12:25
  • Yes... it will be there.. but after EC2 instance creation..and the command executes after creation Commented May 30, 2018 at 12:29
  • 1
    Is there a reason you are not simply dropping the code from inside the powershell script into your terraform doc with <powershell></powershell> tags surrounding it? Commented May 30, 2018 at 12:35
  • I have followed the same, but how can i test whether it executed or not ? Commented May 31, 2018 at 6:29
  • more detailed explanation with sample source code explained here Commented Oct 19, 2022 at 5:18

3 Answers 3

12

You are using a local-exec provisioner which runs the request powershell code on the workstation running Terraform:

The local-exec provisioner invokes a local executable after a resource is created. This invokes a process on the machine running Terraform, not on the resource.

It sounds like you want to execute the powershell script on the resulting instance in which case you'll need to use a remote-exec provisioner which will run your powershell on the target resource:

The remote-exec provisioner invokes a script on a remote resource after it is created. This can be used to run a configuration management tool, bootstrap into a cluster, etc.

You will also need to include connection details, for example:

  provisioner "remote-exec" {
    command = "C:\\ProgramData\\Amazon\\EC2-Windows\\Launch\\Scripts\\InitializeInstance.ps1 -Schedule",
    interpreter = ["PowerShell"]
    connection {
      type     = "winrm"
      user     = "Administrator"
      password = "${var.admin_password}"
    }
  }

Which means this instance must also be ready to accept WinRM connections.

There are other options for completing this task though. Such as using userdata, which Terraform also supports. This might look like the following example:

Example of using a userdata file in Terraform

File named userdata.txt:

<powershell>
C:\\ProgramData\\Amazon\\EC2-Windows\\Launch\\Scripts\\InitializeInstance.ps1 -Schedule
</powershell>

Launch instance using the userdata file:

resource "aws_instance" "my-test-instance" {
  ami             = "${data.aws_ami.ec2-worker-initial-encrypted-ami.id}"
  instance_type   = "t2.micro"

  tags {
    Name = "my-test-instance"
  }

  user_data = "${file(userdata.txt)}"
}

The file interpolation will read the contents of the userdata file as string to pass to userdata for the instance launch. Once the instance launches it should run the script as you expect.

Sign up to request clarification or add additional context in comments.

4 Comments

Script is executing perffectly fine but i am not sure that how can i test that the command gets executed successfully ?
it is fetching the broken metadata related from AWS API
There is a lot of things this script does it would appear docs.aws.amazon.com/AWSEC2/latest/WindowsGuide/ec2launch.html how would you determine it was successful normally?
How to configure a security group to accept WinARM connections. I added at the level of aws_security_group, in ingress part, tcp ports 3389, 5985 and 22. But it still does not work. Do you have an idea ?
6

What Brian is claiming is correct, you will get "invalid or unknown key: interpreter" error.

To correctly run powershell you will need to run it as following, based on Brandon's answer:

provisioner "remote-exec" {
    connection {
      type     = "winrm"
      user     = "Administrator"
      password = "${var.admin_password}"
    }

inline = [
         "powershell -ExecutionPolicy Unrestricted -File C:\\ProgramData\\Amazon\\EC2-Windows\\Launch\\Scripts\\InitializeInstance.ps1 -Schedule"
        ]
      }

Edit To copy the files over to the machine use the below:

  provisioner "file" {
    source      = "${path.module}/some_path"
    destination = "C:/some_path"

    connection {
      host = "${azurerm_network_interface.vm_nic.private_ip_address}"
      timeout  = "3m"
      type     = "winrm"
      https    = true
      port     = 5986
      use_ntlm = true
      insecure = true

      #cacert = "${azurerm_key_vault_certificate.vm_cert.certificate_data}"
      user     = var.admin_username
      password = var.admin_password
    }
  }

Update: Currently provisioners are not recommended by hashicorp, full instructions and explanation (it is long) can be found at: terraform.io/docs/provisioners/index.html

2 Comments

THis is completely useless. We don't need to run a powershell script that already exists on the AMI. We need it to run a powershell script that exists on the machine running terraform. In other words, how to send a powershell script to the remote machine and execute it.
@C johnson - My answer was complete. There was no mentioning of how to copy the file over but how to run a powershell command. Added to the answer how to use "file" provisioner, although the answer for that is the first search result.
4

FTR: Brandon's answer is correct, except the example code provided for the remote-exec includes keys that are unsupported by the provisioner.

Neither command nor interpreter are supported keys.

https://www.terraform.io/docs/provisioners/remote-exec.html

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.