Spec-Zone.ru › Ansible 2.10

Открытие переменных: факты и магические переменные

С помощью Ansible вы можете получить или открыть определённые переменные, содержащие информацию о ваших удалённых системах или об Ansible. Переменные, относящиеся к удалённым системам, называются фактами. С помощью фактов вы можете использовать поведение или состояние одной системы в качестве конфигурации на других системах. Например, вы можете использовать IP-адрес одной системы в качестве значения конфигурации на другой системе. Переменные, относящиеся к Ansible, называются магическими переменными.

  • Факты Ansible

    • Требования к пакетам для сбора фактов
    • Кэширование фактов
    • Отключение фактов
    • Добавление пользовательских фактов

      • facts.d или локальные факты
  • Информация об Ansible: магические переменные

    • Версия Ansible

Факты Ansible

Факты Ansible — это данные, связанные с вашими удалёнными системами, включая операционные системы, IP-адреса, подключённые файловые системы и многое другое. Вы можете получить доступ к этим данным в переменной ansible_facts. По умолчанию вы также можете получить доступ к некоторым фактам Ansible как к переменным верхнего уровня с префиксом ansible_. Вы можете отключить это поведение, используя настройку INJECT_FACTS_AS_VARS. Чтобы увидеть все доступные факты, добавьте эту задачу в плей:

- name: Print all available facts
  ansible.builtin.debug:
    var: ansible_facts

Чтобы увидеть «сырые» данные, собранные в ходе сбора фактов, выполните эту команду в командной строке:

ansible <hostname> -m ansible.builtin.setup

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

{
    "ansible_all_ipv4_addresses": [
        "REDACTED IP ADDRESS"
    ],
    "ansible_all_ipv6_addresses": [
        "REDACTED IPV6 ADDRESS"
    ],
    "ansible_apparmor": {
        "status": "disabled"
    },
    "ansible_architecture": "x86_64",
    "ansible_bios_date": "11/28/2013",
    "ansible_bios_version": "4.1.5",
    "ansible_cmdline": {
        "BOOT_IMAGE": "/boot/vmlinuz-3.10.0-862.14.4.el7.x86_64",
        "console": "ttyS0,115200",
        "no_timer_check": true,
        "nofb": true,
        "nomodeset": true,
        "ro": true,
        "root": "LABEL=cloudimg-rootfs",
        "vga": "normal"
    },
    "ansible_date_time": {
        "date": "2018-10-25",
        "day": "25",
        "epoch": "1540469324",
        "hour": "12",
        "iso8601": "2018-10-25T12:08:44Z",
        "iso8601_basic": "20181025T120844109754",
        "iso8601_basic_short": "20181025T120844",
        "iso8601_micro": "2018-10-25T12:08:44.109968Z",
        "minute": "08",
        "month": "10",
        "second": "44",
        "time": "12:08:44",
        "tz": "UTC",
        "tz_offset": "+0000",
        "weekday": "Thursday",
        "weekday_number": "4",
        "weeknumber": "43",
        "year": "2018"
    },
    "ansible_default_ipv4": {
        "address": "REDACTED",
        "alias": "eth0",
        "broadcast": "REDACTED",
        "gateway": "REDACTED",
        "interface": "eth0",
        "macaddress": "REDACTED",
        "mtu": 1500,
        "netmask": "255.255.255.0",
        "network": "REDACTED",
        "type": "ether"
    },
    "ansible_default_ipv6": {},
    "ansible_device_links": {
        "ids": {},
        "labels": {
            "xvda1": [
                "cloudimg-rootfs"
            ],
            "xvdd": [
                "config-2"
            ]
        },
        "masters": {},
        "uuids": {
            "xvda1": [
                "cac81d61-d0f8-4b47-84aa-b48798239164"
            ],
            "xvdd": [
                "2018-10-25-12-05-57-00"
            ]
        }
    },
    "ansible_devices": {
        "xvda": {
            "holders": [],
            "host": "",
            "links": {
                "ids": [],
                "labels": [],
                "masters": [],
                "uuids": []
            },
            "model": null,
            "partitions": {
                "xvda1": {
                    "holders": [],
                    "links": {
                        "ids": [],
                        "labels": [
                            "cloudimg-rootfs"
                        ],
                        "masters": [],
                        "uuids": [
                            "cac81d61-d0f8-4b47-84aa-b48798239164"
                        ]
                    },
                    "sectors": "83883999",
                    "sectorsize": 512,
                    "size": "40.00 GB",
                    "start": "2048",
                    "uuid": "cac81d61-d0f8-4b47-84aa-b48798239164"
                }
            },
            "removable": "0",
            "rotational": "0",
            "sas_address": null,
            "sas_device_handle": null,
            "scheduler_mode": "deadline",
            "sectors": "83886080",
            "sectorsize": "512",
            "size": "40.00 GB",
            "support_discard": "0",
            "vendor": null,
            "virtual": 1
        },
        "xvdd": {
            "holders": [],
            "host": "",
            "links": {
                "ids": [],
                "labels": [
                    "config-2"
                ],
                "masters": [],
                "uuids": [
                    "2018-10-25-12-05-57-00"
                ]
            },
            "model": null,
            "partitions": {},
            "removable": "0",
            "rotational": "0",
            "sas_address": null,
            "sas_device_handle": null,
            "scheduler_mode": "deadline",
            "sectors": "131072",
            "sectorsize": "512",
            "size": "64.00 MB",
            "support_discard": "0",
            "vendor": null,
            "virtual": 1
        },
        "xvde": {
            "holders": [],
            "host": "",
            "links": {
                "ids": [],
                "labels": [],
                "masters": [],
                "uuids": []
            },
            "model": null,
            "partitions": {
                "xvde1": {
                    "holders": [],
                    "links": {
                        "ids": [],
                        "labels": [],
                        "masters": [],
                        "uuids": []
                    },
                    "sectors": "167770112",
                    "sectorsize": 512,
                    "size": "80.00 GB",
                    "start": "2048",
                    "uuid": null
                }
            },
            "removable": "0",
            "rotational": "0",
            "sas_address": null,
            "sas_device_handle": null,
            "scheduler_mode": "deadline",
            "sectors": "167772160",
            "sectorsize": "512",
            "size": "80.00 GB",
            "support_discard": "0",
            "vendor": null,
            "virtual": 1
        }
    },
    "ansible_distribution": "CentOS",
    "ansible_distribution_file_parsed": true,
    "ansible_distribution_file_path": "/etc/redhat-release",
    "ansible_distribution_file_variety": "RedHat",
    "ansible_distribution_major_version": "7",
    "ansible_distribution_release": "Core",
    "ansible_distribution_version": "7.5.1804",
    "ansible_dns": {
        "nameservers": [
            "127.0.0.1"
        ]
    },
    "ansible_domain": "",
    "ansible_effective_group_id": 1000,
    "ansible_effective_user_id": 1000,
    "ansible_env": {
        "HOME": "/home/zuul",
        "LANG": "en_US.UTF-8",
        "LESSOPEN": "||/usr/bin/lesspipe.sh %s",
        "LOGNAME": "zuul",
        "MAIL": "/var/mail/zuul",
        "PATH": "/usr/local/bin:/usr/bin",
        "PWD": "/home/zuul",
        "SELINUX_LEVEL_REQUESTED": "",
        "SELINUX_ROLE_REQUESTED": "",
        "SELINUX_USE_CURRENT_RANGE": "",
        "SHELL": "/bin/bash",
        "SHLVL": "2",
        "SSH_CLIENT": "REDACTED 55672 22",
        "SSH_CONNECTION": "REDACTED 55672 REDACTED 22",
        "USER": "zuul",
        "XDG_RUNTIME_DIR": "/run/user/1000",
        "XDG_SESSION_ID": "1",
        "_": "/usr/bin/python2"
    },
    "ansible_eth0": {
        "active": true,
        "device": "eth0",
        "ipv4": {
            "address": "REDACTED",
            "broadcast": "REDACTED",
            "netmask": "255.255.255.0",
            "network": "REDACTED"
        },
        "ipv6": [
            {
                "address": "REDACTED",
                "prefix": "64",
                "scope": "link"
            }
        ],
        "macaddress": "REDACTED",
        "module": "xen_netfront",
        "mtu": 1500,
        "pciid": "vif-0",
        "promisc": false,
        "type": "ether"
    },
    "ansible_eth1": {
        "active": true,
        "device": "eth1",
        "ipv4": {
            "address": "REDACTED",
            "broadcast": "REDACTED",
            "netmask": "255.255.224.0",
            "network": "REDACTED"
        },
        "ipv6": [
            {
                "address": "REDACTED",
                "prefix": "64",
                "scope": "link"
            }
        ],
        "macaddress": "REDACTED",
        "module": "xen_netfront",
        "mtu": 1500,
        "pciid": "vif-1",
        "promisc": false,
        "type": "ether"
    },
    "ansible_fips": false,
    "ansible_form_factor": "Other",
    "ansible_fqdn": "centos-7-rax-dfw-0003427354",
    "ansible_hostname": "centos-7-rax-dfw-0003427354",
    "ansible_interfaces": [
        "lo",
        "eth1",
        "eth0"
    ],
    "ansible_is_chroot": false,
    "ansible_kernel": "3.10.0-862.14.4.el7.x86_64",
    "ansible_lo": {
        "active": true,
        "device": "lo",
        "ipv4": {
            "address": "127.0.0.1",
            "broadcast": "host",
            "netmask": "255.0.0.0",
            "network": "127.0.0.0"
        },
        "ipv6": [
            {
                "address": "::1",
                "prefix": "128",
                "scope": "host"
            }
        ],
        "mtu": 65536,
        "promisc": false,
        "type": "loopback"
    },
    "ansible_local": {},
    "ansible_lsb": {
        "codename": "Core",
        "description": "CentOS Linux release 7.5.1804 (Core)",
        "id": "CentOS",
        "major_release": "7",
        "release": "7.5.1804"
    },
    "ansible_machine": "x86_64",
    "ansible_machine_id": "2db133253c984c82aef2fafcce6f2bed",
    "ansible_memfree_mb": 7709,
    "ansible_memory_mb": {
        "nocache": {
            "free": 7804,
            "used": 173
        },
        "real": {
            "free": 7709,
            "total": 7977,
            "used": 268
        },
        "swap": {
            "cached": 0,
            "free": 0,
            "total": 0,
            "used": 0
        }
    },
    "ansible_memtotal_mb": 7977,
    "ansible_mounts": [
        {
            "block_available": 7220998,
            "block_size": 4096,
            "block_total": 9817227,
            "block_used": 2596229,
            "device": "/dev/xvda1",
            "fstype": "ext4",
            "inode_available": 10052341,
            "inode_total": 10419200,
            "inode_used": 366859,
            "mount": "/",
            "options": "rw,seclabel,relatime,data=ordered",
            "size_available": 29577207808,
            "size_total": 40211361792,
            "uuid": "cac81d61-d0f8-4b47-84aa-b48798239164"
        },
        {
            "block_available": 0,
            "block_size": 2048,
            "block_total": 252,
            "block_used": 252,
            "device": "/dev/xvdd",
            "fstype": "iso9660",
            "inode_available": 0,
            "inode_total": 0,
            "inode_used": 0,
            "mount": "/mnt/config",
            "options": "ro,relatime,mode=0700",
            "size_available": 0,
            "size_total": 516096,
            "uuid": "2018-10-25-12-05-57-00"
        }
    ],
    "ansible_nodename": "centos-7-rax-dfw-0003427354",
    "ansible_os_family": "RedHat",
    "ansible_pkg_mgr": "yum",
    "ansible_processor": [
        "0",
        "GenuineIntel",
        "Intel(R) Xeon(R) CPU E5-2670 0 @ 2.60GHz",
        "1",
        "GenuineIntel",
        "Intel(R) Xeon(R) CPU E5-2670 0 @ 2.60GHz",
        "2",
        "GenuineIntel",
        "Intel(R) Xeon(R) CPU E5-2670 0 @ 2.60GHz",
        "3",
        "GenuineIntel",
        "Intel(R) Xeon(R) CPU E5-2670 0 @ 2.60GHz",
        "4",
        "GenuineIntel",
        "Intel(R) Xeon(R) CPU E5-2670 0 @ 2.60GHz",
        "5",
        "GenuineIntel",
        "Intel(R) Xeon(R) CPU E5-2670 0 @ 2.60GHz",
        "6",
        "GenuineIntel",
        "Intel(R) Xeon(R) CPU E5-2670 0 @ 2.60GHz",
        "7",
        "GenuineIntel",
        "Intel(R) Xeon(R) CPU E5-2670 0 @ 2.60GHz"
    ],
    "ansible_processor_cores": 8,
    "ansible_processor_count": 8,
    "ansible_processor_nproc": 8,
    "ansible_processor_threads_per_core": 1,
    "ansible_processor_vcpus": 8,
    "ansible_product_name": "HVM domU",
    "ansible_product_serial": "REDACTED",
    "ansible_product_uuid": "REDACTED",
    "ansible_product_version": "4.1.5",
    "ansible_python": {
        "executable": "/usr/bin/python2",
        "has_sslcontext": true,
        "type": "CPython",
        "version": {
            "major": 2,
            "micro": 5,
            "minor": 7,
            "releaselevel": "final",
            "serial": 0
        },
        "version_info": [
            2,
            7,
            5,
            "final",
            0
        ]
    },
    "ansible_python_version": "2.7.5",
    "ansible_real_group_id": 1000,
    "ansible_real_user_id": 1000,
    "ansible_selinux": {
        "config_mode": "enforcing",
        "mode": "enforcing",
        "policyvers": 31,
        "status": "enabled",
        "type": "targeted"
    },
    "ansible_selinux_python_present": true,
    "ansible_service_mgr": "systemd",
    "ansible_ssh_host_key_ecdsa_public": "REDACTED KEY VALUE",
    "ansible_ssh_host_key_ed25519_public": "REDACTED KEY VALUE",
    "ansible_ssh_host_key_rsa_public": "REDACTED KEY VALUE",
    "ansible_swapfree_mb": 0,
    "ansible_swaptotal_mb": 0,
    "ansible_system": "Linux",
    "ansible_system_capabilities": [
        ""
    ],
    "ansible_system_capabilities_enforced": "True",
    "ansible_system_vendor": "Xen",
    "ansible_uptime_seconds": 151,
    "ansible_user_dir": "/home/zuul",
    "ansible_user_gecos": "",
    "ansible_user_gid": 1000,
    "ansible_user_id": "zuul",
    "ansible_user_shell": "/bin/bash",
    "ansible_user_uid": 1000,
    "ansible_userspace_architecture": "x86_64",
    "ansible_userspace_bits": "64",
    "ansible_virtualization_role": "guest",
    "ansible_virtualization_type": "xen",
    "gather_subset": [
        "all"
    ],
    "module_setup": true
}

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

{{ ansible_facts['devices']['xvda']['model'] }}

Чтобы обратиться к имени хоста системы:

{{ ansible_facts['nodename'] }}

Вы можете использовать факты в условных операторах (см. Условные операторы), а также в шаблонах. Вы также можете использовать факты для создания динамических групп хостов, соответствующих определённым критериям, см. документацию модуля group_by для получения подробной информации.

Требования к пакетам для сбора фактов

В некоторых дистрибутивах вы можете увидеть отсутствующие значения фактов или факты, установленные по умолчанию, потому что пакеты, поддерживающие сбор этих фактов, не установлены по умолчанию. Вы можете установить необходимые пакеты на своих удалённых хостах с помощью системного менеджера пакетов. Известные зависимости включают:

  • Сбор фактов сети Linux — зависит от двоичного файла ip, обычно включённого в пакет iproute2.

Кэширование фактов

Как и зарегистрированные переменные, факты по умолчанию хранятся в памяти. Однако, в отличие от зарегистрированных переменных, факты могут быть собраны независимо и кэшированы для повторного использования. С кэшированными фактами вы можете ссылаться на факты одной системы при конфигурации второй системы, даже если Ansible выполнит текущий плей на второй системе раньше. Например:

{{ hostvars['asdf.example.com']['ansible_facts']['os_family'] }}

Кэширование контролируется плагинами кэша. По умолчанию Ansible использует плагин кэша памяти, который хранит факты в памяти на время выполнения текущего плейбука. Чтобы сохранить факты Ansible для повторного использования, выберите другой плагин кэша. Подробнее см. Плагины кэша.

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

Отключение фактов

По умолчанию Ansible собирает факты в начале каждого плей. Если вам не нужно собирать факты (например, если вы знаете всё о своих системах централизованно), вы можете отключить сбор фактов на уровне плей, чтобы повысить масштабируемость. Отключение фактов может особенно улучшить производительность в режиме push с очень большим количеством систем или если вы используете Ansible на экспериментальных платформах. Чтобы отключить сбор фактов:

- hosts: whatever
  gather_facts: no

Добавление пользовательских фактов

Модуль setup в Ansible автоматически обнаруживает стандартный набор фактов о каждом хосте. Если вы хотите добавить пользовательские значения в свои факты, вы можете написать пользовательский модуль фактов, установить временные факты с помощью задачи ansible.builtin.set_fact или предоставить постоянные пользовательские факты с помощью каталога facts.d.

facts.d или локальные факты

Новое в версии 1.3.

Вы можете добавить статические пользовательские факты, добавив статические файлы в facts.d, или добавить динамические факты, добавив исполняемые скрипты в facts.d. Например, вы можете добавить список всех пользователей на хосте в свои факты, создав и запустив скрипт в facts.d.

Чтобы использовать facts.d, создайте каталог /etc/ansible/facts.d на удалённом хосте или хостах. Если вы предпочитаете другой каталог, создайте его и укажите его с помощью ключевого слова плей fact_path. Добавьте файлы в каталог для предоставления ваших пользовательских фактов. Все имена файлов должны оканчиваться на .fact. Файлы могут быть JSON, INI или исполняемыми файлами, возвращающими JSON.

Чтобы добавить статические факты, просто добавьте файл с расширением .facts. Например, создайте /etc/ansible/facts.d/preferences.fact с этим содержимым:

[general]
asdf=1
bar=2

В следующий раз, когда будет выполняться сбор фактов, ваши факты будут содержать переменную hash fact с именем general с asdf и bar в качестве членов. Чтобы проверить это, выполните следующее:

ansible <hostname> -m ansible.builtin.setup -a "filter=ansible_local"

И вы увидите добавленный вами пользовательский факт:

"ansible_local": {
        "preferences": {
            "general": {
                "asdf" : "1",
                "bar"  : "2"
            }
        }
 }

Пространство имён ansible_local отделяет пользовательские факты, созданные facts.d, от системных фактов или переменных, определённых в другом месте в плейбуке, поэтому переменные не будут перезаписывать друг друга. Вы можете получить доступ к этому пользовательскому факту в шаблоне или плейбуке как:

{{ ansible_local['preferences']['general']['asdf'] }}

Примечание

Ключевая часть в парах ключ=значение будет преобразована в нижний регистр внутри переменной ansible_local. Используя пример выше, если ini-файл содержал XYZ=3 в секции [general], то вы должны ожидать доступа к нему как к {{ ansible_local['preferences']['general']['xyz'] }}, а не к {{ ansible_local['preferences']['general']['XYZ'] }}. Это потому, что Ansible использует ConfigParser Python, который пропускает все имена параметров через метод optionxform, а по умолчанию этот метод преобразует имена параметров в нижний регистр.

Вы также можете использовать facts.d для выполнения скрипта на удалённом хосте, генерируя динамические пользовательские факты в пространство имён ansible_local. Например, вы можете сгенерировать список всех существующих на удалённом хосте пользователей как факт о данном хосте. Чтобы сгенерировать динамические пользовательские факты с помощью facts.d:

  1. Напишите и протестируйте скрипт для генерации JSON-данных, которые вам нужны.
  2. Сохраните скрипт в каталоге facts.d.
  3. Убедитесь, что ваш скрипт имеет расширение .fact.
  4. Убедитесь, что ваш скрипт выполним пользователем подключения Ansible.
  5. Соберите факты, чтобы выполнить скрипт и добавить JSON-вывод в ansible_local.

По умолчанию сбор фактов выполняется один раз в начале каждого плей. Если вы создаёте пользовательский факт с помощью facts.d в плейбуке, он будет доступен в следующем плей, который собирает факты. Если вы хотите использовать его в том же плей, где вы его создали, вы должны явно повторно запустить модуль setup. Например:

- hosts: webservers
  tasks:

    - name: Create directory for ansible custom facts
      ansible.builtin.file:
        state: directory
        recurse: yes
        path: /etc/ansible/facts.d

    - name: Install custom ipmi fact
      ansible.builtin.copy:
        src: ipmi.fact
        dest: /etc/ansible/facts.d

    - name: Re-read facts after adding custom fact
      ansible.builtin.setup:
        filter: ansible_local

Если вы часто используете эту схему, пользовательский модуль фактов будет более эффективен, чем facts.d.

Информация об Ansible: магические переменные

Вы можете получить доступ к информации об операциях Ansible, включая используемую версию Python, хосты и группы в инвентаре и каталоги для плейбуков и ролей, используя «магические» переменные. Как и переменные подключения, магические переменные являются Специальными переменными. Имена магических переменных зарезервированы — не устанавливайте переменные с этими именами. Переменная environment также зарезервирована.

Наиболее часто используемые магические переменные — это hostvars, groups, group_names, и inventory_hostname. С помощью hostvars, вы можете получить доступ к переменным, определённым для любого хоста в плей, в любой момент в плейбуке. Вы также можете получить доступ к фактам Ansible, используя переменную hostvars, но только после того, как вы собрали (или кэшировали) факты.

Если вы хотите настроить сервер базы данных, используя значение «факта» с другого узла или значение переменной инвентаризации, назначенной другому узлу, вы можете использовать hostvars в шаблоне или в строке действия:

{{ hostvars['test.example.com']['ansible_facts']['distribution'] }}

С помощью groups, списка всех групп (и хостов) в инвентаре, вы можете перечислить все хосты в группе. Например:

{% for host in groups['app_servers'] %}
   # something that applies to all app servers.
{% endfor %}

Вы можете использовать groups и hostvars вместе, чтобы найти все IP-адреса в группе.

{% for host in groups['app_servers'] %}
   {{ hostvars[host]['ansible_facts']['eth0']['ipv4']['address'] }}
{% endfor %}

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

С помощью group_names, списка (массива) всех групп, в которых находится текущий хост, вы можете создавать шаблонизированные файлы, которые различаются в зависимости от членства в группе (или роли) хоста:

{% if 'webserver' in group_names %}
   # some part of a configuration file that only applies to webservers
{% endif %}

Вы можете использовать магическую переменную inventory_hostname, имя хоста, как он настроен в вашем инвентаре, в качестве альтернативы ansible_hostname, когда сбор фактов отключён. Если у вас длинный FQDN, вы можете использовать inventory_hostname_short, которая содержит часть до первой точки, без остальной части домена.

Другие полезные магические переменные относятся к текущему плей или плейбуку. Эти переменные могут быть полезны для заполнения шаблонов несколькими именами хостов или для вставки списка в правила балансировщика нагрузки.

ansible_play_hosts — это список всех узлов, по-прежнему активных в текущей игре.

ansible_play_batch — это список имен хостов, которые находятся в области действия текущей «группы» игры.

Размер группы определяется serial, а если не задан, он эквивалентен всей игре (что делает его таким же, как ansible_play_hosts).

ansible_playbook_python — это путь к исполняемому файлу python, используемому для вызова командной строки Ansible.

inventory_dir — это путь к каталогу, содержащему файл инвентаризации хостов Ansible.

inventory_file — это путь и имя файла, указывающие на файл инвентаризации хостов Ansible.

playbook_dir содержит базовый каталог playbook.

role_path содержит путь к текущему роли и работает только внутри роли.

ansible_check_mode — это булево значение, установленное в True, если вы запускаете Ansible с --check.

Версия Ansible

Новая в версии 1.8.

Для адаптации поведения playbook к различным версиям Ansible можно использовать переменную ansible_version, которая имеет следующую структуру:

"ansible_version": {
    "full": "2.10.1",
    "major": 2,
    "minor": 10,
    "revision": 1,
    "string": "2.10.1"
}

© 2012–2018 Michael DeHaan
© 2018–2019 Red Hat, Inc.
Licensed under the GNU General Public License version 3.
https://docs.ansible.com/ansible/2.10/user_guide/playbooks_vars_facts.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API