Terraform Kubernetes provisioner "local-exec" kubectl apply -f -<<EOF on Windows not working

Viewed 4163

I am trying to create/apply this kubectl .yaml file https://github.com/Azure/aad-pod-identity/blob/master/deploy/infra/deployment.yaml via Terrraform`s null_resource to the AKS to install Azure AD Pod Identity. It needed to deploy Azure Gateway Ingress Controller. Using Windows 10 with VS Code

main.tf:

data "template_file" "aad_pod" {
  template = "${file("${path.module}/templates/aad_pod.yaml")}"
}

resource "null_resource" "aad_pod_deploy" {
  triggers = {
    manifest_sha1 = "${sha1("${data.template_file.aad_pod.rendered}")}"
  }

  provisioner "local-exec" {
    command = "kubectl apply -f -<<EOF\n${data.template_file.aad_pod.rendered}\nEOF"
  }
}

After terraform apply I have this error:

Error: Error running command 'kubectl apply -f -<<EOF
'cutted listing of yaml file'
EOF': exit status 1. Output: << was unexpected at this time.

Any help will be appreciated

2 Answers

Because of differences between Unix-like operating systems and Windows, it's rarely possible to use local-exec in a portable way unless your use-case is very simple. This is one of the reasons why provisioners are a last resort.

I think the most portable answer would be to use the official Kubernetes provider to interact with Kubernetes here. Alternatively, if using kubectl's input format in particular is important for what you are doing, you could use a community-maintained kubectl provider.

resource "kubectl_manifest" "example" {
  yaml_body = data.template_file.aad_pod.rendered
}

If you have a strong reason to use the local-exec provisioner rather than a native Terraform provider, you'll need to find a way to write a command that can be interpreted in a compatible way by both a Unix-style shell and by Windows's command line conventions. I expect it would be easier to achieve that by writing the file out to disk first and passing the filename to kubectl, because that avoids the need to use any special features of the shell and lets everything be handled by kubectl itself:

resource "local_file" "aad_pod_deploy" {
  filename = "${path.module}/aad_pod.yaml"
  content  = data.template_file.aad_pod.rendered

  provisioner "local-exec" {
    command = "kubectl apply -f ${self.filename}"
  }
}

There are still some caveats to watch out for with this approach. For example, if you run Terraform under a directory path containing spaces then self.filename will contain spaces and therefore probably won't be parsed as you want by the Unix shell or by the kubectl Windows executable.

Thank you for the comments. I found the solution. I am using helm_release resource in terraform. Just create your helm chart with necessary template and use it with helm_release. I made a helm chart for AAD Identity and it make the job

Related