ansible-collections / community.kubernetes

Kubernetes Collection for Ansible
https://galaxy.ansible.com/community/kubernetes
GNU General Public License v3.0
265 stars 106 forks source link

"Unprocessable Entity", "status": 422 #336

Closed thanos1983 closed 3 years ago

thanos1983 commented 3 years ago
SUMMARY

I am trying to use the module community.kubernetes.k8s – Manage Kubernetes (K8s) objects with variables from the role (e.g. role/sampleRole/vars file).

I am failing when it comes to the integer point e.g.:

- name: sample                                                                                                                                                         
  community.kubernetes.k8s:                                                                                                                                                                                                                      
  state: present                                                                                                                                                                                                                               
  definition:                                                                                                                                                                                                                                    
    apiVersion: apps/v1                                                                                                                                                                                                                          
    kind: Deployment                                                                                                                                                                                                                             
    metadata:                                                                                                                                                                                                                                      
      name: "{{ name }}"
      namespace: "{{ namespace }}"                                                                                                                                                                                             
      labels:
        app: "{{ app }}"                                                                                                                                                                                              
    spec:
      replicas: 2
        selector:
          matchLabels:
            app: "{{ app }}"                                                                                                                                                                                    
        template:
          metadata:
            labels:
              app: "{{ app }}"                                                                                                                                                                                
          spec:
            containers:
            - name: "{{ name }}"                                                                                                                                                                                  
              image: "{{ image }}"                                                                                                                                                                                
              ports:
              - containerPort: {{ containerPort }}

When I deploy with this format obviously it will fail at it can not parse the "reference" to the var.

Sample of error:

ERROR! We were unable to read either as JSON nor YAML, these are the errors we got from each:
JSON: Expecting value: line 1 column 1 (char 0)

Syntax Error while loading YAML.
  found unacceptable key (unhashable type: 'AnsibleMapping')

The error appears to be in 'deploy.yml': line <some line>, column <some column>, but may
be elsewhere in the file depending on the exact syntax problem.

The offending line appears to be:

              ports:
              - containerPort: {{ containerPort }}
                                ^ here
We could be wrong, but this one looks like it might be an issue with
missing quotes. Always quote template expression brackets when they
start a value. For instance:

    with_items:
      - {{ foo }}

Should be written as:

    with_items:
      - "{{ foo }}"

When I use quotes on the variable e.g. - containerPort: "{{ containerPort }}" then I get the following error (part of it):

v1.Deployment.Spec: v1.DeploymentSpec.Template: v1.PodTemplateSpec.Spec: v1.PodSpec.Containers: []v1.Container: v1.Container.Ports: []v1.ContainerPort: v1.ContainerPort.ContainerPort: readUint32: unexpected character: \\\\ufffd, error found in #10 byte of ...|nerPort\\\\\":\\\\\"80\\\\\"}]}],\\\\\"d|..., bigger context ...|\\\\\",\\\\\"name\\\\\":\\\\\"samplegreen\\\\\",\\\\\"ports\\\\\":[{\\\\\"containerPort\\\\\":\\\\\"80\\\\\"}]}],\\\\\"dnsPolicy\\\\\":\\\\\"ClusterFirst\\\\\",\\\\\"restartPolicy\\\\\"|...\",\"field\":\"patch\"}]},\"code\":422}\\n'", "reason": "Unprocessable Entity", "status": 422}

I tried to cast the string to int by using - containerPort: "{{ containerPort | int }}" but it did not worked. The problem seems to be coming from the quotes, independently how I define the var in my var file e.g. containerPort: 80 or containerPort: "80".

I found a similar question on the forum stackoverflow Ansible, k8s and variables but the user seems not to have the same problems that I am having.

I am running with the latest version of the module:

$ pip3 show openshift
Name: openshift
Version: 0.11.2
Summary: OpenShift python client
Home-page: https://github.com/openshift/openshift-restclient-python
Author: OpenShift
Author-email: UNKNOWN
License: Apache License Version 2.0
Location: /usr/local/lib/python3.8/dist-packages
Requires: ruamel.yaml, python-string-utils, jinja2, six, kubernetes

Is there any workaround this problem or is it a bug?

ISSUE TYPE
COMPONENT NAME

module community.kubernetes.k8s – Manage Kubernetes (K8s) objects

ANSIBLE VERSION
$ pip3 show ansible
Name: ansible
Version: 2.10.4
Summary: Radically simple IT automation
Home-page: https://ansible.com/
Author: Ansible, Inc.
Author-email: info@ansible.com
License: GPLv3+
Location: /usr/local/lib/python3.8/dist-packages
Requires: ansible-base
CONFIGURATION
$ ansible-config dump --only-changed
ANSIBLE_COW_SELECTION(/home/<user>/my-cookbook/ansible.cfg) = random
ANSIBLE_NOCOWS(/home/<user>/my-cookbook/ansible.cfg) = False
DEFAULT_LOCAL_TMP(/home/<user>/my-cookbook/ansible.cfg) = /tmp/ansible-local-2287wsxqo1fo
DEFAULT_STRATEGY(/home/<user>/my-cookbook/ansible.cfg) = linear
DEPRECATION_WARNINGS(/home/<user>/my-cookbook/ansible.cfg) = False
HOST_KEY_CHECKING(/home/<user>/my-cookbook/ansible.cfg) = False
INTERPRETER_PYTHON(/home/<user>/my-cookbook/ansible.cfg) = /usr/bin/python3
OS / ENVIRONMENT
$ lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description:    Ubuntu 18.04.5 LTS
Release:        18.04
Codename:       bionic
STEPS TO REPRODUCE

Simply create a small demo and try to deploy on a master node.

- name: sample                                                                                                                                                         
  community.kubernetes.k8s:                                                                                                                                                                                                                      
  state: present                                                                                                                                                                                                                               
  definition:                                                                                                                                                                                                                                    
    apiVersion: apps/v1                                                                                                                                                                                                                          
    kind: Deployment                                                                                                                                                                                                                             
    metadata:                                                                                                                                                                                                                                      
      name: "{{ name }}"
      namespace: "{{ namespace }}"                                                                                                                                                                                             
      labels:
        app: "{{ app }}"                                                                                                                                                                                              
    spec:
      replicas: 2
        selector:
          matchLabels:
            app: "{{ app }}"                                                                                                                                                                                    
        template:
          metadata:
            labels:
              app: "{{ app }}"                                                                                                                                                                                
          spec:
            containers:
            - name: "{{ name }}"                                                                                                                                                                                  
              image: "{{ image }}"                                                                                                                                                                                
              ports:
              - containerPort: "{{ containerPort }}"
EXPECTED RESULTS

Expected result would be that the module can parse the string (or casted int) and not produce this error.

ACTUAL RESULTS
v1.Deployment.Spec: v1.DeploymentSpec.Template: v1.PodTemplateSpec.Spec: v1.PodSpec.Containers: []v1.Container: v1.Container.Ports: []v1.ContainerPort: v1.ContainerPort.ContainerPort: readUint32: unexpected character: \\\\ufffd, error found in #10 byte of ...|nerPort\\\\\":\\\\\"80\\\\\"}]}],\\\\\"d|..., bigger context ...|\\\\\",\\\\\"name\\\\\":\\\\\"samplegreen\\\\\",\\\\\"ports\\\\\":[{\\\\\"containerPort\\\\\":\\\\\"80\\\\\"}]}],\\\\\"dnsPolicy\\\\\":\\\\\"ClusterFirst\\\\\",\\\\\"restartPolicy\\\\\"|...\",\"field\":\"patch\"}]},\"code\":422}\\n'", "reason": "Unprocessable Entity", "status": 422}
goneri commented 3 years ago

Hi @thanos1983,

The problem seems to actually be this error: readUint32: unexpected character: \\\\ufffd, error found in #10 byte of ...|nerPort. It looks like you've got some unexpected characters either in the variable configuration file or maybe in the playbook itself. These UTF8 characters are not displayed by text-editor and may be hard to find.

thanos1983 commented 3 years ago

Hi @thanos1983,

The problem seems to actually be this error: readUint32: unexpected character: \\\\ufffd, error found in #10 byte of ...|nerPort. It looks like you've got some unexpected characters either in the variable configuration file or maybe in the playbook itself. These UTF8 characters are not displayed by text-editor and may be hard to find.

Hello @goneri,

I do not think that the problem is there. In my vars file I pass the variable as e.g.:

containerPort: 80

I tried also to pass it as string e.g.:

containerPort: "80"

Then I cast it to int e.g.:

containerPort: "{{ containerPort | int }}"

But none of them worked.

My workaround for the moment is that I am using templates with the module e.g. (from documentation examples):

- name: Read definition template file from the Ansible controller file system
  community.kubernetes.k8s:
    state: present
    template: '/testing/deployment.j2'

Where I can pass the variables without any problems. I think the error is misleading but it is up to you to close the ticket if you can not replicate it :).

BR / Thanos

goneri commented 3 years ago

I just took a look at our melecule test, and we pass a dict to the template... and it works. So I'm a bit confused.

thanos1983 commented 3 years ago

I just took a look at our melecule test, and we pass a dict to the template... and it works. So I'm a bit confused.

I get the same error when I replace also the var:

replicas: 2

In the example provided above I have used an int directly so the script is complaining when you use the plain text deployment. When using template I also use dictionaries with int variables on this values.

From my understanding it seems that the plain text is not able to parse the dictionary when it comes to int. I also tried to run:

cat -A k8s_sample_deployment.yml

But I did not see any weird characters that could explain the error. After all I am passing the var through dictionary that is coming from the vars file. Another alternative way that I was recommended by the stackoverflow/How to use k8s Ansible module without quotes? is to use Formatting data: YAML and JSON/from_yaml.

So in conclusion with plain text and int from vars it can not be used. Unless use template. The strings are parsed just fine the int is the problem. Some tricky is happening there.

Hope this helps.

BR / Thanos

goneri commented 3 years ago

Hi @thanos1983, May I ask you to playbook on a github repository that reproduce the issue?

thanos1983 commented 3 years ago

Hi @thanos1983, May I ask you to playbook on a github repository that reproduce the issue?

Hello again @goneri,

I was replicating the code and I noticed that there was a new version of the package:

$ python3 -m pip show k8s
Name: k8s
Version: 0.17.0
Summary: Python client library for the Kubernetes API
Home-page: https://github.com/fiaas/k8s
Author: FiaaS developers
Author-email: fiaas@googlegroups.com
License: Apache License
Location: /usr/local/lib/python3.8/dist-packages
Requires: requests, pyrfc3339, six, cachetools

I updated and the problem is fixed.

We can close the ticket. :)

Thank you for your time and effort to help me.

goneri commented 3 years ago

Great! Thank you for the update.