Ansible как установить_факт с условием или переменной базой при условии

#ansible

#ansible

Вопрос:

У меня есть 3 типа серверов: dev, qa и prod. Мне нужно отправлять файлы в домашние каталоги, относящиеся к конкретному серверу, т.е:

Домашний каталог Dev: /dev/home

Домашний каталог QA:/qa/home

Домашний каталог PROD: /prod/home

Я установил var как логическое значение для определения типа сервера и думаю об использовании set_fact с условием для назначения домашних каталогов для серверов. Моя пьеса выглядит так:

 ---
- hosts: localhost
  var:
    dev: "{{ True if <hostname matches dev> | else False }}"
    qa: "{{ True if <hostname matches qa> | else False }}"
    prod: "{{ True if <hostname matches prod> | else False }}"

  tasks:
  - set_facts:
      home_dir: "{{'/dev/home/' if dev | '/qa/home' if qa | default('prod')}}"
  

Однако затем я запустил playbook, я получал сообщение об ошибке «имя ожидаемого токена шаблона», получил строку> Кто-нибудь знает, что я сделал не так? Спасибо!

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

1. похоже, вы обрабатываете так, else как если бы это был фильтр, а не ключевое слово в jinja2; вы также, вероятно, выиграете от использования групп в вашем инвентаре (что также позволяет сопоставлять шаблон имени хоста) в сочетании с group_vars тем, чтобы избежать необходимости выполнять две задачи в вашем playbook, которые легко устанавливаются как факты перед playbookдаже выполняется

Ответ №1:

Используйте тест соответствия. Например, сборник пьес

 shell> cat pb.yml
- hosts: localhost
  vars:
    dev_pattern: '^dev_. $'
    qa_pattern: '^qa_. $'
    prod_pattern: '^prod_. $'
    dev: "{{ hostname is match(dev_pattern) }}"
    qa: "{{ hostname is match(qa_pattern) }}"
    prod: "{{ hostname is match(prod_pattern) }}"
  tasks:
    - set_fact:
        home_dir: /prod/home
    - set_fact:
        home_dir: /dev/home
      when: dev|bool
    - set_fact:
        home_dir: /qa/home
      when: qa|bool
    - debug:
        var: home_dir
  

дает (сокращенный)

 shell> ansible-playbook pb.yml -e hostname=dev_007

  home_dir: /dev/home
  

Примечания:

  • Переменная prod не используется, потому что /prod/home используется по умолчанию.
  • prod/home сначала присваивается home_dir, потому что это значение по умолчанию. Следующие задачи могут условно перезаписывать home_dirs .
  • Без заданной переменной hostname произойдет сбой playbook.

Более простым решением, которое дает тот же результат, является создание словаря ‘pattern: home_dir’. Например

 - hosts: localhost
  vars:
    home_dirs:
      dev_: /dev/home
      qa_: /qa/home
      prod_: /prod/home
  tasks:
    - set_fact:
        home_dir: "{{ home_dirs|
                      dict2items|
                      selectattr('key', 'in' , hostname)|
                      map(attribute='value')|
                      list|
                      first|default('/prod/home') }}"
    - debug:
        var: home_dir
  

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

1. Спасибо! Первый сработал. Я еще не пробовал второй.

Ответ №2:

Добавление альтернативного метода для достижения этой цели. Это своего рода расширяет group_vars предложение, данное @mdaniel в его комментарии.

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

Ниже приведен упрощенный пример, пожалуйста, перейдите по ссылке выше для получения дополнительных опций.

Рассмотрим файл инвентаризации /home/user/ansible/hosts :

 [dev]
srv01.dev.example
srv02.dev.example

[qa]
srv01.qa.example
srv02.qa.example

[prod]
srv01.prod.example
srv02.prod.example
  

Используя group_vars :

Тогда у вас могут быть group_var файлы ниже /home/user/ansible/group_vars/ (соответствующие имена групп инвентаря):

 dev.yml
qa.yml
prod.yml
  

В dev.yml :

 home_dir: "/dev/home"
  

В qa.yml :

 home_dir: "/qa/home"
  

В prod.yml :

 home_dir: "/prod/home"
  

Используя host_vars :

Или у вас могут быть переменные, специфичные для узлов в host_vars каталоге /home/user/ansible/host_vars/ :

 srv01.dev.example.yml
srv01.prod.example.yml
# and so on
  

В srv01.dev.example.yml :

 home_dir: "/dev/home"
  

В srv01.prod.example.yml :

 home_dir: "/prod/home"
  

Эти переменные будут выбираться в зависимости от того, на каких хостах вы запускаете playbook, например, приведенный ниже playbook:

 ---
- hosts: dev

  tasks:
  - debug:
      var: home_dir
    # will be "/dev/home"

- hosts: prod

  tasks:
  - debug:
      var: home_dir
    # will be "/prod/home"

- hosts: srv01.dev.example

  tasks:
  - debug:
      var: home_dir
    # will be "/dev/home"

- hosts: srv01.prod.example

  tasks:
  - debug:
      var: home_dir
    # will be "/prod/home"
  

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

1. Спасибо! У меня в инвентаре установлена группа хостов. Однако, когда я запускаю playbook, я запускаю его только на одном хосте, когда пользователь вводит данные из Jenkins. Итак, мне нужно что-то добавить в playbook, чтобы определить, к какой группе принадлежит хост.

2. Если вы перейдете по ссылке в моем ответе, вы увидите, что вы также можете установить переменные, специфичные для хоста, для group. Используйте host_vars каталоги для их определения. Я обновлю ответ.