hashicorp / terraform-provider-google

Terraform Provider for Google Cloud Platform
https://registry.terraform.io/providers/hashicorp/google/latest/docs
Mozilla Public License 2.0
2.32k stars 1.72k forks source link

template_file cannot render bash arrays variables with google provider version = "3.5.0" #8379

Closed cd-bustamante closed 3 years ago

cd-bustamante commented 3 years ago

Community Note

Terraform Version

Terraform v0.14.4

Terraform Configuration Files

main.tf

resource "google_compute_instance" "vm_instance" {
  name         = var.proxy_vm_name
  machine_type = var.proxy_vm_machine_type
  allow_stopping_for_update = var.allow_stopping_for_update
  deletion_protection = var.deletion_protection

  boot_disk {
    initialize_params {
      image = var.proxy_vm_boot_disk
    }
  }

  network_interface {
    network = var.proxy_vm_network
    subnetwork = var.proxy_vm_subnetwork
  }

  metadata_startup_script = "${data.template_file.init.rendered}"

  service_account {
    # Google recommends custom service accounts that have cloud-platform scope and permissions granted via IAM Roles.
    scopes = var.service_account_scope
  }

  labels = var.labels
}

datasource.tf

locals {

  count = length(var.iptables_in)
  in = join(",",var.iptables_in)
  out = join(",",var.iptables_out)

}

data "template_file" "init" {
  template = "${file("templates/init.tpl")}"
#  template = "${file("${​path.module}​​/templates/init.tpl")}"
  vars = {
    counter = local.count
    incoming = local.in
    outgoing = local.out
  }
}

variables.tf

variable "project" {
  description = "(Required) GCP Project where the proxy Virtual machine will be created. The project VPC must have network access against the end point"

}

variable "proxy_vm_name" {
  description = "(Required) A unique name for the resource, required by GCE. Changing this forces a new resource to be created."
}

variable "proxy_vm_machine_type" {
  description = "(Required) The machine type to create."
  default = "e2-medium"
}

variable "allow_stopping_for_update" {
  description = "(Optional) If true, allows Terraform to stop the instance to update its properties. If you try to update a property that requires stopping the instance without setting this field, the update will fail."
  default = true
}

variable "deletion_protection" {
  description = "(Optional) Enable deletion protection on this instance. Defaults to false. Note: you must disable deletion protection before removing the resource (e.g., via terraform destroy), or the instance cannot be deleted and the Terraform run will not complete successfully."
  default = false
}

variable "proxy_vm_boot_disk" {
  description = "(Required) Boot disk image for the proxy vm"
  default = "debian-cloud/debian-10"
}

variable "proxy_vm_network" {
  description = "(Optional) The name or self_link of the network to attach this interface to. Either network or subnetwork must be provided."
  default = "default"
}

variable "proxy_vm_subnetwork" {
  description = "(Optional) The name or self_link of the subnetwork to attach this interface to. The subnetwork must exist in the same region this instance will be created in. If network isn't provided it will be inferred from the subnetwork. Either network or subnetwork must be provided."
  default = "default"
}

variable "service_account_scope" {
  description = "(Required) A list of service scopes. Both OAuth2 URLs and gcloud short names are supported. To allow full access to all Cloud APIs, use the cloud-platform scope."
  type        = list
  default = ["cloud-platform"]
}

variable "labels" {
  description = "A map of the tags to use on the resources that are deployed with this module."
  type        = map
  default     = {
    type = "proxy"
  }
}

variable "iptables_in" {
  description = "(Required) List of IP tables configuration parameters; listening_port, destination_ip, destination_port"
  type = list

}

variable "iptables_out" {
  description = "(Required) List of IP tables configuration parameters; listening_port, destination_ip, destination_port"
  type = list
}

init.tpl

#!/bin/bash

#
# Echo commands as they are run, to make debugging easier.
# GCE startup script output shows up in "/var/log/syslog" .
#
set -x

#
# Stop apt-get calls from trying to bring up UI.
#
export DEBIAN_FRONTEND=noninteractive

#
# Make sure installed packages are up to date with all security patches.
#
apt-get -yq update
apt-get -yq upgrade
#
# Install Google's Stackdriver logging agent, as per
# https://cloud.google.com/logging/docs/agent/installation
#
curl -sSO https://dl.google.com/cloudagents/install-logging-agent.sh
bash install-logging-agent.sh
#
# Install Google's Stackdriver monitoring agent, as per
# https://cloud.google.com/monitoring/agent/installation
curl -sSO https://dl.google.com/cloudagents/add-monitoring-agent-repo.sh
bash add-monitoring-agent-repo.sh
apt-get -yq update
apt-get install -y stackdriver-agent

# IP tables configuration section
#

# Converting string into array for the proxy incoming and outgoing variables
echo "IP TABLES RESET"
my_inco="${incoming}"
declare -a iarray
iarray=($(echo $my_inco | tr "," " "))

my_outg="${outgoing}"
declare -a oarray
oarray=($(echo $my_outg | tr "," " "))

# Retrieving IP address of the VM proxy
IP="$(/usr/sbin/ifconfig | grep -A 1 'ens4' | tail -1 | awk '{print $2}')"
PRE="$(hostname)"

# Delete previous IP tables configuration
iptables -F
iptables -F -t nat
echo 1 >| /proc/sys/net/ipv4/ip_forward

c=0
max=$((${counter} - 1))
until [ $c -gt $max ]
do
  echo 'iptables -t nat -A PREROUTING -p tcp -d $IP --dport "${iarray[$c]}" -j DNAT --to "${oarray[$c]}"'
  echo "iptables -t nat -A POSTROUTING -j MASQUERADE"
  echo 'iptables -A FORWARD -p tcp -m tcp --dport "${iarray[$c]}" -j LOG --log-prefix "$PRE-${iarray[$c]}"'
  iptables -t nat -A PREROUTING -p tcp -d $IP --dport "${iarray[$c]}" -j DNAT --to "${oarray[$c]}"
  iptables -t nat -A POSTROUTING -j MASQUERADE
  iptables -A FORWARD -p tcp -m tcp --dport "${iarray[$c]}" -j LOG --log-prefix "$PRE-${iarray[$c]}"
  c=$((c+1))
done
echo "Finished the loop"

Debug Output

N/A

Panic Output

Expected Behavior

When running the code I should be able to create a new VM and be able to use template_file to pass it to GCP to enable it for the new VM to use as starting up script

Actual Behavior

I am receiving the following error in Terraform command line

Error: failed to render : :59,70-71: Invalid character; This character is not used within the language., and 7 other diagnostic(s)

on datasource.tf line 9, in data "template_file" "init": 9: data "template_file" "init" {

Steps to Reproduce

  1. terraform apply

Important Factoids

References

edwardmedia commented 3 years ago

@cd-bustamante same question to you as https://github.com/hashicorp/terraform-provider-google/issues/8376. If this is still an open question, please share the debug log

cd-bustamante commented 3 years ago

Hello @edwardmedia , here is the URL to the GIST with the log ==> https://gist.github.com/cd-bustamante/3ffe6ad6f8e8cd0293cac73ea3a16f70

Thanks for the follow up!

edwardmedia commented 3 years ago

@cd-bustamante I have left comments in https://github.com/hashicorp/terraform-provider-google/issues/8376. This is about the script rendering via data source & template_file. These features are owned by Terraform. I can try to repro the issue by directly using the inline scripts for metadata_startup_script?

edwardmedia commented 3 years ago

@cd-bustamante Closing this issue then along with #8376. Feel free to reopen if the provider can help

ghost commented 3 years ago

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 feel this issue should be reopened, we encourage creating a new issue linking back to this one for added context. If you feel I made an error πŸ€– πŸ™‰ , please reach out to my human friends πŸ‘‰ hashibot-feedback@hashicorp.com. Thanks!