为多个目标主机创建 ansible 清单

bhu*_*der 6 json yaml ansible terraform

我使用 terraform 创建资源,然后使用模板文件方法以 yaml 语言创建 ansible 库存。我正在 terraform 中创建多个虚拟机,并在单个管道中使用 ansible 配置它们。

我遇到的问题是 yaml 文件使用 - 对于在 ansible playbook 中给出错误的列表

输出.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"
}
Run Code Online (Sandbox Code Playgroud)

库存.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"
        }
      ]
    }
  }
})}
Run Code Online (Sandbox Code Playgroud)

库存.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"}}}}
Run Code Online (Sandbox Code Playgroud)

库存.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
Run Code Online (Sandbox Code Playgroud)

我的方法是如何从代码中删除“-”还是我做错了什么。

编辑:

我正在管道中使用 bash 将 json 文件转换为 yaml 文件。

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

β.ε*_*.βε 8

正如@ydaetskcoR 的评论所指出,您的库存是错误的,因为您需要将主机列表作为该hosts属性的直接子项。


请注意,您最终得到的列表是通过在 Terraform 模板中使用方括号[]生成元组生成的,for而不是使用方括号{}生成对象。

for表达式周围的括号类型决定了它产生的结果类型。上面的例子使用[and ],它产生一个元组。如果使用{}代替,则结果是一个对象,并且必须提供两个结果表达式,用=>符号分隔。

https://www.terraform.io/docs/configuration/expressions.html#for-expressions


如果你的结构,应该看起来像 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
Run Code Online (Sandbox Code Playgroud)

这是用于生成以下内容的 Terraform 模板的一种方法:

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

这给出了这个有效的inventory.yaml

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

另一方面,如果你想要一个像 all > server > server1, server2, server3

然后,您应该创建server一个子项all并使用您库存中的children条目

"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
Run Code Online (Sandbox Code Playgroud)

对于这个,相应的 Terraform 模板将是

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

其中产生这个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
Run Code Online (Sandbox Code Playgroud)

注意:对于上面的所有示例,我使用的是下面的 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"
}
Run Code Online (Sandbox Code Playgroud)