Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Help]: linode.cloud.api_request #334

Closed
grzegorzk opened this issue Apr 9, 2023 · 2 comments · Fixed by #342
Closed

[Help]: linode.cloud.api_request #334

grzegorzk opened this issue Apr 9, 2023 · 2 comments · Fixed by #342
Labels
help wanted Extra attention is needed

Comments

@grzegorzk
Copy link
Contributor

grzegorzk commented Apr 9, 2023

Description

I'm trying to issue a task which would reboot my vm into rescue mode, but I'm getting error suggesting my JSON is incorrect. I'm pretty sure JSON is not missing double-quotes anywhere, so I must be doing something wrong and can't see where.

Ansible Configuration

CONFIG_FILE() = /opt/ansible/ansible.cfg
DEFAULT_VAULT_PASSWORD_FILE(/opt/ansible/ansible.cfg) = /opt/ansible/.vault-pass
HOST_KEY_CHECKING(/opt/ansible/ansible.cfg) = False

Attempted Config

Below fails with fatal: [localhost]: FAILED! => {"changed": false, "msg": "JSONDecodeError: Expecting property name enclosed in double quotes: line 1 column 2 (char 1)"}:

# empty_linode registered earlier
- name: Boot empty linode into rescue mode
  # https://github.com/linode/ansible_linode/blob/dev/docs/modules/api_request.md
  linode.cloud.api_request:
    # https://www.linode.com/docs/api/linode-instances/#linode-boot-into-rescue-mode
    api_token: "{{ linode_api_token }}"
    path: "/linode/instances/{{ empty_linode.instance.id }}/rescue"
    method: POST
    body_json: >
      {
        "devices": {
          "sda": {
            "disk_id": {{ empty_linode.configs[0].devices.sda.disk_id }}
          }
        }
      }
  register: response

However below "works" (linode boots to rescue mode however no devices are mapped):

# empty_linode registered earlier
- name: Boot empty linode into rescue mode
  # https://github.com/linode/ansible_linode/blob/dev/docs/modules/api_request.md
  linode.cloud.api_request:
    # https://www.linode.com/docs/api/linode-instances/#linode-boot-into-rescue-mode
    api_token: "{{ linode_api_token }}"
    path: "/linode/instances/{{ empty_linode.instance.id }}/rescue"
    method: POST
    body_json: >
      {
        "devices": {
        }
      }
  register: response

I'm trying to use json above because below yml renders to json with strings as disk id (int is required), it would be nice if in this case strings could be converted to int when rendering to json

- name: Boot empty linode instance into rescue mode
  # https://github.com/linode/ansible_linode/blob/dev/docs/modules/api_request.md
  linode.cloud.api_request:
    # https://www.linode.com/docs/api/linode-instances/#linode-boot-into-rescue-mode
    api_token: "{{ linode_api_token }}"
    path: "/linode/instances/{{ empty_linode.instance.id }}/rescue"
    method: POST
    body:
      devices:
        sda:
          disk_id: "{{ empty_linode.configs.devices.sda.disk_id }}"
  register: response
@grzegorzk grzegorzk added the help wanted Extra attention is needed label Apr 9, 2023
@grzegorzk
Copy link
Contributor Author

I have done some googling and found that {{whatever}} will always render as string (so wrapped within double-quotes) - I thought this would not be the case if I used template within string...

As a workaround I used below which works only because linode config registered earlier was using the same key for disk_id within sda which is also required within sda in devices for API call.

- name: Boot empty linode instance into rescue mode
  # https://github.com/linode/ansible_linode/blob/dev/docs/modules/api_request.md
  linode.cloud.api_request:
    # https://www.linode.com/docs/api/linode-instances/#linode-boot-into-rescue-mode
    api_token: "{{ linode_api_token }}"
    path: "/linode/instances/{{ empty_linode.instance.id }}/rescue"
    method: POST
    body:
      devices:
        sda: "{{ empty_linode.configs[0].devices.sda }}"
  register: response

I still think it would be nice if linode.cloud.api_request would cast values to proper types when rendering json from yml... though at least my immediate pain is solved.

@lgarber-akamai
Copy link
Contributor

lgarber-akamai commented Apr 10, 2023

Thanks for the report @grzegorzk !

Below fails with fatal: [localhost]: FAILED! => {"changed": false, "msg": "JSONDecodeError: Expecting property name enclosed in double quotes: line 1 column 2 (char 1)"}:

I did a bit of digging and it looks like this error is the result of some odd Ansible templating functionality that is converting your valid JSON into invalid JSON:

{'devices': {'sda': {'disk_id': 12345}}}

This appears to be related to a known Ansible/Jinja2 issue, although I haven't been able to resolve the issue using the jinja2_native configuration value mentioned in the thread.

That said, I was able to work around this issue using the to_json filter:

    - name: Build request body
      set_fact:
        rescue_request_body: >
          {
            "devices": {
              "sda": {
                "disk_id": {{ empty_linode.configs[0].devices.sda.disk_id }}
              }
            }
          }
          

    # empty_linode registered earlier
    - name: Boot empty linode into rescue mode
      # https://github.com/linode/ansible_linode/blob/dev/docs/modules/api_request.md
      linode.cloud.api_request:
        # https://www.linode.com/docs/api/linode-instances/#linode-boot-into-rescue-mode
        path: "/linode/instances/{{ empty_linode.instance.id }}/rescue"
        method: POST
        body_json: "{{ rescue_request_body | to_json }}"
      register: response

I still think it would be nice if linode.cloud.api_request would cast values to proper types when rendering json from yml... though at least my immediate pain is solved.

We've had some users run into some related issues in the past and it seems to be very problematic for manually hitting endpoints that expect integers in the request body. I'll create a ticket in our internal tracker to investigate solutions to this issue and will let you know if we have any updates 🙂

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
help wanted Extra attention is needed
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants