Page MenuHomeVyOS Platform

Running a "delete" in ansible will prevent subsequent "set" from being applied
Open, NormalPublicBUG

Description

I am currently working on updating our firewall groups using ansible.

When deleting a group before adding it again (e.g. to make sure no extra addresses from previous runs are present). It will delete the group but not add it again.

Example playbook:

---
- name: Test vyos idempotency
  hosts: dev-fw
  tasks:
    - name: Create firewall group
      vyos.vyos.vyos_config:
        lines:
          - set firewall group network-group PUBLIC_DNS network '1.1.1.1/32'
          - set firewall group network-group PUBLIC_DNS network '8.8.8.8/32'
          - set firewall group network-group PUBLIC_DNS network '9.9.9.9/32'

    - name: Delete and Create firewall group again
      vyos.vyos.vyos_config:
        lines:
          - delete firewall group network-group PUBLIC_DNS
          - set firewall group network-group PUBLIC_DNS network '1.1.1.1/32'
          - set firewall group network-group PUBLIC_DNS network '8.8.8.8/32'
          - set firewall group network-group PUBLIC_DNS network '9.9.9.9/32'

It will return the following on the second step

TASK [Delete and Create firewall group again] *****************************************************************************************************************************************************************************************************************************************************************************
task path: /home/nicolas.berens/repos/gs-networking/test.yml:12
[firewall group network-group]
- PUBLIC_DNS {
-     network "1.1.1.1/32"
-     network "8.8.8.8/32"
-     network "9.9.9.9/32"
- }


[edit]
[WARNING]: To ensure idempotency and correct diff the input configuration lines should be similar to how they appear if present in the running configuration on device
changed: [fw-dev] => {
    "changed": true,
    "commands": [
        "delete firewall group network-group PUBLIC_DNS"
    ],
    "diff": {
        "prepared": "[firewall group network-group]\n- PUBLIC_DNS {\n-     network \"1.1.1.1/32\"\n-     network \"8.8.8.8/32\"\n-     network \"9.9.9.9/32\"\n- }\n\n\n[edit]"
    },
    "filtered": [],
    "invocation": {
        "module_args": {
            "backup": false,
            "backup_options": null,
            "comment": "configured by vyos_config",
            "config": null,
            "lines": [
                "delete firewall group network-group PUBLIC_DNS",
                "set firewall group network-group PUBLIC_DNS network '1.1.1.1/32'",
                "set firewall group network-group PUBLIC_DNS network '8.8.8.8/32'",
                "set firewall group network-group PUBLIC_DNS network '9.9.9.9/32'"
            ],
            "match": "line",
            "save": false,
            "src": null
        }
    }
}

Running the commands manually will result in the expected behaviour:

nicolas.berens@fw-dev# set firewall group network-group PUBLIC_DNS network '1.1.1.1/32'
[edit]
nicolas.berens@fw-dev# set firewall group network-group PUBLIC_DNS network '8.8.8.8/32'
[edit]
nicolas.berens@fw-dev# set firewall group network-group PUBLIC_DNS network '9.9.9.9/32'
[edit]
nicolas.berens@fw-dev# commit
[edit]
nicolas.berens@fw-dev# delete firewall group network-group PUBLIC_DNS
[edit]
nicolas.berens@fw-dev# set firewall group network-group PUBLIC_DNS network '1.1.1.1/32'
[edit]
nicolas.berens@fw-dev# set firewall group network-group PUBLIC_DNS network '8.8.8.8/32'
[edit]
nicolas.berens@fw-dev# set firewall group network-group PUBLIC_DNS network '9.9.9.9/32'
[edit]
nicolas.berens@fw-dev# show | compare
No changes between working and active configurations.

[edit]

Doing the same using command scripting: https://docs.vyos.io/en/1.4/automation/command-scripting.html

Also works as expected.

Details

Version
1.4
Is it a breaking change?
Unspecified (possibly destroys the router)
Issue type
Bug (incorrect behavior)

Event Timeline

Viacheslav triaged this task as Normal priority.Jul 9 2025, 8:26 PM

Hi @nicolasberens!
I believe the module is configured to match line by line by default and only work out on deltas in the config.
So if in the active Ansible session, the module does not sense changes after 'delete' (because there are none as yet, since the command is not applied) - At start, the module retrieves the current configuration and process it, then issues a set of commands.
Either having two separate tasks to delete first, then to set works, or the example below also works.

- name: Delete and Create firewall group again
  vyos.vyos.vyos_config:
    lines:
      - delete firewall group network-group PUBLIC_DNS
      - set firewall group network-group PUBLIC_DNS network '1.1.1.1/32'
      - set firewall group network-group PUBLIC_DNS network '8.8.8.8/32'
      - set firewall group network-group PUBLIC_DNS network '9.9.9.9/32'
    match: none

That said, there is vyos.vyos.vyos_firewall_global (https://docs.ansible.com/ansible/latest/collections/vyos/vyos/vyos_firewall_global_module.html#parameter-config/group/network_group) that might be of help

Given this, do we want to consider this as a bug really? Thanks

Hi,
thanks for the reply.

2 Separate tasks would not be not a good solution for 2 reasons:

  • its not idempotent, it would always create a change even if the config does not change
  • it can lead to the rules being deleted and not applied (e.g. if there is a network issue between the first and second step)

match: none has a similar issue, it does not allow you to see if the rules have changed (since the task will always create a change).

I haven't had a look at the firewall_global_module, but will test if it is possible to create the desired outcome with it.

As an example (and the reason why i try to solve this issue the way i am doing it right now), the junos module (https://docs.ansible.com/ansible/latest/collections/junipernetworks/junos/junos_config_module.html#ansible-collections-junipernetworks-junos-junos-config-module) support this exact behaviour. So it was easy to adapt this for our vyos firewalls.

Looking at vyos.vyos.vyos_firewall_global, i have a few issues with it:

  • it seems like --diff is not supported, at least it never outputs what it changes, only that something changes
  • it is not possible to only replace a single network-group, you have to completely define the firewall and use state: replaced (merged does not remove anything, only adds more rules).

As an example (and the reason why i try to solve this issue the way i am doing it right now), the junos module (https://docs.ansible.com/ansible/latest/collections/junipernetworks/junos/junos_config_module.html#ansible-collections-junipernetworks-junos-junos-config-module) support this exact behaviour. So it was easy to adapt this for our vyos firewalls.

Thanks - and Why not? I will check and revert

@nicholaschaffeee Hi!
Are you able to describe your use case above?

Now, why I am asking:
I checked both JunOS and CISCO IoS implementations in hopes to get some ideas. The former uses RPC/XML to refresh the config set; the latter makes use of running and startup config, thus offloading work to the router itself (correct me if I am wrong here). Both are not exactly the case of what we can do here.

Hence was the questions - if you only want to replace the firewall configuration with the same set, then you may want to set match=none or have the 'delete' as a separate task (common thing with network_cli).
If you put some different set (e.g. if you changed the attribute of the set clause) in the second task, I believe that the module would include the delete and your set command (since it differs from the running config)

I can try and add some "smartness" to vyos_config, so it would not ignore the lines to be deleted, but rather force them.
Alternatively (IMO betetr) we invest time in enhancing vyos_firewall_global for more accurate firewall list processing (replace rules, etc)

Thoughts?

@evgmol did you want to tag me?

Our usecase is, that we generate the Firewall rules based on a few external sources, therefore we do not always know how the firewall config looks like (so a whole replace of the complete config is currently not possible).

Having the ability to scope vyos_firewall_global (e.g. replace this group but ignore the rest) might help here.

At the same time we also want to use (and are already doing it on other systems) the Ansible as a drift control, e.g. we apply the playbook in --check and --diff mode on a regular basis to see if the configuration on the system differs from what we expect it to be.
In this case, having it change every time would defeat the purpose.

Deleting a group and then applying it again would also lead to a small service interruption.

That is clear now, thanks @nicolasberens
(Sorry, I must have misspelled your username)

In fact, I was testing vyos_config logic to treat delete slightly separately, for example, as in Cisco IOS Ansible modules.
I will post the progress here

So, I tried a few approaches here - in particular, I coded logic to preserve 'set' commands if they are in running config and there is a corresponding 'delete' clause, to we do see 'delete' and 'set' commands in the config to compare.
Despite this, the Ansible connnection.get_diff does not work with this well, as it tends to remove 'delete' from the resultant set as not making sense (it kind of being over-smart here)

So, if we want to support the OP's use case in vyos_config, when will need to generate the diff ourselves in the code, not relying on Ansible, or implement and use match="exact'

@nicolasberens WRT this

Deleting a group and then applying it again would also lead to a small service interruption.

but you do want to delete the groups and then set them a new, don't you? We are looking at

commands = ['delete firewall group network-group PUBLIC_DNS', 'set firewall group network-group PUBLIC_DNS network 1.1.1.1/32', 'set firewall group network-group PUBLIC_DNS network 8.8.8.8/32', 'set firewall group network-group PUBLIC_DNS network 9.9.9.9/32']

and this is exactly what will happen.
What I think would be appropriate, is a "smart" processing of the firewall elements/ rules if we want to replace, override, merge it via firewall_global?

Attn: @gaige

Yes, i want to delete and recreate it. But it needs to be in the same step, not in 2 separate ones.
With 2 Seperate ones, you delete the group, commit it, then recreate and commit it again.
In a single step, you delete the group, recreate it and then commit. That way the group itself will always exist.

@nicolasberens hi!

I raised a PR for vyos_config, so it detects there is a 're-provision' use case - e.g. if wanted config includes delete and then set for the same, it will include all the commands in the single transaction.
That said, we were disputing a bit internally about this use case and the solution, since vyos_firewall_global 'replaced' works perfectly fine - in particular, it removes all the content from the group that is not listed in the playbook, and re-builds the group by new content from the playbook (when it is needed). That works as designed and suggests no outage related to the deleting the network-group, that vyos_config can still exhibit.

I am happy to elaborate, and I suggest you look into this, review and advise.
Thank you

On the other note, I added support of 'diff' to vyos_firewall_config