1

Is it possible to use the python API to create a "custom object" in kubernetes?

Edit:

By custom objects I'm refering to this.

Thank you.

3
  • Can you be more specific about what you mean by "custom object" Commented Mar 13, 2017 at 19:22
  • Did you check pypi.python.org/pypi/python-k8sclient/0.1.0? Commented Mar 13, 2017 at 22:54
  • Yes. I didn't find any function for custom objects. But there are for ThirdPartyResource. Commented Mar 14, 2017 at 5:04

3 Answers 3

2

Update2024: There is two ways to create a custom object or CRD in kubernetes using python SDK:

  • Normal client: is generated from the Kubernetes API Swagger specification. It provides a strongly typed API with methods specific to each resource type, enabling easy and type-safe interaction with the API. However, it requires pre-defined client objects for each resource type.

code snippet for namespace custom resource creation:

from kubernetes import client, config
# ...(your function definition or your main function)
config.load_kube_config()

api = client.CustomObjectsApi()

# it's my custom resource defined as Dict
my_resource = {
    "apiVersion": "stable.example.com/v1",
    "kind": "CronTab",
    "metadata": {"name": "my-new-cron-object"},
    "spec": {
        "cronSpec": "* * * * */5",
        "image": "my-awesome-cron-image"
    }
}

# patch to update the `spec.cronSpec` field
patch_body = {
    "spec": {"cronSpec": "* * * * */10", "image": "my-awesome-cron-image"}
}

# create the resource
api.create_namespaced_custom_object(
    group="stable.example.com",
    version="v1",
    namespace="default",
    plural="crontabs",
    body=my_resource,
)
print("Resource created")
  • Dynamic client: offers a more flexible and dynamic way to interact with the Kubernetes API. It provides a lower-level interface that allows you to interact with the API using dynamic objects and unstructured data. It may be suitable for your use case where you will create a CRD.

code snippet : namespaced_custom_resource.py

from kubernetes import config, dynamic
from kubernetes.client import api_client
# ...(your function definition or your main function)
# Creating a dynamic client
client = dynamic.DynamicClient(
    api_client.ApiClient(configuration=config.load_kube_config())
)
# get ingressroute api
ingressroute_api = client.resources.get(
    api_version="apps.example.com/v1", kind="IngressRoute"
)
# define resource to be created
ingressroute_manifest = {
    "apiVersion": "apps.example.com/v1",
    "kind": "IngressRoute",
    "metadata": {
        "name": "ingress-route-first",
        "namespace": mynamespace,
    },
    "spec": {
        "virtualhost": {
            "fqdn": "www.google.com",
            "tls": {"secretName": "google-tls"},
        },
        "strategy": "RoundRobin",
    },
}
# create resource
ingressroute_api.create(body=ingressroute_manifest, namespace=mynamespace)

references:

Sign up to request clarification or add additional context in comments.

Comments

1

There isn't a ready-to-use API yet. Here is a rudimentary example using https://github.com/kubernetes-incubator/client-python

import json
from kubernetes import client, config

class ThingyApi(object):
    def __init__(self):
        config = client.Configuration()
        if not config.api_client:
            config.api_client = client.ApiClient()
        self.api_client = config.api_client

    def create_thingy(self, body, namespace='default'):
        resource_path = '/apis/example.com/v1/namespaces/' + namespace + '/thingies'
        header_params = {}
        header_params['Accept'] = self.api_client.select_header_accept(['application/json'])
        header_params['Content-Type'] = self.api_client.select_header_content_type(['*/*'])

        (resp, code, header) = self.api_client.call_api(
                resource_path, 'POST', {'namespace': namespace}, {}, header_params, body, [], _preload_content=False)

        return json.loads(resp.data.decode('utf-8'))

config.load_kube_config()

# Create the ThirdPartyResource (Thingy.example.com)
resp = client.ExtensionsV1beta1Api().create_third_party_resource(body={
    'apiVersion': 'extensions/v1beta1',
    'kind': 'ThirdPartyResource',
    'metadata': {'name': 'thingy.example.com'},
    'description': 'For storage of Thingy objects',
    'versions': [{'name': 'v1'}]})
print("ThirdPartyResource created")
print(str(resp))

# Create 3 Thingy objects (mything-{1,2,3})
thingyapi = ThingyApi()
for i in range(1, 4):
    obj = {'apiVersion': 'example.com/v1',
           'metadata': {'name': 'mythingy-'+str(i)},
           'kind': 'Thingy',
           # Arbitrary contents
           'key': 'value',
           'array': [40, 2],
           'object': {'foo': 'bar'}}
    resp = thingyapi.create_thingy(body=obj, namespace='default')
    print(str(resp))

The output will be something like this:

$ bin/python test.py                                                                                                                                                                    
ThirdPartyResource created
{'api_version': 'extensions/v1beta1',
 'description': 'For storage of Thingy objects',
 'kind': 'ThirdPartyResource',
 'metadata': {'annotations': None,
              'cluster_name': None,
              'creation_timestamp': u'2017-03-14T13:57:07Z',
              'deletion_grace_period_seconds': None,
              'deletion_timestamp': None,
              'finalizers': None,
              'generate_name': None,
              'generation': None,
              'labels': None,
              'name': 'thingy.example.com',
              'namespace': None,
              'owner_references': None,
              'resource_version': '59942',
              'self_link': '/apis/extensions/v1beta1/thirdpartyresourcesthingy.example.com',
              'uid': '1c596824-08be-11e7-9a5f-5254000f561a'},
 'versions': [{'name': 'v1'}]}
{u'kind': u'Thingy', u'object': {u'foo': u'bar'}, u'apiVersion': u'example.com/v1', u'key': u'value', u'array': [40, 2], u'metadata': {u'name': u'mythingy-1', u'namespace': u'default', u'resourceVersion': u'59943', u'creationTimestamp': u'2017-03-14T13:57:07Z', u'selfLink': u'/apis/example.com/v1/namespaces/default/thingies/mythingy-1', u'uid': u'1c59f7ae-08be-11e7-9a5f-5254000f561a'}}
{u'kind': u'Thingy', u'object': {u'foo': u'bar'}, u'apiVersion': u'example.com/v1', u'key': u'value', u'array': [40, 2], u'metadata': {u'name': u'mythingy-2', u'namespace': u'default', u'resourceVersion': u'59944', u'creationTimestamp': u'2017-03-14T13:57:07Z', u'selfLink': u'/apis/example.com/v1/namespaces/default/thingies/mythingy-2', u'uid': u'1c5be2a7-08be-11e7-9a5f-5254000f561a'}}
{u'kind': u'Thingy', u'object': {u'foo': u'bar'}, u'apiVersion': u'example.com/v1', u'key': u'value', u'array': [40, 2], u'metadata': {u'name': u'mythingy-3', u'namespace': u'default', u'resourceVersion': u'59945', u'creationTimestamp': u'2017-03-14T13:57:07Z', u'selfLink': u'/apis/example.com/v1/namespaces/default/thingies/mythingy-3', u'uid': u'1c5c390e-08be-11e7-9a5f-5254000f561a'}}

Don't forget to run this after:

kubectl delete thingy --all
kubectl delete thirdpartyresource thingy.example.com

Comments

1

client-python now supports TPRs. This is the example from the repo:

from __future__ import print_function

from pprint import pprint

import kubernetes
from kubernetes import config
from kubernetes.rest import ApiException

config.load_kube_config()
api_instance = kubernetes.ThirdPartyResources()

namespace = 'default'
resource = 'repos'
fqdn = 'git.k8s.com'

body = {}
body['apiVersion'] = "git.k8s.com/v1"
body['kind'] = "RePo"
body['metadata'] = {}
body['metadata']['name'] = "blog-repo"
body['repo'] = "github.com/user/my-blog"
body['username'] = "username"
body['password'] = "password"
body['branch'] = "branch"



try: 
    # Create a Resource
    api_response = api_instance.apis_fqdn_v1_namespaces_namespace_resource_post(
        namespace, fqdn, resource, body)
    pprint(api_response)
except ApiException as e:
    print(
        "Exception when calling DefaultApi->apis_fqdn_v1_namespaces_namespace_resource_post: %s\n" % 
        e)

ref: https://github.com/kubernetes-incubator/client-python/blob/master/examples/create_thirdparty_resource.md

1 Comment

For which python-client version this works ? I am not able to make it work with 9.0.0 version.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.