# Issue about defining variable within the task does not work

**URL:** <https://forum.ansible.com/t/issue-about-defining-variable-within-the-task-does-not-work/38651>\
**Category:** Ansible Project\
**Tags:** ubuntu, aws\
**Created:** [January 13, 2024, 2:40pm UTC](https://forum.ansible.com/t/issue-about-defining-variable-within-the-task-does-not-work/38651 "2024-01-13T14:40:30Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![ricardobarbosams](https://avatars.discourse-cdn.com/v4/letter/r/ce73a5/32.png) [@ricardobarbosams](https://forum.ansible.com/u/ricardobarbosams)\
**Post date:** [January 13, 2024, 2:40pm UTC](https://forum.ansible.com/t/issue-about-defining-variable-within-the-task-does-not-work/38651/1 "2024-01-13T14:40:30Z")

</div>

Hello guys

I created the following structure:

```auto
amis:
us-east-1:
amazonlinux:
owner_id: "137112412989"
x86_64: "ami-01bc990364452ab3e"
arm64: "ami-0900a8f768a21540a"
user: "ec2-user"
ubuntu:
owner_id: "099720109477"
x86_64: "ami-0fc5d935ebf8bc3bc" # Ubuntu 22
arm64: "ami-016485166ec7fa705" #
user: "ubuntu"

```

and I have a json file that I fill in to raise an ec2 instance:

```json
{
"aws_region":"us-east-1",
"architecture":"arm64",
"os_version":"ubuntu",
"instance_name":"test6",
"domain":"example.corp",
"subnet":"SUBNET-PUB-A",
"instance_type":"t4g.micro",
"security_groups": ["sg-xxxxxx", "sg-yyyyyyyy"],
"aws_role":"default-role",
"root_volume_size":20,
"ebs_swap_size": 4,
"keyname": "ssh-key",
"ebs_type": "gp3",
"backup": "no",

"boxenv":"DEV"
}

```

And I read this json and create the variables with the tasks:

```auto
- name: Read json configuration
shell: cat config-ec2-launch.json
register: result

- name: save the Json data to a Variable as a Fact
set_fact:
jsondata: "{{ result.stdout | from_json }}"

- name: Variable | Get aws_region variable
set_fact:
aws_region: "{{ jsondata | json_query(jmesquery) }}"
vars:
jmesquery: 'aws_region'

- name: Variable | Get architecture variable
set_fact:
architecture: "{{ jsondata | json_query(jmesquery) }}"
vars:
jmesquery: 'architecture'

- name: Variable | Get os_version variable
set_fact:
os_version: "{{ jsondata | json_query(jmesquery) }}"
vars:
jmesquery: 'os_version'

```

and created the tasks right away:

```auto

- name: AWS Ec2 Instance | Create the EC2 instance
ec2_instance:
state: started # started state=running + waits for EC2 status checks to report OK if wait=true
image_id: "{{ newest_ami }}"
name: "{{ instance_name }}"
detailed_monitoring: false
metadata_options:
http_tokens: required
instance_type: "{{ instance_type }}"
region: "{{ aws_region }}"
vpc_subnet_id: "{{ [subnet_facts.subnets.0.id](http://subnet_facts.subnets.0.id) }}"
instance_initiated_shutdown_behavior: stop
instance_role: "{{ aws_roles[aws_role] }}"
volumes:
- device_name: "{{ name_device_root_ami.images.0.root_device_name }}"
ebs:
volume_type: gp3
volume_size: "{{ root_volume_size }}"
delete_on_termination: true
security_groups: "{{ security_groups }}"
tags:
Name: "{{ instance_name }}"
Domain: "{{ domain }}"
Backup: "{{ backup }}"
BOXENV: "{{ boxenv }}"
key_name: "{{ aws_key_names[keyname] }}"
wait: yes
register: ec2

- name: AWS Ec2 ebs | Add volume to swap
amazon.aws.ec2_vol:
instance: "{{ ec2.instances[0].instance_id }}"
volume_size: "{{ ebs_swap_size }}"
volume_type: "{{ ebs_type }}"
delete_on_termination: True
device_name: "/dev/sdf"
region: '{{ aws_region }}'
tags:
Name: "{{ instance_name }}:swap"
BOXENV: "{{ boxenv }}"

- name: Swap | List all devices on {{ instance_name }}
vars:
ansible_ssh_user: "{{ amis[aws_region][os_version].user }}"
ansible.builtin.shell: echo "{{ aws_region }} {{ ec2.instances.0.network_interfaces.0.private_ip_address }}"
register: devices_host
delegate_to: "{{ ec2.instances.0.network_interfaces.0.private_ip_address }}"
args:
executable: /bin/bash

```

But when I run it, it displays the error below

```auto
FAILED! => {"msg": "'aws_region' is undefined"}

```

If I comment the line `ansible_ssh_user: "{{ amis[aws_region][os_version].user }}"` it displays the contents of the aws\_region variable. Any idea where I’m going wrong?

Thanks

---

<div class="post-metadata">

**Author:** ![utoddl](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/utoddl/32/249_2.png) [@utoddl](https://forum.ansible.com/u/utoddl)\
**Post date:** [January 13, 2024, 4:52pm UTC](https://forum.ansible.com/t/issue-about-defining-variable-within-the-task-does-not-work/38651/2 "2024-01-13T16:52:55Z")

</div>

It’s even stranger than that (until you realize what’s going on).  
Rather than commenting out the “ansible\_ssh\_user:” line, just misspell the variable, like “ansible\_ssh\_userx”. It’ll work then, too — but with the wrong user of course.

What you’re running into is a combination of things: set\_fact, delegate\_to, and the bit you didn’t show, which is your playbook’s “hosts:” line and/or your command’s “–limit” specification. Also the “special variable” function of the “ansible\_ssh\_user” variable itself. Maybe throw in lazy variable template evaluation for good measure.

The error message is correct but incomplete, in that “aws\_region” is undefined. What the message leaves out is “… in the context of the delegation host ‘ec2.instances.0.network\_interfaces.0.private\_ip\_address’”.

You set the task variable “ansible\_ssh\_user” to a template. By lazy template evaluation, that template isn’t evaluated until the variable is used, which is at the point of connection. So it’s evaluated in the context of a host _which has no set\_fact-derived variables defined_: ‘ec2.instances.0.network\_interfaces.0.private\_ip\_address’. Only your play hosts will have set\_fact-derived variables.

Assuming your hosts line is something like “hosts: localhost”, then you can work around it by changing your variable definition to  
ansible\_ssh\_user: “{{ amis[\*\*hostvars[‘localhost’].\*\*aws\_region][\*\*hostvars[‘localhost’].\*\*os\_version].user }}”

I’m reasonably sure (but could be wrong) that the “amis” dict is defined, because it isn’t a host variable. That’s different from set\_fact-derived variables which are both host-specific and template resolved at their creation.

Let us know if this resolves your issue.

---

<div class="post-metadata">

**Author:** ![Evan\_Hisey](https://avatars.discourse-cdn.com/v4/letter/e/ce73a5/32.png) [@Evan\_Hisey](https://forum.ansible.com/u/Evan_Hisey)\
**Post date:** [January 13, 2024, 5:25pm UTC](https://forum.ansible.com/t/issue-about-defining-variable-within-the-task-does-not-work/38651/3 "2024-01-13T17:25:03Z")

</div>

Ricardo-  
I would also recommend changing how you are sending the json to the playbook. I have done this a lot in AWS and found it is much cleaner to either A) use a variable group file, or B) pass it via a parameter file. Both methods help avoid some of what Todd is referring to.

---

<div class="post-metadata">

**Author:** ![ricardobarbosams](https://avatars.discourse-cdn.com/v4/letter/r/ce73a5/32.png) [@ricardobarbosams](https://forum.ansible.com/u/ricardobarbosams)\
**Post date:** [January 15, 2024, 10:00pm UTC](https://forum.ansible.com/t/issue-about-defining-variable-within-the-task-does-not-work/38651/4 "2024-01-15T22:00:31Z")

</div>

Thanks Todd,

It worked. So because “delegate\_to” the localhost host variables are not available I need to pass the variables with hostvars[host], right?

Thank you I will correct the entire playbook

---

<div class="post-metadata">

**Author:** ![ricardobarbosams](https://avatars.discourse-cdn.com/v4/letter/r/ce73a5/32.png) [@ricardobarbosams](https://forum.ansible.com/u/ricardobarbosams)\
**Post date:** [January 15, 2024, 10:01pm UTC](https://forum.ansible.com/t/issue-about-defining-variable-within-the-task-does-not-work/38651/5 "2024-01-15T22:01:30Z")

</div>

Thanks for the tip Evan 🙂
