zalando-incubator / kopf

A Python framework to write Kubernetes operators in just few lines of code.
https://kopf.readthedocs.io
MIT License
969 stars 87 forks source link

Missing namespace parameter in create_namespaced_pod #294

Open chainhead opened 4 years ago

chainhead commented 4 years ago

Long story short

create_namespaced_pod fails with message ValueError: Missing the required parameter namespace when calling create_namespaced_pod

Description

The controller code - `controller.py`. ```python @kopf.on.create('stable.demo.com', 'v1', 'demo') def create_fn(meta, spec, namespace, logger, **kwargs): name = meta.get('name') image = 'busybox:latest' p = Path(os.getcwd()).parents[1] yamlDir = os.path.join(p, 'yaml') yamlPod = os.path.join(yamlDir,'pod.yaml') tmpl = open(yamlPod, 'rt').read() text = tmpl.format(name=name, image=image) data = yaml.safe_load(text) api = kubernetes.client.CoreV1Api() obj = api.create_namespaced_pod( namespace=namespace, body=data) logger.info('Pod created: %s', obj) ``` Run the controller. ```bash kopf run controller.py --verbose ``` Create an object based on a new CRD. ```bash kubectl create -f example-crd.yaml -n demo ``` Error message: `ValueError: Missing the required parameter namespace when calling create_namespaced_pod`

Environment

Name: kopf
Version: 0.24
Summary: Kubernetes Operator Pythonic Framework (Kopf)
Home-page: https://github.com/zalando-incubator/kopf
Author: Sergey Vasilyev
Author-email: sergey.vasilyev@zalando.de
License: MIT
Location: /usr/local/lib/python3.7/site-packages
Requires: iso8601, click, typing-extensions, aiojobs, aiohttp, pykube-ng
Required-by: 
Client Version: version.Info{Major:"1", Minor:"17", GitVersion:"v1.17.0", GitCommit:"70132b0f130acc0bed193d9ba59dd186f0e634cf", GitTreeState:"clean", BuildDate:"2019-12-13T11:52:32Z", GoVersion:"go1.13.4", Compiler:"gc", Platform:"darwin/amd64"}
Server Version: version.Info{Major:"1", Minor:"17", GitVersion:"v1.17.0", GitCommit:"70132b0f130acc0bed193d9ba59dd186f0e634cf", GitTreeState:"clean", BuildDate:"2019-12-07T21:12:17Z", GoVersion:"go1.13.4", Compiler:"gc", Platform:"linux/amd64"}
Python 3.7.3 (default, Dec 13 2019, 19:58:14) 
[Clang 11.0.0 (clang-1100.0.33.17)] on darwin
Python packages installed ``` aiohttp==3.6.2 aiojobs==0.2.2 async-timeout==3.0.1 attrs==19.3.0 autopep8==1.4.4 cachetools==4.0.0 certifi==2019.11.28 chardet==3.0.4 Click==7.0 google-auth==1.10.1 idna==2.8 iso8601==0.1.12 kopf==0.24 kubernetes==10.0.1 multidict==4.7.4 oauthlib==3.1.0 pip==19.3.1 pyasn1==0.4.8 pyasn1-modules==0.2.8 pycodestyle==2.5.0 pykube-ng==20.1.0 python-dateutil==2.8.1 PyYAML==5.1.2 requests==2.22.0 requests-oauthlib==1.3.0 rsa==4.0 setuptools==42.0.2 six==1.14.0 typing-extensions==3.7.4.1 urllib3==1.25.7 websocket-client==0.57.0 wheel==0.33.6 yarl==1.4.2 ```
nolar commented 4 years ago

@chainhead Is it a cluster-scoped CRD or namespace-scoped? Can you please show the CRD's YAML and pod.yaml?

In any case, it seems like an issue with kubernetes client library, not Kopf. The only way how Kopf can affect it, is namespace=None for cluster-scoped CRDs. But the error message should be different: the parameter is passed, it is just "wrong" (pod's namespace cannot be None).

chainhead commented 4 years ago

My CRD has a scope of Cluster and pod.yaml does not have namespace. Isn't the namespace passed in via the kubectl create -f example-yaml -n someNamespace command?

nolar commented 4 years ago

For custom resources — yes (when it is namespace-scoped). But here, you create a pod, and this pod needs its own namespace specified. Pods cannot be cluster-scoped, they must be namespaced. It can be a namespace of the custom resource, or any other (depends on the domain logic).

kopf.adopt(data) partially solves that task of parent-child relations — see https://kopf.readthedocs.io/en/latest/hierarchies/ — but only if the custom resource itself were namespaced. Your way would also work (namespace=namespace pass-through kwarg). BUT:

When your CR is cluster-scoped, there is no namespace (technically, namespace is None) in the handler's kwargs, and you have to specify the pod's namespace explicitly from some other source. That is by design of the CR scopes (cluster vs. namespaces).

chainhead commented 4 years ago

Thanks for your response; let me run some experiments.