Krish
Krish

Reputation: 21

ansible - regexp for netplan config nameserver address

I'm trying to edit the netcfg.yaml and update the nameserver address:

currently it has this:

version: 2
  renderer: networkd
  ethernets:
    enp0s3:
     dhcp4: no
     addresses: [192.168.1.222/24]
     gateway4: 192.168.1.1
     nameservers:
       addresses: [8.8.8.8,8.8.4.4]

I was able to edit all the lines with lineinfile, except the last line in the above: addresses: [8.8.8.8.,8.8.4.4]

I tried this:

regexp: ' addresses: [[0-9]{1}[.][0-9]{1}[.][0-9]{1}[.][0-9]{1}]'

Ansible playbook doesn't show any error, but it's not identifying it to modify the values.

Upvotes: 1

Views: 229

Answers (3)

Vladimir Botka
Vladimir Botka

Reputation: 68189

It's very risky to update IPs in such files by regex. There are two attributes addresses in this simple example. It would be more practical to read the YAML dictionary, update it and write it back.

Declare what you want to update. For example, update addresses of the nameservers in each interface from ethernets

  ethernets_update:
    nameservers:
      addresses: [127.0.0.53, 8.8.8.8, 8.8.4.4]

Given the (fixed) file for testing

shell> cat /tmp/netcfg.yaml 
network:
  version: 2
  renderer: networkd
  ethernets:
    enp0s3:
      dhcp4: no
      addresses: [192.168.1.222/24]
      gateway4: 192.168.1.1
      nameservers:
        addresses: [8.8.8.8,8.8.4.4]

Declare the variable

  netcfg: "{{ netcfg_yaml.content|b64decode|from_yaml }}"

and read the file

    - slurp:
        src: /tmp/netcfg.yaml
      register: netcfg_yaml

gives

  netcfg:
    network:
      ethernets:
        enp0s3:
          addresses: [192.168.1.222/24]
          dhcp4: false
          gateway4: 192.168.1.1
          nameservers:
            addresses: [8.8.8.8, 8.8.4.4]
      renderer: networkd
      version: 2

Update the dictionary

  ethernets: "{{ dict(netcfg.network.ethernets.keys()|
                      zip(netcfg.network.ethernets.values()|
                          product([ethernets_update])|map('combine'))) }}"
  netcfg_update: "{{ [netcfg, {'network': {'ethernets': ethernets}}]|
                     combine(recursive=true) }}"

gives

  netcfg_update:
    network:
      ethernets:
        enp0s3:
          addresses: [192.168.1.222/24]
          dhcp4: false
          gateway4: 192.168.1.1
          nameservers:
            addresses: [127.0.0.53, 8.8.8.8, 8.8.4.4]
      renderer: networkd
      version: 2

Write the file

    - copy:
        dest: /tmp/netcfg.yaml
        content: |
          {{ netcfg_update|to_yaml }}

gives

shell> cat /tmp/netcfg.yaml 
network:
  ethernets:
    enp0s3:
      addresses: [192.168.1.222/24]
      dhcp4: false
      gateway4: 192.168.1.1
      nameservers:
        addresses: [127.0.0.53, 8.8.8.8, 8.8.4.4]
  renderer: networkd
  version: 2

Example of a complete playbook for testing

- hosts: localhost

  vars:

    ethernets_update:
      nameservers:
        addresses: [127.0.0.53, 8.8.8.8, 8.8.4.4]

    netcfg: "{{ netcfg_yaml.content|b64decode|from_yaml }}"
    ethernets: "{{ dict(netcfg.network.ethernets|dict2items|map(attribute='key')|
                        zip(netcfg.network.ethernets|dict2items|map(attribute='value')|
                            product([ethernets_update])|map('combine'))) }}"

    netcfg_update: "{{ [netcfg, {'network': {'ethernets': ethernets}}]|
                       combine(recursive=true) }}"

  tasks:

    - slurp:
        src: /tmp/netcfg.yaml
      register: netcfg_yaml
    - debug:
        var: netcfg

    - debug:
        var: ethernets
    - debug:
        var: netcfg_update|to_yaml

    - copy:
        dest: /tmp/netcfg.yaml
        content: |
          {{ netcfg_update|to_yaml }}

Upvotes: 0

The fourth bird
The fourth bird

Reputation: 163577

You could write the pattern escaping the first \[ and optionally repeat matching , followed by the digits and dots.

If you want to match 1 or more digits, you can use \d+

\baddresses: \[\d\.\d\.\d\.\d(?:,\d\.\d\.\d\.\d)*]

Explanation

  • \baddresses: \[ Match the word addresses followed by : [
  • \d\.\d\.\d\.\d Match 4 times a digit with a dot in between
  • (?:,\d\.\d\.\d\.\d)* Optionally repeat matching a , and the previous pattern
  • ] Match literally

See a regex demo.

Upvotes: 0

Trung Duong
Trung Duong

Reputation: 3475

Your pattern is missed comma , between address, you could try this pattern:

addresses: \[(\d\.\d\.\d\.\d\,?)*\]

See demo here.

Upvotes: 0

Related Questions