Ansible: повторение и объединение элементов инвентаря с переменными

Это напрямую связано со следующим вопросом ссылки и ответом от larsks, который я пробовал, но он не работает: "как пройти через инвентарь и присвоить значение в недоступном "

Я пытался сделать то же самое, и я попытался переименовать 2 виртуальные машины, управляемые Ansible, но при попытке запустить Playbook (ansible-playbook -i hosts test_iterate_win.yml -vvv) я получаю такие же ошибки, как следующая, я бы сказал, что он буквально берет по имени '< strong> System.Object[] 'вместо, например, wCloud2:

failed: [oldVM2] (item=[u'oldVM2', u'wCloud2']) => {
    "ansible_loop_var": "item", 
    "changed": false, 
    "item": [
        "oldVM2", 
        "wCloud2"
    ], 
    "msg": "Failed to rename computer to 'System.Object[]': Skip computer 'oldVM2' with new name 'System.Object[]' because the new name is not valid. The new computer name entered is not properly formatted. Standard names may contain letters (a-z, A-Z), numbers (0-9), and hyphens (-), but no spaces or periods (.). The name may not consist entirely of digits, and may not be longer than 63 characters.", 
    "old_name": "oldVM2", 
    "reboot_required": false
}

В моем файле инвентаря:

[windows]
oldVM1 ansible_host=192.168.122.6
oldVM2 ansible_host=192.168.122.139

Моя книга:

---
- hosts: windows
  gather_facts: false
  vars:
    hostnames:
      - wCloud1
      - wCloud2
  tasks:
    - name: change hostname
      win_hostname:
        name: "{{ item }}"
      loop: "{{ groups.windows|zip(hostnames)|list }}"

Что я делаю не так?


person xCovelus    schedule 18.09.2019    source источник


Ответы (1)


TL;DR;

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

Ваша задача может быть легко решена, просто используя переменные хоста в вашем инвентаре:

[windows]
oldVM1 ansible_host=192.168.122.6 newName=wCloud1
oldVM2 ansible_host=192.168.122.139 newName=wCloud2

Тогда ваш playbook так же прост, как:

---
- hosts: windows
  gather_facts: false

  tasks:
    - name: change hostname
      win_hostname:
        name: "{{ newName }}"

Я бы сказал, что причина, по которой ваша попытка не сработала, на самом деле связана с некоторым неправильным представлением о задачах, выполняемых на нескольких хостах с помощью Ansible.

А именно, когда у Ansible есть задача (или набор задач) для запуска на нескольких хостах, необходимо определить одну и только одну задачу.

На основе указанной задачи, когда хосты инвентаризации фактически представляют собой группу хостов, задача будет выполняться на host 1, затем на host 2, ... до host n, прежде чем она перейдет к выполнению следующей задачи (если есть).

Замечание: тем не менее, не принимайте это как должное, были известные проблемы, когда Ansible не следовал порядку определения хостов в инвентаре (см .: https://github.com/ansible/ansible/issues/34861), так что на самом деле это может оказаться host 2, host n, host 1.

Рассмотрим эту пьесу с указанным выше инвентарем:

---
- hosts: windows
  gather_facts: false

  tasks:
    - name: change hostname
      debug:
        msg: '{{ newName }}'

    - name: another task
      debug:
        msg: 'some example'

Результатом будет

$ansible-playbook test.yml

PLAY [windows] *****************************************************************

TASK [change hostname] *********************************************************
ok: [oldVM1] => {
    "msg": "wCloud1"
}
ok: [oldVM2] => {
    "msg": "wCloud2"
}

TASK [another task] ************************************************************
ok: [oldVM1] => {
    "msg": "some example"
}
ok: [oldVM2] => {
    "msg": "some example"
}

PLAY RECAP *********************************************************************
oldVM1                     : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
oldVM2                     : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

Здесь вы можете ясно видеть, что первая задача (named, change hostname) обрабатывается на всех хостах, прежде чем Ansible сможет перейти к другим задачам в игре.


И на самом деле ваша System.Object[] ошибка означает, что вы пытаетесь передать объект (а именно список) в name модуля win_hostname, который каким-то образом пытается преобразовать его как строку и терпит неудачу, потому что вот список, который содержит ваша item переменная :

[
    "oldVM1",
    "wCloud1"
]
person β.εηοιτ.βε    schedule 18.09.2019
comment
это кажется блестящим решением и хорошей философией (пусть будет проще), большое спасибо. Я скоро протестирую его и выберу ваш ответ в качестве принятого решения. - person xCovelus; 19.09.2019