How to execute PowerShell command through Terraform

天大地大妈咪最大 提交于 2020-06-26 14:11:26

问题


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

回答1:


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.




回答2:


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




回答3:


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



来源:https://stackoverflow.com/questions/50604127/how-to-execute-powershell-command-through-terraform

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!