Ansible: объединение dict в определенный элемент списка, вложенный в dict

Я определил основную книгу воспроизведения, которая вызывает другую книгу подготовки через import_playbook.

Книга подготовки возвращает учетные данные для репозитория S3, var в данный момент называется «service_secrets», что является словарем (см. ниже). Этот словарь необходимо добавить в последний элемент product.dependents. Индикатором выбора конкретного элемента списка может быть просто «Source=S3».

---
- name: 'Preparation'
  ansible.builtin.import_playbook: 'playbook_preparation.yml'
  vars:
    product:
      name: 'mssql'
      dependencies:
        - Name: 'SqlServer'
          Source: 'psgallery'
          Type: 'psmodule'
        - Name: 'SqlServerDsc'
          Source: 'psgallery'
          Type: 'dscmodule'
        - Name: 'AWSPowershell.NetCore'
          Source: 'psgallery'
          Type: 'psmodule'
        - Name: 'ComputerManagementDsc'
          Source: 'psgallery'
          Type: 'dscmodule'
        - Name: >-
            {{
              ["mssql", ci.attributes.input_parameters.mssql.version,
              ci.attributes.input_parameters.mssql.edition,
              ci.attributes.input_parameters.mssql.language]
              | join("_")
            }}
          Source: 'S3'
          Type: 'iso'
          Bucket: 'repository'

Новый факт «service_secrets» выглядит примерно так:

        "service_secrets": {
            "Access_key_id": "abc",
            "Access_key_secret": "defghi",
            "Bucket": "repository",
            "Endpoint": "https://s3.abc.com"
        }

Я пытался поэкспериментировать с функцией join(), но мне не удалось поместить service_secrets в последний элемент списка.

    - name: DEBUG
      debug:
        msg: '{{ product | combine({"dependencies": [service_secrets]}, list_merge = "append") }}'
      loop: '{{ product.dependencies }}'
      when: 'item.Source == "S3"'

Это приведет к:

ok: [localhost] => (item = {'Name': 'mssql_2022_standard_en', 'Source': 'S3', 'Type': 'iso', 'Bucket': 'repository'}) => {
    "msg": {
        "dependencies": [
            {
                "Name": "SqlServer",
                "Source": "psgallery",
                "Type": "psmodule"
            },
            {
                "Name": "SqlServerDsc",
                "Source": "psgallery",
                "Type": "dscmodule"
            },
            {
                "Name": "AWSPowershell.NetCore",
                "Source": "psgallery",
                "Type": "psmodule"
            },
            {
                "Name": "ComputerManagementDsc",
                "Source": "psgallery",
                "Type": "dscmodule"
            },
            {
                "Bucket": "repository",
                "Name": "mssql_2022_standard_en",
                "Source": "S3",
                "Type": "iso"
            },
            {
                "Access_key_id": "abc",
                "Access_key_secret": "defgh",
                "Bucket": "repository",
                "Endpoint": "https://s3.abc.com"
            }
        ],
        "name": "mssql"
    }
}

Чтобы было более понятно: последние два элемента списка product.dependents должны быть одним элементом.

Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
0
50
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Есть несколько способов добиться этого, я хотел бы показать вам два разных, поскольку оба имеют свои преимущества и недостатки.

Ваши исходные данные

vars:
  dependencies:
    - Name: 'SqlServer'
      Source: 'psgallery'
      Type: 'psmodule'
    - Name: 'SqlServerDsc'
      Source: 'psgallery'
      Type: 'dscmodule'
    - Name: 'AWSPowershell.NetCore'
      Source: 'psgallery'
      Type: 'psmodule'
    - Name: 'ComputerManagementDsc'
      Source: 'psgallery'
      Type: 'dscmodule'
    - Name: mssql_2022_standard_en
      Source: 'S3'
      Type: 'iso'
      Bucket: 'repository'
    - Name: 'AnotherDependency_notFromS3'
      Source: 'psgallery'
      Type: 'dscmodule'

  service_secrets:
    Access_key_id: abc
    Access_key_secret: defghi
    Bucket: repository
    Endpoint: https://s3.abc.com

Вариант 1 — разделить по Источнику, обогатить и рекомбинировать

Может быть реализовано в одной задаче без необходимости подготовки данных в отдельной задаче. Сначала ваш dependencies список разбивается на элементы Source == 'S3' да или нет.

Разделение работает с помощью функций ignoreattr() или selectattr(). Элементы, атрибут Source == 'S3' которых либо отклонен, либо отфильтрован (выбран).

Для всех элементов, источником которых является S3, добавляются service_secrets. Service_secrets добавляются с помощью map() , при этом объединение(service_secrets) выполняется для каждого элемента в списке.

Два отдельных списка затем снова добавляются вместе.

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

Код задачи

- name: Variant 1 - split by Source, enrich and recombine
  debug:
    msg: "{{ dependencies_not_s3 + dependencies_s3 }}"
  vars:
    dependencies_not_s3: "{{ dependencies | rejectattr('Source', 'eq', 'S3') }}"
    dependencies_s3: "{{ dependencies | selectattr('Source', 'eq', 'S3') | map('combine', service_secrets) }}"

Результат

TASK [Variant 1 - split by Source, enrich and recombine] ************
ok: [localhost] => {
    "msg": [
        {
            "Name": "SqlServer",
            "Source": "psgallery",
            "Type": "psmodule"
        },
        {
            "Name": "SqlServerDsc",
            "Source": "psgallery",
            "Type": "dscmodule"
        },
        {
            "Name": "AWSPowershell.NetCore",
            "Source": "psgallery",
            "Type": "psmodule"
        },
        {
            "Name": "ComputerManagementDsc",
            "Source": "psgallery",
            "Type": "dscmodule"
        },
        {
            "Name": "AnotherDependency_notFromS3",
            "Source": "psgallery",
            "Type": "dscmodule"
        },
        {
            "Access_key_id": "abc",
            "Access_key_secret": "defghi",
            "Bucket": "repository",
            "Endpoint": "https://s3.abc.com",
            "Name": "mssql_2022_standard_en",
            "Source": "S3",
            "Type": "iso"
        }
    ]
}

Вариант 2 — перебор зависимостей

Во втором варианте вы перебираете список dependencies как исходный набор и создаете новый список с помощью модуля set_fact. В зависимости от источника новый элемент сначала дополняется атрибутом service_secrets.

Для каждой записи в списке dependencies требуется шаг итерации задачи, но это гарантирует сохранение исходного порядка сортировки списка dependencies.

Будьте осторожны, если вы делаете это несколько раз для разных списков зависимостей, которые начинаются с пустой новой переменной.

Код задачи

- name: Variant 2 - iterate over dependencies
  set_fact:
    extended_dependencies: "{{ (extended_dependencies | default([])) + [new_item] }}"
  vars:
    new_item: "{{ item | combine(service_secrets) if item.Source == 'S3' else item }}"
  with_items: "{{ dependencies }}"

- name: Print result from Variant 2
  debug:
    var: extended_dependencies

Результат

TASK [Variant 2 - iterate over dependencies] **************************************************************************
ok: [localhost] => (item = {'Name': 'SqlServer', 'Source': 'psgallery', 'Type': 'psmodule'})
ok: [localhost] => (item = {'Name': 'SqlServerDsc', 'Source': 'psgallery', 'Type': 'dscmodule'})
ok: [localhost] => (item = {'Name': 'AWSPowershell.NetCore', 'Source': 'psgallery', 'Type': 'psmodule'})
ok: [localhost] => (item = {'Name': 'ComputerManagementDsc', 'Source': 'psgallery', 'Type': 'dscmodule'})
ok: [localhost] => (item = {'Name': 'mssql_2022_standard_en', 'Source': 'S3', 'Type': 'iso', 'Bucket': 'repository'})
ok: [localhost] => (item = {'Name': 'AnotherDependency_notFromS3', 'Source': 'psgallery', 'Type': 'dscmodule'})

TASK [Print result from Variant 2] ************************************************************************************
ok: [localhost] => {
    "extended_dependencies": [
        {
            "Name": "SqlServer",
            "Source": "psgallery",
            "Type": "psmodule"
        },
        {
            "Name": "SqlServerDsc",
            "Source": "psgallery",
            "Type": "dscmodule"
        },
        {
            "Name": "AWSPowershell.NetCore",
            "Source": "psgallery",
            "Type": "psmodule"
        },
        {
            "Name": "ComputerManagementDsc",
            "Source": "psgallery",
            "Type": "dscmodule"
        },
        {
            "Access_key_id": "abc",
            "Access_key_secret": "defghi",
            "Bucket": "repository",
            "Endpoint": "https://s3.abc.com",
            "Name": "mssql_2022_standard_en",
            "Source": "S3",
            "Type": "iso"
        },
        {
            "Name": "AnotherDependency_notFromS3",
            "Source": "psgallery",
            "Type": "dscmodule"
        }
    ]
}

Другие вопросы по теме