Ошибка использования user_data при создании экземпляра в terrafom - PullRequest
0 голосов
/ 13 февраля 2020

Версия Terraform = 0,12

resource "aws_instance" "bespin-ec2-web" {
  ami = "ami-0bea7fd38fabe821a"
  instance_type = "t2.micro"
  vpc_security_group_ids = [aws_security_group.bespin-sg.id]
  subnet_id = aws_subnet.bespin-subnet-private-a.id
  associate_public_ip_address = true
  tags = {
    Name = "bespin-ec2-web-a"
  }
  user_data = <<EOF
   #!/bin/bash
   USERS="bespin"
   GROUP="bespin"
   for i in $USERS; do
   adduser ${i} -g ${GROUP};
   echo ${i}:${i}1! | chpasswd;

   cp -a /etc/ssh/sshd_config /etc/ssh/sshd_config_old
   sed -i 's/PasswordAuthentication no/#PasswordAuthentication no/' /etc/ssh/sshd_config
   sed -i 's/#PasswordAuthentication yes/PasswordAuthentication yes/' /etc/ssh/sshd_config
   systemctl restart sshd
EOF
}

Почему я получаю ошибку при запуске плана Terraform?

Ошибка: недопустимая ссылка

в instance.tf строке 15, в ресурсе "aws_instance" "bespin-ec2-web": 15: adduser $ {i} -g $ {GROUP};

За ссылкой на тип ресурса должен следовать хотя бы один доступ к атрибуту, указывая имя ресурса.

Ошибка: недопустимая ссылка

в строке instance.tf 15, в ресурсе "aws_instance" "bespin-ec2-web": 15: adduser $ {i} -g $ {GROUP};

За ссылкой на тип ресурса должен следовать хотя бы один доступ к атрибуту с указанием имени ресурса.

Ответы [ 2 ]

1 голос
/ 13 февраля 2020

Прямая причина ошибки здесь в том, что ${ ... } равен Синтаксис интерполяции строкового шаблона Terraform , поэтому Terraform понимает ${GROUP} как попытку интерполировать выражение GROUP, которое не является допустимое выражение Terraform. Как следует из сообщения об ошибке, Terraform понимает GROUP как тип ресурса, как если бы это была первая часть ссылки, подобная aws_instance.foo.

Наименьшее изменение, которое нужно исправить, это экранировать ${ ... } последовательность, добавляя дополнительный $ впереди, так что литерал ${GROUP} может пройти до значения user_data:

  user_data = <<-EOF
   #!/bin/bash
   USERS="bespin"
   GROUP="bespin"
   for i in $USERS; do
   adduser ${i} -g $${GROUP};
   echo $${i}:$${i}1! | chpasswd;

   cp -a /etc/ssh/sshd_config /etc/ssh/sshd_config_old
   sed -i 's/PasswordAuthentication no/#PasswordAuthentication no/' /etc/ssh/sshd_config
   sed -i 's/#PasswordAuthentication yes/PasswordAuthentication yes/' /etc/ssh/sshd_config
   systemctl restart sshd
  EOF

Обратите внимание, что экранирование необходимо только для ${ ... }, не для таких последовательностей, как $USERS: Terraform не интерпретирует один знак доллара как специальный символ, так что он всегда будет проходить буквально.


Это конкретное выражение user_data полностью указано c и не включает в себя предназначенный синтаксис шаблона Terraform, поэтому можно полностью избежать экранирования, переместив значение user_data в отдельный файл и используя функцию file для воспринимать содержимое этого файла буквально (вообще без интерпретации шаблона):

  user_data = file("${path.module}/user_data.sh")

Иногда user_data требует включения данных int используется в другом месте конфигурации Terraform, смешанный с синтаксисом оболочки. Для этого можно использовать экранирование, как описано выше, но по мере усложнения необходимой строки может оказаться полезным отделить часть, содержащую интерполяции, от литеральной части, чтобы получить лучшее из обоих миров и избежать экранирования внутри Основная часть сценария:

  user_data = <<-EOT
    EXAMPLE_VARIABLE='${var.example}'
    ${file("${path.module}/user_data.sh")}
  EOT
1 голос
/ 13 февраля 2020

Данные пользователя должны передаваться при рендеринге шаблона, или вы также можете использовать функцию base64encode для передачи вашего файла.

data "template_file" "user-data" {
  template = file("${path.module}/user-data.sh")
}

resource "aws_instance" "bespin-ec2-web" {
  ...
  ...

  user_data = "${data.template_file.user_data.rendered}"

  ...
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...