set facts from items in a loop

I wonder if something like this can be done, the problem i’m seeing is that the fact name has to be static, and could not use {{ item }}:

  • name: Set each tag to facts
    set_fact:
    list_of_vars: “{{ my_instance.instances | map(attribute=‘tags.list_of_vars’) | list | join(‘\n’) }}”

  • name: Split “list_of_vars” variable into a comma separated list
    set_fact:
    item_list: “{{ list_of_vars.split(‘,’) }}”

  • name: lookup SSM Parameter Store secrets
    set_fact:
    {{ item }}: “{{ lookup(‘amazon.aws.ssm_parameter’, puppet_env+‘‘+env+’{{ item }}’, region=ansible_ec2_placement_region) }}”
    with_items: “{{ item_list }}”

This would give me a fact for each comma separated var I put in the tag, if only it worked. Is there a better way to do something like this?

You could perhaps template your desired variables and values into a file, then use the ansible.builtin.include_vars module to read them in.
https://docs.ansible.com/ansible/latest/collections/ansible/builtin/include_vars_module.html

I don’t 100% understand your ultimate aim here. It might be easier to understand if you break it down into smaller steps and include some sample inputs and desired output?

A sanitised version of what’s in my_instance, item_list , and what you would like out at the end might help?

IF I understand what you’re trying to do, using your loop item as the key for your set_fact. For me, with appropriate quoting this seems to work…

$ cat wtf.yml

  • hosts: localhost
    become: no
    gather_facts: no

vars:
varlist:

  • value1
  • value2
  • valueC

tasks:

  • name: Use item as the fact key for set_fact in a loop
    set_fact:
    “{{ item }}”: value
    loop: “{{ varlist }}”

  • name: Check the values assigned to the facts
    debug:
    var: “{{ item }}”
    loop: “{{ varlist }}”

$ ansible-playbook wtf.yml
PLAY [localhost] *************************************************************************************************************************
TASK [Use item as the fact key for set_fact in a loop] ***********************************************************************************
ok: [localhost] => (item=value1)
ok: [localhost] => (item=value2)
ok: [localhost] => (item=valueC)

TASK [Check the values assigned to the facts] ********************************************************************************************
ok: [localhost] => (item=value1) => {
“ansible_loop_var”: “item”,
“item”: “value1”,
“value1”: “value”
}
ok: [localhost] => (item=value2) => {
“ansible_loop_var”: “item”,
“item”: “value2”,
“value2”: “value”
}
ok: [localhost] => (item=valueC) => {
“ansible_loop_var”: “item”,
“item”: “valueC”,
“valueC”: “value”
}

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

doh, thats the only thing it took I was missing! If I double quoted {{item}} like you just did, then it works.

To give some more background on the problem, I couldn’t simply template the vars since each of my different host inventories may have a different number of variables it needed. So my aim was to do something like this, Create a tag on an EC2 instance with a comma separated list I would use to loop through, for each item it would assign a value from parameter store that matches with the item name:

TAG:

Key Value

list_of_vars = a,b,c

in param store I have a parameter of “a” “b” and “c” with a secret value assigned. This way all I have to do is update the tag with more variables, and each host can have whatever I want as long as there is a matching param store. Its working now, this is great, thanks to everyone.

The only other way I could think of would have to say “for this inventory file, use this var template” and I don’t think there is any good way to do that.