Создание ansible инвентаря для нескольких целевых хостов - PullRequest
5 голосов
/ 17 июня 2020

Я использую terraform для создания ресурсов, а затем использую файл шаблона для создания ansible инвентаря на языке yaml. Я создаю несколько виртуальных машин в терраформе и настраиваю их, используя ansible в одном конвейере.

Проблема, с которой я сталкиваюсь, - это использование файла yaml - для списков, которые выдают ошибку в ansible playbook

Outputs.tf

resource "local_file" "AnsibleInventory" {
content = templatefile("inventory.tmpl",
{
ansible_port = "5986"
ansible_connection = "winrm"
ansible_winrm_server_cert_validation = "ignore"
ansible_winrm_transport = "ntlm"
vm-ip = data.azurerm_public_ip.main.*.ip_address,
username = "testadmin",
ansible_password = "abc"
}
)
filename = "inventory.json"
}

inventory.tmpl

${jsonencode({
  "all": {
    "hosts": {
      "server": [
        for ip in vm-ip : { 
        "ansible_host": "${ip}",
        "ansible_port": 5986,
        "ansible_user": "testadmin",
        "ansible_winrm_transport": "ntlm",
        "ansible_connection": "winrm",
        "ansible_winrm_server_cert_validation": "ignore",
        "ansible_password": "abc"
        }
      ]
    }
  }
})}

inventory. json

{"all":{"hosts":{"server":{"ansible_connection":"winrm","ansible_host":"343434","ansible_password":"abc","ansible_port":5986,"ansible_user":"testadmin","ansible_winrm_server_cert_validation":"ignore","ansible_winrm_transport":"ntlm"}}}}

inventory.yaml

all:
  hosts:
    server:
    - ansible_connection: winrm
      ansible_host: 40.88.14.205
      ansible_password: abc
      ansible_port: 5986
      ansible_user: testadmin
      ansible_winrm_server_cert_validation: ignore
      ansible_winrm_transport: ntlm

Правильно ли мой подход, как удалить "-" из кода, или я что-то делаю неправильно.

Отредактировано:

Я конвертирую json файл в файл yaml, используя bash в трубопровод.

python -c 'import sys, yaml, json; yaml.safe_dump(json.load(sys.stdin), sys.stdout, default_flow_style=False)' < inventory.json > inventory.yaml

1 Ответ

7 голосов
/ 22 июня 2020

Как указано в комментарии @ ydaetskcoR , ваш инвентарь неверен, потому что вам нужно, чтобы список хостов был непосредственным дочерним элементом атрибута hosts.

Обратите внимание, что список, который вы получите, создается с помощью скобок [], генерирующих кортежи, около for в вашем шаблоне Terraform, в отличие от использования скобок {} для создания объектов.

Тип скобок вокруг выражения for определяет, какой тип результата оно дает. В приведенном выше примере используются [ и ], что создает кортеж. Если вместо этого используются { и }, результатом является объект, и необходимо предоставить два результирующих выражения, разделенных символом =>.

https://www.terraform.io/docs/configuration/expressions.html#for -выражения

Если ваша структура должна выглядеть как all > server1, server2, server3

Тогда ваш инвентарь должен быть

all:
  hosts:
    server1:
      ansible_host: 10.0.0.2
      ansible_port: 5986
    server2:
      ansible_host: 10.0.0.3
      ansible_port: 5986
    server3:
      ansible_host: 10.0.0.4
      ansible_port: 5986

Это подход для шаблона Terraform, создающего это:

${yamlencode({
  "all": {
    "hosts": {
      for i, ip in vm-ip:
        "server${i+1}" => {
          "ansible_host": "${ip}",
          "ansible_port": 5986
        }
    }
  }
})}

Что дает этот действительный inventory.yaml :

"all":
  "hosts":
    "server1":
      "ansible_host": "10.0.0.2"
      "ansible_port": 5986
    "server2":
      "ansible_host": "10.0.0.3"
      "ansible_port": 5986
    "server3":
      "ansible_host": "10.0.0.4"
      "ansible_port": 5986

С другой стороны, если вам нужна структура типа all > server > server1, server2, server3

, тогда вы должны сделать server дочерним элементом all и использовать запись children в ваш инвентарь:

all:
  children:
    server:
      hosts:
        server1:
          ansible_host: 10.0.0.2
          ansible_port: 5986
        server2:
          ansible_host: 10.0.0.3
          ansible_port: 5986
        server3:
          ansible_host: 10.0.0.4
          ansible_port: 5986

Для этого соответствующий шаблон Terraform будет

${yamlencode({
  "all": {
    "children": {
      "server": {
        "hosts": {
          for i, ip in vm-ip:
            "server${i+1}" => {
              "ansible_host": "${ip}",
              "ansible_port": 5986
            }
        }
      }
    }
  }
})}

, который производит это inventory.yaml :

"all":
  "children":
    "server":
      "hosts":
        "server1":
          "ansible_host": "10.0.0.2"
          "ansible_port": 5986
        "server2":
          "ansible_host": "10.0.0.3"
          "ansible_port": 5986
        "server3":
          "ansible_host": "10.0.0.4"
          "ansible_port": 5986

Примечание: для всех приведенных выше примеров я использую файл terraform test.tf ниже:

resource "local_file" "AnsibleInventory" {
  content = templatefile("inventory.tpl", {
    vm-ip = ["10.0.0.2","10.0.0.3","10.0.0.4"],
  })
  filename = "inventory.yaml"
}
...