ansible-collections / ansible-collections/google.cloud

google.cloud.gcp_compute_instance_info won't give metadata in dictionnary output

Open
#565 6 comments 0 reactions 0 assignees View on GitHub
stale
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

Open the contributing 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.