ansible-opnsense icon indicating copy to clipboard operation
ansible-opnsense copied to clipboard

object uuids in vars

Open FlorianHeigl opened this issue 2 years ago • 3 comments

Hi,

could you add your idea to the readme how to handle the uuid generation?

i.e. alias objects need a uuid as you show in your examples

opn_alias:
  - uuid: 6e319c0e-f016-11e9-b3fd-1002b50d9337
    settings:
      - key: name
        value: private
      - key: type
        value: network
      - key: content
        list:
          - 10.0.0.0/8
          - 172.16.0.0/12
          - 192.168.0.0/16

do you manually generate one with each object you add to the vars or did you use a more magic approach? kinda wondering what's best. I read there's a | to_uuid filter in ansible. I could also imagine autogenerating the group_vars file for generic aliases like ports_smtp_outbound.

what's your favorite poison on this?

p.s.: the module is insanely good work, one of the best / most advanced things I've seen done in like 10 years of ansible use.

FlorianHeigl avatar Jan 12 '22 13:01 FlorianHeigl

for our setup we generate the required vars for the ansible opnsense role using a jinja2 template and for the uuid field I use: uuid: {{ data.uuid | default(name | to_uuid) }} This allows you to define a uuid if required, otherwise generate one from the name. (!this assumes you will not change the name ever!) For example: our alias definition

  PRIVATE_NETWORKS:
    type: network
    content:
      - 10.0.0.0/8
      - 172.16.0.0/12
      - 192.168.0.0/16

will be converted to

  - uuid: b9ca4f72-ab35-5c48-8460-d71a7ef50184
    settings:
      - key: name
        value: PRIVATE_NETWORKS
      - key: type
        value: network
      - key: content
        list:
          - 10.0.0.0/8
          - 172.16.0.0/12
          - 192.168.0.0/16
      - key: enabled
        value: 1
      - key: description
        value: "global opn alias PRIVATE_NETWORKS"

zerwes avatar Jan 12 '22 14:01 zerwes

Very nice - thank you for taking the time to answer! I'll walk myself through it :-)

FlorianHeigl avatar Jan 12 '22 14:01 FlorianHeigl

In case it is of interest, here a excerpt from the jinja2 template we use. It allows us to define VARs in different scopes in our simplified notation and then merge them reformatted and use them for the playbook. But: ! it is exactly what one should not do : it puts logic and complexity in a template ! But to be honest, it was the only way I found ...

{% if opn_alias is defined or opn_alias_from_vlans is defined or define_other_zones_as_alias|default(true) or local_opn_alias is defined or (global_opn_alias is defined and use_global_opn_alias|default(true)) -%}
opn_alias:
{% endif -%} {# if opn_alias is defined or ... #}
{% if opn_alias is defined -%}
# original var opn_alias
{# as the ansible var merging is restricted to hashes, we need to merge the defined list in opn_alias w/ the newly generated elements #}
{{ opn_alias | to_nice_yaml(indent=2) | indent(2, true) }}
{% endif -%}
{# ... deleted some very internal voodoo #}
# global_opn_alias
{% for name, data in global_opn_alias.items() | list %}
  - uuid: {{ data.uuid | default(name | to_uuid) }}
    settings:
      - key: name
        value: {{ name }}
      - key: type
        value: {{ data.type }}
{% if data.content is defined %}
      - key: content
{% if data.content is string %}
        value: "{{ data.content }}"
{% elif data.content is iterable %}
        list:
{% for le in data.content %}
          - {{ le }}
{% endfor %}
{% endif %}{# if data.content is string #}{% endif %}{# if data.content is defined #}
      - key: enabled
        value: 1
      - key: description
        value: "{{ data.description | default('global opn alias ' + name ) }}"
{% for k in opn_alias_optional_fields -%} {# additional optional stuff #}
{% if k in data %}
      - key: {{ k }}
        value: {{ data[k] }}
{% endif %}
{% endfor %}{# for k in opn_alias_optional_fields #}
{% endfor -%} {# for name, data in global_opn_alias.items() | list #}
{% endif -%} {# if global_opn_alias is defined and use_global_opn_alias|default(true) #}
{% if local_opn_alias is defined -%}
# local_opn_alias
{% for name, data in local_opn_alias.items() | list %}
  - uuid: {{ data.uuid | default(name | to_uuid) }}
    settings:
      - key: name
        value: {{ name }}
      - key: type
        value: {{ data.type }}
{% if data.content is defined %}
      - key: content
{% if data.content is string %}
        value: "{{ data.content }}"
{% elif data.content is iterable %}
        list:
{% for le in data.content %}
          - {{ le }}
{% endfor %}
{% endif %}{# if data.content is string #}
{% endif %}{# if data.content is defined #}
      - key: enabled
        value: 1
      - key: description
        value: "{{ data.description | default('global opn alias ' + name ) }}"
{% for k in opn_alias_optional_fields -%} {# additional optional stuff #}
{% if k in data %}
      - key: {{ k }}
        value: {{ data[k] }}
{% endif %}
{% endfor %}{# for k in opn_alias_optional_fields #}
{% endfor -%} {# for name, data in local_opn_alias.items() | list #}
{% endif -%} {# if local_opn_alias is defined #}

excerpt of the playbook that prepares the VARs before applying the ansible-opnsense playbook:

- name: Generate volatile config
  delegate_to: localhost
  template:
    src: opnsense.vars.j2
    dest: "{{ tmp_var_cfg_file }}"
    mode: 0600

- name: Include volatile config
  include_vars:
    file: "{{ tmp_var_cfg_file }}"

zerwes avatar Jan 12 '22 14:01 zerwes