Объект Ansible Jinja2 Loop — Dict не имеет атрибута

#python #ansible #jinja2 #cisco #asa

Вопрос:

Я схожу с ума здесь, но я просто не могу понять, в чем моя проблема! Я пытаюсь заставить ansible создавать своих пользователей в Cisco ASA и использую шаблоны Jinja 2.

У меня есть файл vars хоста, в котором я указываю пользователей (чувствительные данные).:

 users:
  tom:
    sshkey: "xxxx"
    privilegelevel: 15
  dick:
    sshkey: "xxxx"
    privilegelevel: 15
  harry:
    password: "yyyy"
    privilegelevel: 15
 

Мои шаблоны для создания пользователей (users.j2):

 {% if users is defined %}
{% for user, value in users.items() %}
username {{ value }} privilege {{ value.privilegelevel }}
{% endfor %}
{% endif %}
 

и если у них есть ssh-ключ (пользователи-ssh.j2):

 {% if users and 'sshkey' is defined %}
{% for user, value in users.items() %}
username {{ value }} privilege {{ value.privilegelevel }}
username {{ value }} attributes
  ssh authentication publickey {{ value.sshkey }}
{% endfor %}
{% endif %}
 

И последнее, но не менее важное: сборник пьес:

 - name: create users
  asa_config:
    src: templates/users.j2
    provider: "{{ cli }}"
    save: yes
  tags: users

- name: create ssh pubkey auth
  asa_config:
    src: templates/users-ssh.j2
    provider: "{{ cli }}"
    save: yes
  tags: users
 

При запуске playbook файл user.j2 работает нормально, но файл user-ssh.j2 не работает с:

 fatal: [HOSTNAME_HERE]: FAILED! => {"changed": false, "msg": "'dict object' has no attribute 'sshkey'"}
 

При вызове значений dict с:

 - name: Output dict
  debug:
    msg: "User is {{ item.key }} and the ssh key is {{ item.value.sshkey }}"
  loop: "{{ lookup('dict', users) }}"
  tags: users
 

Это дает мне правильные значения:

 ok: [fw01.prd.sc1] => (item={'key': 'tom', 'value': {'sshkey': 'xxxx', 'privilegelevel': 15}}) => {
    "msg": "User is tom and the ssh key is xxxx"
}
ok: [fw01.prd.sc1] => (item={'key': 'dick', 'value': {'sshkey': 'xxxx', 'privilegelevel': 15}}) => {
    "msg": "User is dick and the ssh key is xxxx"
}
 

Может ли кто-нибудь увидеть, где я могу ошибаться с моим шаблоном J2, так как у меня есть несколько вещей, но ничего не получается!

Заранее большое спасибо 🙂

Крис

Ответ №1:

Эта петля…

 {% if users and 'sshkey' is defined %}
{% for user, value in users.items() %}
username {{ value }} privilege {{ value.privilegelevel }}
username {{ value }} attributes
  ssh authentication publickey {{ value.sshkey }}
{% endfor %}
{% endif %}
 

…не проверяет, есть ли у пользователя sshkey атрибут. Выражение if users and 'sshkey' is defined идентично написанию if users , потому что выражение if 'sshkey' is defined всегда будет true 'sshkey' это буквальная строка, а не переменная.

Поскольку цикл выполняется для всех пользователей, он завершается неудачно , когда вы добираетесь harry , потому harry что у него нет sshkey атрибута.

Вам необходимо отфильтровать пользователей по тем, у которых есть sshkey атрибут, например, с помощью циклической фильтрации, как описано в документации:

 {% for user, value in users.items() if value.sshkey is defined %}
username {{ user }} privilege {{ value.privilegelevel }}
username {{ user }} attributes
  ssh authentication publickey {{ value.sshkey }}
{% endfor %}
 

Обратите внимание , что я также заменил username {{ value }} на username {{ user }} , потому что я вполне уверен, что первое было не тем, что вы имели в виду.


Например, этот сборник пьес:

 - hosts: localhost
  gather_facts: false
  vars:
    users:
      tom:
        sshkey: "xxxx"
        privilegelevel: 15
      dick:
        sshkey: "xxxx"
        privilegelevel: 15
      harry:
        password: "yyyy"
        privilegelevel: 15

  tasks:
    - copy:
        dest: users.txt
        content: |
          {% for user, value in users.items() if value.sshkey is defined %}
          username {{ user }} privilege {{ value.privilegelevel }}
          username {{ user }} attributes
            ssh authentication publickey {{ value.sshkey }}
          {% endfor %}
 

Производит в качестве продукции в users.txt :

 username tom privilege 15
username tom attributes
  ssh authentication publickey xxxx
username dick privilege 15
username dick attributes
  ssh authentication publickey xxxx
 

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

1. Это действительно то, что я имел в виду, когда ставил {{ значение }}! Ну, вы бы посмотрели на это, теперь это имеет гораздо больше смысла. Помогает и с несколькими другими учебниками 😀 большое спасибо за этот ларс!