ansible-collections / ansible-collections/google.cloud
google.cloud.gcp_compute_instance_info won't give metadata in dictionnary output
- Dominant language
- Python
- Stars
- 105
- Forks
- 144
- Avg merge
- 5d 10h
- Merged PRs (30d)
- 4
Description
##### SUMMARY
**google.cloud.gcp_compute_instance_info** module will give the instance metadata in the form of a dictionary list instead of a dictionary.
##### ISSUE TYPE
- Bug Report
##### COMPONENT NAME
gcp_compute_instance_info
##### ANSIBLE VERSION
```
ansible [core 2.13.7]
config file = /runner/ansible.cfg
configured module search path = ['/usr/local/lib64/python3.8/site-packages/pyrfc', '/runner/project/plugins']
ansible python module location = /usr/local/lib/python3.8/site-packages/ansible
ansible collection location = /home/runner/.ansible/collections:/usr/share/ansible/collections
executable location = /usr/local/bin/ansible
python version = 3.8.13 (default, Jun 24 2022, 15:27:57) [GCC 8.5.0 20210514 (Red Hat 8.5.0-13)]
jinja version = 3.1.2
libyaml = True
```
##### COLLECTION VERSION
```
# /usr/local/lib/python3.8/site-packages/ansible_collections
Collection Version
------------ -------
google.cloud 1.0.2
# /usr/share/ansible/collections/ansible_collections
Collection Version
------------ -------
google.cloud 1.1.2
```
##### CONFIGURATION
```
CALLBACKS_ENABLED(/runner/ansible.cfg) = ['profile_tasks']
DEFAULT_FACT_PATH(/runner/ansible.cfg) = /SRC/GLOBAL/AWX/facts
DEFAULT_MODULE_PATH(/runner/ansible.cfg) = ['/usr/local/lib64/python3.8/site-packages/pyrfc', '/runner/project/plugins']
DEFAULT_REMOTE_USER(/runner/ansible.cfg) = root
DEPRECATION_WARNINGS(/runner/ansible.cfg) = False
DISPLAY_SKIPPED_HOSTS(/runner/ansible.cfg) = False
HOST_KEY_CHECKING(/runner/ansible.cfg) = False
INTERPRETER_PYTHON(/runner/ansible.cfg) = /usr/bin/python
SHOW_CUSTOM_STATS(/runner/ansible.cfg) = True
```
##### OS / ENVIRONMENT
It only works with GCP API.
##### STEPS TO REPRODUCE
When I retrieve instance data with **google.cloud.gcp_compute_instance_info**, metadata is given as a list of dictionaries.
```
"metadata": {
"kind": "compute#metadata",
"fingerprint": "xxxxxxxxx",
"items": [
{
"key": "foo_1",
"value": "bar_1"
},
{
"key": "foo_2",
"value": "bar_2"
}
]
```
As explained in [documentation](https://docs.ansible.com/ansible/latest/collections/google/cloud/gcp_compute_instance_info_module.html), it should be a dictionnary and the output should be like this:
```
"metadata": {
"foo_1": "bar_1",
"foo_2": "bar_2"
}
```
_**STEP 1**_ - Retrieve all data from GCP API (internal/gcp_get_info_internal.yml)
```yaml
- name: Get instance info from GCP API
google.cloud.gcp_compute_instance_info:
auth_kind: serviceaccount
project: "{{ project }}"
service_account_contents: "{{ gcp_credential_json }}"
zone: "{{ hostvars[my_gcp_target_instance_internal]['zone'] }}"
filters:
- name = "{{ my_gcp_target_instance_internal }}"
register: get_output
delegate_to: localhost
- name: Set fact to return the call API response from GCP
ansible.builtin.set_fact:
"{{ return_my_server_info_internal }}": "{{ get_output.resources[0] }}"
delegate_to: localhost
```
_**STEP 2**_ - Retrieve all metadata based on data previously extracted from internal/gcp_get_info_internal.yml (gcp_get_instance_metadata.yml)
```yaml
- name: Get instance informations
ansible.builtin.include_tasks: internal/gcp_get_info_internal.yml
vars:
return_my_server_info_internal: my_instance_info
my_gcp_target_instance_internal: "{{ my_gcp_target_instance | default(inventory_hostname) }}"
- name: Set fact to store instance metadata in variable {{ return_my_server_metadata }}
ansible.builtin.set_fact:
"{{ return_my_server_metadata }}": "{{ my_instance_info.metadata['items'] }}"
delegate_to: localhost
```
_**STEP 3**_ - Store all metadata based in variable on data previously extracted from gcp_get_instance_metadata.yml and modify GCP instance by specifying metadata
- **Initial Status** : I delete the part where i add/modify the metadata > I just want at this point verify all is working well with the module.
```yaml
- name: Fetch metadata of instance from GCP API
ansible.builtin.include_tasks: gcp_get_instance_metadata.yml
vars:
return_my_server_metadata: instance_metadata
- name: Add a metadata
vars:
gcp_target_instance: "{% if my_gcp_target_instance is defined %}{{ my_gcp_target_instance }}{% else %}{{ inventory_hostname }}{% endif %}"
zone_gcp: "{% if my_gcp_target_instance is defined %}{{ hostvars[my_gcp_target_instance]['zone'] }}{% else %}{{ zone }}{% endif %}"
machine_type_gcp: "{% if my_gcp_machine_type is defined %}{{ my_gcp_machine_type }}{% elif my_gcp_target_instance is defined %}{{ hostvars[my_gcp_target_instance]['machineType'] }}{% else %}{{ machineType }}{% endif %}"
google.cloud.gcp_compute_instance:
name: "{{ gcp_target_instance }}"
zone: "{{ zone_gcp }}"
project: "{{ project }}"
auth_kind: serviceaccount
service_account_contents: "{{ gcp_credential_json }}"
machine_type: "{{ machine_type_gcp }}"
labels: "{{ instance_labels }}"
metadata: "{{ instance_metadata }}"
delegate_to: localhost
```
##### EXPECTED RESULTS
Playbook do nothing (because of initial status) or says everything is already ok.
##### ACTUAL RESULTS
Because of that, when I'm trying to update / add metadata with **google.cloud.gcp_compute_instance**, it is exiting with error
```
argument 'metadata' is of type and we were unable to convert to dict: cannot be converted to a dict"
```
Contributor guide
Research direction
Start by running the three-step reproduction using google.cloud.gcp_compute_instance_info and google.cloud.gcp_compute_instance, beginning with internal/gcp_get_info_internal.yml and gcp_get_instance_metadata.yml. Inspect the gcp_compute_instance_info module's metadata output and compare it with the documented dictionary shape; done means the returned metadata can be passed to gcp_compute_instance without a list-to-dict conversion error.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- google-cloud, python
- Domain
- cloud, devops
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 58/100