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

Unable to create jobs #589

Closed
pvanderlinden opened this issue Aug 2, 2018 · 13 comments
Closed

Unable to create jobs #589

pvanderlinden opened this issue Aug 2, 2018 · 13 comments

Comments

@pvanderlinden
Copy link

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:

  • inconsisten behavior: in some cases you need to pass in parameters in the contructor of the object, in some cases you can assign it to a property after creating the object
  • some of the examples are not working
  • the docs of the api client are not that helpful in some cases (I managed to do something with configmaps and listing pods, but I can't create a job at all)
  • it's hard to translate a yaml file into the correct objects
@pvanderlinden
Copy link
Author

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.

@shanit-saha
Copy link

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.

@pvanderlinden
Copy link
Author

@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)

@shanit-saha
Copy link

@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'
================YAML is As below======================================

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

@pvanderlinden
Copy link
Author

@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)
)

@dsever
Copy link

dsever commented Feb 11, 2019

Same here,

Still there is resolution?

@shanit-saha
Copy link

shanit-saha commented Feb 12, 2019

@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

@dsever
Copy link

dsever commented Feb 12, 2019

At the end I resolved problem by creating spec key manually.
#755

@akotlar
Copy link

akotlar commented Mar 29, 2019

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

@fejta-bot
Copy link

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

@k8s-ci-robot k8s-ci-robot added the lifecycle/stale Denotes an issue or PR has remained open with no activity and has become stale. label Jun 27, 2019
@koder-ua
Copy link

koder-ua commented Jul 4, 2019

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

@roycaihw
Copy link
Member

/remove-lifecycle stale

for #589 (comment), 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 #872 (comment). Contribution to improve our documentation/examples is welcome

@k8s-ci-robot k8s-ci-robot removed the lifecycle/stale Denotes an issue or PR has remained open with no activity and has become stale. label Jul 16, 2019
@roycaihw
Copy link
Member

Closing as the original question was intended behavior

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

8 participants