admin管理员组

文章数量:1122846

Here is my sample YAML file input.yaml.

name: "My name"
surname: "Bar"
address:
  city: "My city"
  street: "My street"
  number: 1

Using Ansible, how to add address.pincode with value 12345 to input.yaml? How to delete address.number from input.yaml?

For deleting, I tried this, it works for name, but not working for address.city

 - name: "Removing key"
      debug:
        msg: "{{ my_data | ansible.utils.remove_keys(target=['name']) }}"

Here is my sample YAML file input.yaml.

name: "My name"
surname: "Bar"
address:
  city: "My city"
  street: "My street"
  number: 1

Using Ansible, how to add address.pincode with value 12345 to input.yaml? How to delete address.number from input.yaml?

For deleting, I tried this, it works for name, but not working for address.city

 - name: "Removing key"
      debug:
        msg: "{{ my_data | ansible.utils.remove_keys(target=['name']) }}"
Share Improve this question edited yesterday Arjun asked yesterday ArjunArjun 6,73110 gold badges34 silver badges36 bronze badges 2
  • learnxinyminutes.com/yaml is a good start for getting a basic idea about how YAML works – m90 Commented yesterday
  • 4 What have you tried ? If you really don't know where to start, see remove_keys, combine and to_nice_yaml – Zeitounator Commented yesterday
Add a comment  | 

2 Answers 2

Reset to default 1

A simple framework would be putting the files into a directory. For example,

shell> tree addr_book
addr_book
├── bar_baz.yml
└── foo_bar.yml
shell> cat addr_book/foo_bar.yml 
name: Foo
surname: Bar
address:
  city: My city
  street: My street
  number: 1
shell> cat addr_book/bar_baz.yml 
name: Bar
surname: Baz
address:
  city: My city
  street: My street
  number: 43

Read the files and create an address book

    - include_vars:
        file: "{{ item }}"
        name: "{{ item | basename | splitext | first }}-addr_book"
      with_fileglob: addr_book/*.yml

    - set_fact:
        addr_book: "{{ dict(keys|zip(vals)) }}"
      vars:
        keys: "{{ q('varnames', '-addr_book') | map('split', '-') | map('first') }}"
        vals: "{{ q('vars', *q('varnames', '-addr_book')) }}"

gives

  addr_book:
    bar_baz:
      address:
        city: My city
        number: 43
        street: My street
      name: Bar
      surname: Baz
    foo_bar:
      address:
        city: My city
        number: 1
        pincode: 12345
        street: My street
      name: Foo
      surname: Bar

Create a dictionary with the item(s) you want to update. For example,

    addr_book_update:
      foo_bar:
        address:
          pincode: 12345

and test the update

    - debug:
        msg: |
          {{ item }}
          {{ addr_book[item] |
             combine(addr_book_update[item], recursive=true) |
             to_nice_yaml }}
      loop: "{{ addr_book_update.keys() }}"

gives

  msg: |-
    foo_bar
    address:
        city: My city
        number: 1
        pincode: 12345
        street: My street
    name: Foo
    surname: Bar

Update the file(s)

    - copy:
        dest: "addr_book/{{ item }}.yml"
        content: |
          {{ addr_book[item] |
             combine(addr_book_update[item], recursive=true) |
             to_nice_yaml }}
      loop: "{{ addr_book_update.keys() }}"

gives

shell> cat addr_book/foo_bar.yml 
address:
    city: My city
    number: 1
    pincode: 12345
    street: My street
name: Foo
surname: Bar

Notes:

  • This does not remove attributes. Update the declaration of vals if you want to remove the attributes.

  • Or, you can remove the attribute number from the file(s)

    - replace:
        path: "{{ item }}"
        regexp: '    number:.*'
      with_fileglob: addr_book/*.yml
  • If you don't need the complete address book read only the files you want to update
    - include_vars:
        file: "addr_book/{{ item }}.yml"
        name: "{{ item }}-addr_book"
      loop: "{{ addr_book_update.keys() }}"

Example of a complete playbook for testing

- hosts: localhost

  vars:

    addr_book_update:
      foo_bar:
        address:
          pincode: 12345

  tasks:

    - include_vars:
        file: "{{ item }}"
        name: "{{ item | basename | splitext | first }}-addr_book"
      with_fileglob: addr_book/*.yml

    - set_fact:
        addr_book: "{{ dict(keys|zip(vals)) }}"
      vars:
        keys: "{{ q('varnames', '-addr_book') | map('split', '-') | map('first') }}"
        vals: "{{ q('vars', *q('varnames', '-addr_book')) }}"

    - debug:
        var: addr_book

    - debug:
        msg: |
          {{ item }}
          {{ addr_book[item] |
             combine(addr_book_update[item], recursive=true) |
             to_nice_yaml }}
      loop: "{{ addr_book_update.keys() }}"

    - copy:
        dest: "addr_book/{{ item }}.yml"
        content: |
          {{ addr_book[item] |
             combine(addr_book_update[item], recursive=true) |
             to_nice_yaml }}
      loop: "{{ addr_book_update.keys() }}"

Based on the given comment and the there referenced Ansible documentation, a minimal example

---
- hosts: localhost
  become: false
  gather_facts: false

  vars:

    input: "{{ lookup('file', 'input.yaml') | from_yaml }}"

  tasks:

  - debug:
      msg: "{{ input }}"

  - name: Add ZIP code
    set_fact:
      updated: "{{ input | combine( { 'address': { 'zip': 'MA 01914' } }, recursive=True ) }}"

  - debug:
      msg: "{{ updated |  ansible.utils.remove_keys(target=['number']) }}"

will provide the requested behavior

TASK [debug] *********************************
ok: [localhost] =>
  msg:
    address:
      city: Arkham
      number: 1
      street: Main Street
    name: J.
    surname: Doe

TASK [Add ZIP code] **************************
ok: [localhost]

TASK [debug] ************
ok: [localhost] =>
  msg:
    address:
      city: Arkham
      street: Main Street
      zip: MA 01914
    name: J.
    surname: Doe

The updated data structure can become written out via copy module and in example content: "{{ updated | ansible.utils.remove_keys(target=['number']) }}".

本文标签: ansibleHow to add todelete from YAML fileStack Overflow