Назад | Перейти на главную страницу

Ansible - несколько операторов с одинаковыми переменными

Я новичок в Ansible, поэтому могу упустить что-то очевидное. У меня есть playbook, делающий следующее:

- name: Create real users
  user: name="{{item.user_name}}" comment="{{item.user_description}}" home="/home/{{item.user_name}}" shell="/bin/bash" uid="{{item.user_id}}"
  with_items:
    - { user_name: "user1", user_description: "user 1", user_id: "2000" }
    - { user_name: "user2", user_description: "user 2",  user_id: "2001" }

- name: Copy SSH keys
  copy:
    src: "keys/{{ item.user_name }}.key"
    dest: "/home/{{ item.user_name }}/.ssh/authorized_keys"
    owner: "{{ item.user_name }}"
    group: "{{ item.user_name }}"
    mode: 0600
  with_items:
     - { user_name: "user1", user_description: "user 1", user_id: "2000" }
     - { user_name: "user2", user_description: "user 2",  user_id: "2001" }

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

Это возможно? С чего мне начать искать?

Та .... Том

Я новичок в ансибле

Я перечисляю здесь несколько различных вариантов, чтобы вы могли узнать немного больше, чем просто идеальное решение (вариант 5).

Вариант 1. Используйте якоря и ссылки YAML

Это совершенно не связано с Ansible, но поскольку файлы находятся в формате YAML, вы можете сделать что-то вроде этого:

- name: Create real users
  user: name="{{item.user_name}}" comment="{{item.user_description}}" home="/home/{{item.user_name}}" shell="/bin/bash" uid="{{item.user_id}}"
  with_items: &my_items
    - user_name: user1
      user_description: user 1
      user_id: 2000
    - user_name: user2
      user_description: user 2
      user_id: 2001

- name: Copy SSH keys
  copy:
    src: "keys/{{ item.user_name }}.key"
    dest: "/home/{{ item.user_name }}/.ssh/authorized_keys"
    owner: "{{ item.user_name }}"
    group: "{{ item.user_name }}"
    mode: 0600
  with_items: *my_items

Вариант 2: переменные в блоках

Блоки - это функция, представленная в Ansible 2. Вы можете определять переменные для блоков и использовать их в содержащихся задачах.

- vars:
    userlist:
      - user_name: user1
        user_description: user 1
        user_id: 2000
      - user_name: user2
        user_description: user 2
        user_id: 2001
  block:
    - name: Create real users
      user: name="{{item.user_name}}" comment="{{item.user_description}}" home="/home/{{item.user_name}}" shell="/bin/bash" uid="{{item.user_id}}"
      with_items: "{{ userlist }}"

    - name: Copy SSH keys
      copy:
        src: "keys/{{ item.user_name }}.key"
        dest: "/home/{{ item.user_name }}/.ssh/authorized_keys"
        owner: "{{ item.user_name }}"
        group: "{{ item.user_name }}"
        mode: 0600
      with_items: "{{ userlist }}"

Вариант 3. Примените петлю к include задача и ваши задачи во включенном файле

- include: other_file.yml
  with_items:
    - user_name: user1
      user_description: user 1
      user_id: 2000
    - user_name: user2
      user_description: user 2
      user_id: 2001

Во включенном файле вы сможете получить доступ к элементу и его свойствам, например item.user_name, как будто он у вас уже был:

- name: Create real users
  user: name="{{item.user_name}}" comment="{{item.user_description}}" home="/home/{{item.user_name}}" shell="/bin/bash" uid="{{item.user_id}}"

- name: Copy SSH keys
  copy:
    src: "keys/{{ item.user_name }}.key"
    dest: "/home/{{ item.user_name }}/.ssh/authorized_keys"
    owner: "{{ item.user_name }}"
    group: "{{ item.user_name }}"
    mode: 0600

Вариант 4: выделите факт, содержащий ваш список пользователей, в отдельную задачу

- set_fact:
    userlist:
      - user_name: user1
        user_description: user 1
        user_id: 2000
      - user_name: user2
        user_description: user 2
        user_id: 2001

- name: Create real users
  user: name="{{item.user_name}}" comment="{{item.user_description}}" home="/home/{{item.user_name}}" shell="/bin/bash" uid="{{item.user_id}}"
  with_items: "{{ userlist }}"

- name: Copy SSH keys
  copy:
    src: "keys/{{ item.user_name }}.key"
    dest: "/home/{{ item.user_name }}/.ssh/authorized_keys"
    owner: "{{ item.user_name }}"
    group: "{{ item.user_name }}"
    mode: 0600
  with_items: "{{ userlist }}"

Вариант 5: используйте group_vars

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

Создать файл group_vars/foo относительно вашей playbook с контентом:

userlist:
  - user_name: user1
    user_description: user 1
    user_id: 2000
  - user_name: user2
    user_description: user 2
    user_id: 2001

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

- name: Create real users
  user: name="{{item.user_name}}" comment="{{item.user_description}}" home="/home/{{item.user_name}}" shell="/bin/bash" uid="{{item.user_id}}"
  with_items: "{{ userlist }}"

- name: Copy SSH keys
  copy:
    src: "keys/{{ item.user_name }}.key"
    dest: "/home/{{ item.user_name }}/.ssh/authorized_keys"
    owner: "{{ item.user_name }}"
    group: "{{ item.user_name }}"
    mode: 0600
  with_items: "{{ userlist }}"

Если у вас нет групп или вы не хотите ограничивать их определенными группами, вы можете сохранить файл vars как group_vars/all где все хосты имеют доступ.

Спасибо за такой исчерпывающий ответ. В конце концов я обнаружил, что могу использовать with_dict вот так:

1) Создайте файл vars.yml (в том же каталоге)

---
usersxxx:
    user1:
      description: User1
      user_id: 2001
      shell: /bin/bash
      ...other options here
    user2:
      description: User2        
      user_id: 2002
      shell: /bin/bash
      ...other options here

2) Создайте новую пьесу:

---
- hosts: home
  vars_files:
    - vars.yml

  become: yes

  tasks: 
    - name: Create real users
      user: name="{{item.key}}" comment="{{item.value.description}}" home="/home/{{item.key}}" uid="{{item.value.user_id}}"
      with_dict: "{{usersxxx}}"

Похоже, работает отлично.

Я только изменил его на usersxxx, чтобы убедиться, что я не попал ни в какие примитивы python / ansible.

Надеюсь, это поможет кому-то другому!