I'm trying the client, but I run into several issues, the main issue at the moment is that I'm unable to create jobs with the client, the code:
import kubernetes.client
from kubernetes import config
from pprint import pprint
config.load_kube_config()
job_name = 'test'
api_instance = kubernetes.client.BatchV1Api()
namespace = 'default'
body = kubernetes.client.V1Job()
body.metadata = kubernetes.client.V1ObjectMeta(name=job_name)
template = kubernetes.client.V1PodTemplate()
template.template = kubernetes.client.V1PodTemplateSpec()
container = kubernetes.client.V1Container(name="busybox")
container.image = "busybox"
container.args = ["sleep", "10"]
container.restart_policy = 'Never'
template.template.spec = kubernetes.client.V1PodSpec(restart_policy='Never', containers=[container])
body.spec = kubernetes.client.V1JobSpec(template=template, backoff_limit=0)
print(str(body))
api_response = api_instance.create_namespaced_job(namespace, body, pretty=True)
pprint(api_response)
The output:
{'api_version': None,
'kind': None,
'metadata': {'annotations': None,
'cluster_name': None,
'creation_timestamp': None,
'deletion_grace_period_seconds': None,
'deletion_timestamp': None,
'finalizers': None,
'generate_name': None,
'generation': None,
'initializers': None,
'labels': None,
'name': 'test',
'namespace': None,
'owner_references': None,
'resource_version': None,
'self_link': None,
'uid': None},
'spec': {'active_deadline_seconds': None,
'backoff_limit': 0,
'completions': None,
'manual_selector': None,
'parallelism': None,
'selector': None,
'template': {'api_version': None,
'kind': None,
'metadata': None,
'template': {'metadata': None,
'spec': {'active_deadline_seconds': None,
'affinity': None,
'automount_service_account_token': None,
'containers': [{'args': ['sleep',
'10'],
'command': None,
'env': None,
'env_from': None,
'image': 'busybox',
'image_pull_policy': None,
'lifecycle': None,
'liveness_probe': None,
'name': 'busybox',
'ports': None,
'readiness_probe': None,
'resources': None,
'security_context': None,
'stdin': None,
'stdin_once': None,
'termination_message_path': None,
'termination_message_policy': None,
'tty': None,
'volume_devices': None,
'volume_mounts': None,
'working_dir': None}],
'dns_config': None,
'dns_policy': None,
'host_aliases': None,
'host_ipc': None,
'host_network': None,
'host_pid': None,
'hostname': None,
'image_pull_secrets': None,
'init_containers': None,
'node_name': None,
'node_selector': None,
'priority': None,
'priority_class_name': None,
'readiness_gates': None,
'restart_policy': 'Never',
'scheduler_name': None,
'security_context': None,
'service_account': None,
'service_account_name': None,
'share_process_namespace': None,
'subdomain': None,
'termination_grace_period_seconds': None,
'tolerations': None,
'volumes': None}}}},
'status': None}
Traceback (most recent call last):
File "job.py", line 32, in <module>
api_response = api_instance.create_namespaced_job(namespace, body, pretty=True)
File "/home/paul/anaconda3/envs/kubeapi-psike/lib/python3.7/site-packages/kubernetes/client/apis/batch_v1_api.py", line 58, in create_namespaced_job
(data) = self.create_namespaced_job_with_http_info(namespace, body, **kwargs)
File "/home/paul/anaconda3/envs/kubeapi-psike/lib/python3.7/site-packages/kubernetes/client/apis/batch_v1_api.py", line 143, in create_namespaced_job_with_http_info
collection_formats=collection_formats)
File "/home/paul/anaconda3/envs/kubeapi-psike/lib/python3.7/site-packages/kubernetes/client/api_client.py", line 321, in call_api
_return_http_data_only, collection_formats, _preload_content, _request_timeout)
File "/home/paul/anaconda3/envs/kubeapi-psike/lib/python3.7/site-packages/kubernetes/client/api_client.py", line 155, in __call_api
_request_timeout=_request_timeout)
File "/home/paul/anaconda3/envs/kubeapi-psike/lib/python3.7/site-packages/kubernetes/client/api_client.py", line 364, in request
body=body)
File "/home/paul/anaconda3/envs/kubeapi-psike/lib/python3.7/site-packages/kubernetes/client/rest.py", line 266, in POST
body=body)
File "/home/paul/anaconda3/envs/kubeapi-psike/lib/python3.7/site-packages/kubernetes/client/rest.py", line 222, in request
raise ApiException(http_resp=r)
kubernetes.client.rest.ApiException: (422)
Reason: Unprocessable Entity
HTTP response headers: HTTPHeaderDict({'Content-Type': 'application/json', 'Date': 'Thu, 02 Aug 2018 17:57:25 GMT', 'Content-Length': '789'})
HTTP response body: {
"kind": "Status",
"apiVersion": "v1",
"metadata": {
},
"status": "Failure",
"message": "Job.batch \"test\" is invalid: [spec.template.spec.containers: Required value, spec.template.spec.restartPolicy: Unsupported value: \"Always\": supported values: \"OnFailure\", \"Never\"]",
"reason": "Invalid",
"details": {
"name": "test",
"group": "batch",
"kind": "Job",
"causes": [
{
"reason": "FieldValueRequired",
"message": "Required value",
"field": "spec.template.spec.containers"
},
{
"reason": "FieldValueNotSupported",
"message": "Unsupported value: \"Always\": supported values: \"OnFailure\", \"Never\"",
"field": "spec.template.spec.restartPolicy"
}
]
},
"code": 422
}
basicly it ignores the actually restartPolicy, or I am doing something wrong.
The underlying issue is documentation and inconsistency:
It seems to be an issue with the objects, if I send a dictionary it is fine. It might have to do with template.template.spec in the code, but if I use template.spec, it won't be included in the resulting dictionary.
I too am stuck with the same problem as reported by @pvanderlinden . By any chance is there a solution available. My use case demands to create Environment variables on the run time when I am creating the K8-Job / Pod. We are creating K8-jobs from an application flow. using YAML doesn't seem to be flexible to do this.
@shanit-saha What I found working the best so far is using a yaml file as template, then with python code fill in the blanks (as it is just basic python structures then (dicts, lists, strings, etc)
@pvanderlinden : Thank You ! for the response and advise.
When I am trying to read the YML template and use it the way you have stated I am getting the error as below
'BatchV1Api' object has no attribute 'select_header_accept'
apiVersion: batch/v1
kind: Job
metadata:
name: dx3-job-test-4
spec:
ttlSecondsAfterFinished: 2
backoffLimit: 4
completions: 1
parallelism: 1
template:
metadata:
name: dx3-job-4
spec:
containers:
- image: "19.0.11.77/ux3user/lab-testdeployment:v1"
name: counter
ports:
- containerPort: 5035
volumeMounts:
- mountPath: /mnt/nfs/dir
name: dx-pv-volume1
resources:
requests:
cpu: 100m
memory: 100Mi
terminationGracePeriodSeconds: 5
restartPolicy: Never
volumes:
- name: dx-pv-volume1
persistentVolumeClaim:
claimName: dx-pv-claim1
@shanit-saha It sounds like you still read it into an object?
What I do:
import ruamel.yaml
# Load yaml file
with open('template.yaml') as fo:
job = ruamel.yaml.safe_load(fo)
# ... manipulate python dict, for example set the name
job['metadata']['name'] = 'test'
# Send
api.create_namespaced_job(
job['metadata']['namespace'], job, pretty=True,
_request_timeout=(settings.CONNECTION_TIMEOUT_SECONDS, settings.READ_TIMEOUT_SECONDS)
)
Same here,
Still there is resolution?
@dsever : I had no issues to create pod and other stuff with the python kubernetes API except for the job object. I have no knowledge if a fix or soultion available with the K8-Api for Job object.
However going by the advice of @pvanderlinden above helped to resolve my problem. Going by his advice this is what I did
a) created a bare minimum K8-Yml specification for a Job . For e.g. 'create_k8job_v1.yml' saved it to a location.
b) Then read that YML with the help of 'ruamel.yaml' object. This returns a JSON dictionary.
c) Then set the values of the K8 job specification as per the usecase needs.
d) Pass the final set to JobBatchClient.create_namespaced_job().
The sample python code synopsys below I think should help.
import ruamel.yaml # assuming a pip install is done :-)
objConfig = config.load_kube_config(path.join(environ["HOME"], '.kube/config'))
k8JobBatchClient = client.BatchV1Api(kubernetes.client.ApiClient(objConfig))
strK8YmlTemplatePath = "/dir-abc/code/k8Job/create_k8job_v1.yml"
fo = open(strK8YmlTemplatePath)
objJob = ruamel.yaml.safe_load(fo)
# Set the custom values of the to-be K8-Job as below
objJob ['metadata']['name'] = "k8-Job-JingaLaLa" # Job Name
objJob ['spec']['template']['spec']['containers'][0]['name'] = "Provide Some Valid ContainerName Here" # Container Name
objJob ['spec']['template']['spec']['containers'][0]['image'] = "Provide some valid Container-Image name"
objJob ['spec']['template']['spec']['containers'][0]['resources']['requests']['cpu'] = '200m'
objJob ['spec']['template']['spec']['containers'][0]['resources']['requests']['memory'] = '512Mi'
# Finally the lines below to create the k8-Job
executionResult = self._k8JobBatchClient.create_namespaced_job("NameSpaceDataPipe", objJob)
# The execution result "executionResult " will be a JSON dictionary
At the end I resolved problem by creating spec key manually.
https://github.com/kubernetes-client/python/issues/755
Fix, should I submit a PR?
def __deserialize_model(self, data, klass):
"""
Deserializes list or dict to model.
:param data: dict, list.
:param klass: class literal.
:return: model object.
"""
if not klass.swagger_types and not hasattr(klass, 'get_real_child_model'):
return data
kwargs = {}
if klass.swagger_types is not None:
for attr, attr_type in iteritems(klass.swagger_types):
if data is not None \
# instead of: klass.attribute_map[attr] in data
and attr in data \
and isinstance(data, (list, dict)):
# instead of: value = data[klass.attribute_map[attr]]
value = data[attr]
kwargs[attr] = self.__deserialize(value, attr_type)
instance = klass(**kwargs)
if hasattr(instance, 'get_real_child_model'):
klass_name = instance.get_real_child_model(data)
if klass_name:
instance = self.__deserialize(data, klass_name)
return instance
Issues go stale after 90d of inactivity.
Mark the issue as fresh with /remove-lifecycle stale.
Stale issues rot after an additional 30d of inactivity and eventually close.
If this issue is safe to close now please do so with /close.
Send feedback to sig-testing, kubernetes/test-infra and/or fejta.
/lifecycle stale
File "/home/koder/workspace/ceph-kaas-controller/ceph_controller/__main__.py", line 344, in set_node_labels
for node in core_api.list_node().items:
File "/home/koder/workspace/venvs/k8s/lib/python3.7/site-packages/kubernetes/client/apis/core_v1_api.py", line 13392, in list_node
(data) = self.list_node_with_http_info(**kwargs)
File "/home/koder/workspace/venvs/k8s/lib/python3.7/site-packages/kubernetes/client/apis/core_v1_api.py", line 13466, in list_node_with_http_info
header_params['Accept'] = self.api_client.\
AttributeError: 'ExtensionsV1beta1Api' object has no attribute 'select_header_accept'
during CoreV1Api().list_nodes()
kubernetes==10.0.0
/remove-lifecycle stale
for https://github.com/kubernetes-client/python/issues/589#issue-347117150, the error message is from apiserver as the request is invalid, job only supports Never or OnFailure as restart policy https://kubernetes.io/docs/concepts/workloads/controllers/jobs-run-to-completion/#writing-a-job-spec (although pod template has an option Always, it's not allowed in job)
I see we are lacking documentation/examples around job creation. I put together a small example in https://github.com/kubernetes-client/python/issues/872#issuecomment-511988833. Contribution to improve our documentation/examples is welcome
Closing as the original question was intended behavior
Most helpful comment
@shanit-saha It sounds like you still read it into an object?
What I do: