ansiblejinja2

How do I convert a list of strings to a list of dictionaries?


I have a list of strings that looks like this:

"forwarded_ports": [
    "123",
    "234",
    "456"
]

And I'd like to use the values of this list as values in a list of dictionaries that would look like this:

"mapped_ports": [
    {
        "external_port": "123",
        "internal_port": "123"
    },
    {
        "external_port": "234",
        "internal_port": "234"
    },
    {
        "external_port": "456",
        "internal_port": "456"
    }
]

Is there a way to do this using inline Ansible/Jinja filters? I know I can do this easily with an Ansible loop like this:

- set_fact:
    mapped_ports: "{{ mapped_ports| default([]) + [{ 'internal_port' : item , 'external_port' : item }] }}"
  loop: "{{ forwarded_ports }}"

But ideally this data structure would be created on the fly in a defaults file with just filters, etc. It seems like there's a simple way to do it with map and dict filters but I can't seem to figure it out. Thanks for any help!


Solution

  • Ordinarily, I don't recommend json_query but in this case it's a great fit for what you're trying to do because of its ability to construct new nodes via projection:

    - debug:
        msg: >-
          {{ forwarded_ports | json_query("[*].{external_port: @, internal_port: @}") }}
      vars:
        "forwarded_ports": [
          "123",
          "234",
          "456"
        ]
    

    yields

    ok: [localhost] => {
        "msg": [
            {
                "external_port": "123",
                "internal_port": "123"
            },
            {
                "external_port": "234",
                "internal_port": "234"
            },
            {
                "external_port": "456",
                "internal_port": "456"
            }
        ]
    }