передайте список/массив строк из моего сценария bash в сценарий ansible

#bash #ansible

Вопрос:

Я пытаюсь передать список/массив строк из моего сценария bash в мой сценарий ansible:

Отрывок из сценария bash:

 configureChrony() {
  ntpServer="initVal"
  ntpServers=()
  while ! [[ -z "$ntpServer" ]]; do
    read -e -p "Please input the ip address or domain name of the TP server you wish to add: " ntpServer
    if ! [[ -z "$ntpServer" ]]; then
      ntpServers =($ntpServer)
    fi
  done

  ansible-playbook -i localhost, test.yml --extra-vars="ntp_list = $ntpServers"

}
 

тест.yml

 ---


- name: "This is a test"
  hosts: all
  gather_facts: no
  tasks:

    - name: print variable - with_items
      debug:
        msg: "{{ item.name }}"
      with_items:
      - "{{ ntp_list }}"
 

При тестировании сценария bash я получаю эту ошибку:

 Which timekeeping service would you like to use [ntp/chrony]: chrony
Please input the ip address or domain name of the TP server you wish to add: Test1
Please input the ip address or domain name of the TP server you wish to add: Test2
Please input the ip address or domain name of the TP server you wish to add:

PLAY [This is a test] ****************************************************************************************************************************************

TASK [print variable - with_items] ***************************************************************************************************************************
fatal: [localhost]: FAILED! => {"msg": "'ntp_list' is undefined"}

PLAY RECAP ***************************************************************************************************************************************************
localhost                  : ok=0    changed=0    unreachable=0    failed=1    skipped=0    rescued=0    ignored=0
 

Проблема в том, как я передаю список/массив из сценария bash в сценарий ansible, когда они оба запускаются с учетом требуемых данных.

Желаемый вывод — для каждого элемента списка, который будет выведен на экран.

 Test1
Test2
 

Любая помощь будет признательна.

Комментарии:

1. ntpServers представляет собой массив. Используйте ${ntpServers[@]} , чтобы развернуть его в виде списка слов.

2. Итак, ansible-playbook -i локальный хост, test.yml —extra-vars=»ntp_list = ${ntpServers [@]}»? @Рено Пакале

3. Да, именно так должны быть расширены массивы bash .

4. @RenaudPacalet Теперь у меня есть эта ошибка: ansible-playbook: error: unrecognized arguments: Test2

5. Если бы вы вводили ansible команду вручную без параметров bash, как бы она выглядела (особенно --extra-vars="ntp_list = ..." часть)? Пожалуйста, не отвечайте в комментарии, добавьте это к своему вопросу. И проверьте, что это работает до этого. Тогда мы сможем предложить bash синтаксис, который делает именно это, не зная, как ansible это работает.

Ответ №1:

Прямой ответ

Вы действительно не можете передать массив bash в виде списка внутри дополнительного var в ansible. Это возможно, но для этого потребуется выполнить цикл над массивом bash и преобразовать его в формат для анализа json, который вы вводите в дополнительный var.

Самый простой способ IMO-передать объединение всех элементов массива внутри строки, которую вы позже разделите в учебнике.

Использование формы ${somevar[@]} здесь не сработает, так как каждый элемент массива bash в конечном итоге будет проанализирован в качестве нового аргумента для вашей команды ansible. Вам придется использовать вместо ${somevar[*]} этого . Вам также нужно правильно процитировать дополнительный var, чтобы и bash, и ansible могли успешно его проанализировать. Правильный вызов команды в вашем сценарии-это:

 ansible-playbook test.yml --extra-vars "ntp_list_raw='${ntpServers[*]}'"
 

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

 ---
- name: "This is a test"
  hosts: localhost
  gather_facts: no

  vars:
    ntp_list: "{{ ntp_list_raw.split(' ') }}"

  tasks:

    - name: Print split variable items
      debug:
        var: item
      loop: "{{ ntp_list }}"
 

А теперь ввод значений и вызов playbook из вашего сценария дает:

 Please input the ip address or domain name of the TP server you wish to add: toto
Please input the ip address or domain name of the TP server you wish to add: pipo
Please input the ip address or domain name of the TP server you wish to add: bingo
Please input the ip address or domain name of the TP server you wish to add: 

PLAY [This is a test] *********************************************************************

TASK [Print split variable items] *********************************************************************
ok: [localhost] => (item=toto) => {
    "ansible_loop_var": "item",
    "item": "toto"
}
ok: [localhost] => (item=pipo) => {
    "ansible_loop_var": "item",
    "item": "pipo"
}
ok: [localhost] => (item=bingo) => {
    "ansible_loop_var": "item",
    "item": "bingo"
}

PLAY RECAP *********************************************************************
localhost                  : ok=1    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0 
 

Идем дальше

Если ваша единственная цель-запросить ваши серверы ntp в интерактивном режиме, вы можете сделать все вышеперечисленное непосредственно в своем учебнике, используя vars_prompt

 ---
- name: "This is a test"
  hosts: localhost
  gather_facts: no

  vars_prompt:
    - name: ntp_list_raw
      prompt: "Please enter ntp servers separated by a comma without spaces"
      private: no

  vars:
    ntp_list: "{{ ntp_list_raw.split(',') }}"

  tasks:

    - name: Print split variable
      debug:
        var: item
      loop: "{{ ntp_list }}"
 

что дает:

 $ ansible-playbook test.yaml 
Please enter ntp servers separated by a comma without spaces []: toto,pipo,bingo

PLAY [This is a test] *********************************************************************

TASK [Print split variable] *********************************************************************
ok: [localhost] => (item=toto) => {
    "ansible_loop_var": "item",
    "item": "toto"
}
ok: [localhost] => (item=pipo) => {
    "ansible_loop_var": "item",
    "item": "pipo"
}
ok: [localhost] => (item=bingo) => {
    "ansible_loop_var": "item",
    "item": "bingo"
}

PLAY RECAP *********************************************************************
localhost                  : ok=1    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
 

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

 $ ansible-playbook test.yaml -e ntp_list_raw=toto,pipo,bingo

PLAY [This is a test] *********************************************************************

TASK [Print split variable] *********************************************************************
ok: [localhost] => (item=toto) => {
    "ansible_loop_var": "item",
    "item": "toto"
}
ok: [localhost] => (item=pipo) => {
    "ansible_loop_var": "item",
    "item": "pipo"
}
ok: [localhost] => (item=bingo) => {
    "ansible_loop_var": "item",
    "item": "bingo"
}

PLAY RECAP *********************************************************************
localhost                  : ok=1    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
 

Комментарии:

1. Спасибо, я буду использовать ваше прямое решение, так как оно более понятно для пользователя. Я бы подумал, что это было бы возможно с ansible, но, думаю, нет.