Ansible host configuration with one hash for multiple params

Viewed 52

I am configuring network ports for an app and accordingly firewall rules as followed:

host_vars/hostXX.yaml:

cluster_nodes:
  - map: TheIsland
    user: theisland
    network:
      game_port: 7777
      query_port: 27015
      rcon_port: 27020

iptables_rules:
  - rule:
    chain: INPUT
    interface: enp98s0f0
    protocol: tcp
    destination_port: 27020
    jump: ACCEPT
  - rule:
    chain: INPUT
    interface: enp98s0f0
    protocol: udp
    destination_port: 7777
    jump: ACCEPT
  - rule:
    chain: INPUT
    interface: enp98s0f0
    protocol: udp
    destination_port: 27015
    jump: ACCEPT

What I would like to achieve is, that I want to define a hash with all network ports and then reference to that for the configuration of the application and the firewall:

ark_cluster_ports:
  theisland:
    game_port: 7777
    query_port: 27015
    rcon_port: 27020

cluster_nodes:
  - map: TheIsland
    user: theisland
    network:
      game_port: > reference to ark_cluster_ports.theisland.game_port
      query_port: > reference to ark_cluster_ports.theisland.query_port
      rcon_port: > reference to ark_cluster_ports.theisland.rcon_port

iptables_rules:
  - rule:
    chain: INPUT
    interface: enp98s0f0
    protocol: tcp
    destination_port: reference to ark_cluster_ports.theisland.rcon_port
    jump: ACCEPT
  - rule:
    chain: INPUT
    interface: enp98s0f0
    protocol: udp
    destination_port: reference to ark_cluster_ports.theisland.game_port
    jump: ACCEPT
  - rule:
    chain: INPUT
    interface: enp98s0f0
    protocol: udp
    destination_port: reference to ark_cluster_ports.theisland.query_port
    jump: ACCEPT

What I tried so far is anchors and the merge operator:

ark_cluster_ports: &ark_cluster_ports
  theisland:
    game_port: 7777
    query_port: 27015
    rcon_port: 27020

cluster_nodes:
  - map: TheIsland
    user: theisland
    network:
      <<: *ark_cluster_ports.theisland

And lookup with dictionary:

ark_cluster_ports:
  theisland:
    game_port: 7777
    query_port: 27015
    rcon_port: 27020

cluster_nodes:
  - map: TheIsland
    user: theisland
    network: "{{ lookup('dict', ark_cluster_ports.theisland) }}"

But it seems that I am totally wrong... Could someone point me into the right direction?

Thanks a lot and best regards, michael

1 Answers

TL;DR;

Here would be the YAML that fits the requirement stated in your question:

ark_cluster_ports:
  theisland: &ark_cluster_ports_theisland
    game_port: &ark_cluster_ports_theisland_game_port 7777
    query_port: &ark_cluster_ports_theisland_query_port 27015
    rcon_port: &ark_cluster_ports_theisland_rcon_port 27020

cluster_nodes:
  - map: TheIsland
    user: theisland
    network:
      <<: *ark_cluster_ports_theisland

iptables_rules:
  - rule:
    chain: INPUT
    interface: enp98s0f0
    protocol: tcp
    destination_port: *ark_cluster_ports_theisland_rcon_port
    jump: ACCEPT
  - rule:
    chain: INPUT
    interface: enp98s0f0
    protocol: udp
    destination_port: *ark_cluster_ports_theisland_game_port
    jump: ACCEPT
  - rule:
    chain: INPUT
    interface: enp98s0f0
    protocol: udp
    destination_port: *ark_cluster_ports_theisland_query_port
    jump: ACCEPT

The anchor and alias reference in YAML is powerful, but you are trying to make it more complex than YAML can cope with.

Your issue stand in the alias *ark_cluster_ports.theisland that is actually too complex.

This said, you can easily simplify this and anchor the theisland key right away, for example:

ark_cluster_ports:
  theisland: &ark_cluster_ports_theisland
    game_port: 7777
    query_port: 27015
    rcon_port: 27020

cluster_nodes:
  - map: TheIsland
    user: theisland
    network:
      <<: *ark_cluster_ports_theisland

Here would be a working playbook demoing this:

- hosts: all
  gather_facts: no

  tasks:
    - debug:
        var: cluster_nodes[0].network
      vars:
        ark_cluster_ports: 
          theisland: &ark_cluster_ports_theisland
            game_port: 7777
            query_port: 27015
            rcon_port: 27020

        cluster_nodes:
          - map: TheIsland
            user: theisland
            network:
              <<: *ark_cluster_ports_theisland

This yields the recap:

PLAY [all] **************************************************************************************************************************************************

TASK [debug] ************************************************************************************************************************************************
ok: [localhost] => {
    "cluster_nodes[0].network": {
        "game_port": 7777,
        "query_port": 27015,
        "rcon_port": 27020
    }
}

PLAY RECAP **************************************************************************************************************************************************
localhost                  : ok=1    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

As for your iptables_rules dictionary, you can also anchor a key that contains a value using the syntax

key: &anchor value

So, in your case:

rcon_port: &ark_cluster_ports_theisland_rcon_port 27020

Here would be another playbook demoing this:

- hosts: all
  gather_facts: no

  tasks:
    - debug:
        var: iptables_rules[0].destination_port
      vars:
        ark_cluster_ports: 
          theisland: &ark_cluster_ports_theisland
            game_port: 7777
            query_port: 27015
            rcon_port: &ark_cluster_ports_theisland_rcon_port 27020

        cluster_nodes:
          - map: TheIsland
            user: theisland
            network:
              <<: *ark_cluster_ports_theisland

        iptables_rules:
          - rule:
            chain: INPUT
            interface: enp98s0f0
            protocol: tcp
            destination_port: *ark_cluster_ports_theisland_rcon_port

This yields the recap:

PLAY [all] *********************************************************************************************************

TASK [debug] *******************************************************************************************************
ok: [localhost] => {
    "iptables_rules[0].destination_port": "27020"
}

PLAY RECAP *********************************************************************************************************
localhost                  : ok=1    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
Related