salt: [BUG] 3000.2 kubernetes.service_present fails on Kubernetes python client version 11.0

Description

Every time I run state.apply with kubernetes.service_present it gives me error: ValueError: Invalid value for `port`, must not be `None`

Setup

tomcat-test.sls

Create tomcat internal service for namespace tomcat:
  kubernetes.service_present:
    - name: tai-tomcat-service-internal
    - kubeconfig: /root/kubeconfig_salt
    - context: default
    - namespace: tomcat
      metadata:
        name: tai-tomcat-service-internal
        labels:
          run: tai-app-service
      spec:
        selector:
          run: tai-app-service
        type: ClusterIP
        ports:
        - name: tai-tomcat-service
          protocol: TCP
          port: 8080
          targetPort: 8080

Steps to Reproduce the behavior

root@dev:/srv/salt/kubernetes# salt mytest state.apply kubernetes.tomcat-test
mytest:
----------
          ID: Create tai-tomcat internal service tai for namespace tomcat
    Function: kubernetes.service_present
        Name: tai-tomcat-service-internal
      Result: False
     Comment: An exception occurred in this state: Traceback (most recent call last):
                File "/usr/lib/python3.6/site-packages/salt/state.py", line 1981, in call
                  **cdata['kwargs'])
                File "/usr/lib/python3.6/site-packages/salt/loader.py", line 1977, in wrapper
                  return f(*args, **kwargs)
                File "/usr/lib/python3.6/site-packages/salt/states/kubernetes.py", line 312, in service_present
                  **kwargs)
                File "/usr/lib/python3.6/site-packages/salt/modules/kubernetesmod.py", line 1072, in create_service
                  saltenv=saltenv)
                File "/usr/lib/python3.6/site-packages/salt/modules/kubernetesmod.py", line 1466, in __create_object_body
                  spec=spec_creator(spec))
                File "/usr/lib/python3.6/site-packages/salt/modules/kubernetesmod.py", line 1574, in __dict_to_service_spec
                  kube_port = kubernetes.client.V1ServicePort()
                File "/usr/local/lib/python3.6/site-packages/kubernetes/client/models/v1_service_port.py", line 63, in __init__
                  self.port = port
                File "/usr/local/lib/python3.6/site-packages/kubernetes/client/models/v1_service_port.py", line 136, in port
                  raise ValueError("Invalid value for `port`, must not be `None`")  # noqa: E501
              ValueError: Invalid value for `port`, must not be `None`
     Started: 16:53:16.407060
    Duration: 23.525 ms
     Changes:
----------

I suspect the method __dict_to_service_spec(spec) on kubernetesmod.py would need to pass the port number into the constructor kube_port = kubernetes.client.V1ServicePort()

https://github.com/kubernetes-client/python/blame/master/kubernetes/client/models/v1_service_port.py

Expected behavior

From the issue seen on https://github.com/kubernetes-client/python/issues/1199 the codes might need to be refactored as kube_port = kubernetes.client.V1ServicePort(port=port)

Versions Report

Salt Version:
           Salt: 3000.2

Dependency Versions:
           cffi: 1.14.0
       cherrypy: Not Installed
       dateutil: 2.8.1
      docker-py: Not Installed
          gitdb: Not Installed
      gitpython: Not Installed
         Jinja2: 2.8.1
        libgit2: Not Installed
       M2Crypto: 0.33.0
           Mako: Not Installed
   msgpack-pure: Not Installed
 msgpack-python: 0.6.2
   mysql-python: Not Installed
      pycparser: 2.20
       pycrypto: 2.6.1
   pycryptodome: Not Installed
         pygit2: Not Installed
         Python: 3.6.8 (default, Aug  7 2019, 17:28:10)
   python-gnupg: Not Installed
         PyYAML: 5.3.1
          PyZMQ: 15.3.0
          smmap: Not Installed
        timelib: Not Installed
        Tornado: 4.5.3
            ZMQ: 4.1.4

System Versions:
           dist: centos 7.4.1708 Core
         locale: UTF-8
        machine: x86_64
        release: 3.10.0-1062.18.1.el7.x86_64
         system: Linux
        version: CentOS Linux 7.4.1708 Core

About this issue

  • Original URL
  • State: open
  • Created 3 years ago
  • Comments: 17 (9 by maintainers)

Commits related to this issue

Most upvoted comments

Hi @sagetherage

Would like to raise PR but am not familiar with salt test process.

In PR template, it mentions about test requirement, I tried to follow the doc on https://docs.saltstack.com/en/latest/topics/tutorials/writing_tests.html and ran the nox, but getting no luck with error “No such file or directory: ‘/root/noxfile.py’”

I guess I would need some time to get familiar with it (I am new to salt dev and integration process here). Would you mind to help me to perform test and raise PR from your side for better process and coverage?

I forked and made my modification here: fix_59758

Before that I also actually tested my changes on version 3001.7, it works fine in my local environment.

These are my changes that I had tested in my local machine with 3001.7 version: 3001.7-fix-kubernetesmod

Thanks.

Hello @sagetherage

I upgraded to salt 3001.6 also seeing same errors.

This is the error output from version 3001.6

----------
          ID: Create tai-tomcat internal service tai for namespace tomcat
    Function: kubernetes.service_present
        Name: tai-tomcat-service-internal
      Result: False
     Comment: An exception occurred in this state: Traceback (most recent call last):
                File "/usr/lib/python3.6/site-packages/salt/state.py", line 2154, in call
                  *cdata["args"], **cdata["kwargs"]
                File "/usr/lib/python3.6/site-packages/salt/loader.py", line 2087, in wrapper
                  return f(*args, **kwargs)
                File "/usr/lib/python3.6/site-packages/salt/states/kubernetes.py", line 320, in service_present
                  **kwargs
                File "/usr/lib/python3.6/site-packages/salt/modules/kubernetesmod.py", line 1252, in replace_service
                  saltenv=saltenv,
                File "/usr/lib/python3.6/site-packages/salt/modules/kubernetesmod.py", line 1416, in __create_object_body
                  spec=spec_creator(spec),
                File "/usr/lib/python3.6/site-packages/salt/modules/kubernetesmod.py", line 1524, in __dict_to_service_spec
                  kube_port = kubernetes.client.V1ServicePort()
                File "/usr/local/lib/python3.6/site-packages/kubernetes/client/models/v1_service_port.py", line 63, in __init__
                  self.port = port
                File "/usr/local/lib/python3.6/site-packages/kubernetes/client/models/v1_service_port.py", line 136, in port
                  raise ValueError("Invalid value for `port`, must not be `None`")  # noqa: E501
              ValueError: Invalid value for `port`, must not be `None`
     Started: 05:47:16.398062
    Duration: 28.728 ms
     Changes:
----------
Salt Version:
           Salt: 3001.6

Dependency Versions:
           cffi: 1.14.0
       cherrypy: Not Installed
       dateutil: 2.8.1
      docker-py: Not Installed
          gitdb: Not Installed
      gitpython: Not Installed
         Jinja2: 2.8.1
        libgit2: Not Installed
       M2Crypto: 0.33.0
           Mako: Not Installed
   msgpack-pure: Not Installed
 msgpack-python: 0.6.2
   mysql-python: Not Installed
      pycparser: 2.20
       pycrypto: 2.6.1
   pycryptodome: Not Installed
         pygit2: Not Installed
         Python: 3.6.8 (default, Aug  7 2019, 17:28:10)
   python-gnupg: Not Installed
         PyYAML: 5.3.1
          PyZMQ: 17.0.0
          smmap: Not Installed
        timelib: Not Installed
        Tornado: 4.5.3
            ZMQ: 4.1.4

System Versions:
           dist: centos 7 Core
         locale: UTF-8
        machine: x86_64
        release: 3.10.0-1062.18.1.el7.x86_64
         system: Linux
        version: CentOS Linux 7 Core

I believe this issue should be still seen even in the latest version 3002, because in master branch, I saw it was still calling constructor kube_port = kubernetes.client.V1ServicePort() without passing the port number into it

https://github.com/saltstack/salt/blob/master/salt/modules/kubernetesmod.py

def __dict_to_service_spec(spec):
    """
    Converts a dictionary into kubernetes V1ServiceSpec instance.
    """
    spec_obj = kubernetes.client.V1ServiceSpec()
    for key, value in spec.items():  # pylint: disable=too-many-nested-blocks
        if key == "ports":
            spec_obj.ports = []
            for port in value:
                kube_port = kubernetes.client.V1ServicePort()  # <--------------------
                if isinstance(port, dict):
                    for port_key, port_value in port.items():
                        if hasattr(kube_port, port_key):
                            setattr(kube_port, port_key, port_value)
                else:
                    kube_port.port = port
                spec_obj.ports.append(kube_port)
        elif hasattr(spec_obj, key):
            setattr(spec_obj, key, value)

    return spec_obj

@felixmarch can you go ahead and open a PR? Then we can review it there 👍

Yep, PR #60218 created. Thanks 🤝😄