openshift/openshift-restclient-python

How to use dynamic client with create_namespaced_route

michalrabinowitch opened this issue · 3 comments

I am a bit confused with two methods I saw to create routes:
1)
resp = v1_routes.create(body=route_data, namespace='default') from the README.md where body is a string loaded with yaml.load(str)
2) second method found in
https://github.com/openshift/openshift-restclient-python/blob/master/openshift/docs/RouteOpenshiftIoV1Api.md

uses an api client with configuration that includes API_KEY 
# create an instance of the API class
api_instance = openshift.client.RouteOpenshiftIoV1Api(openshift.client.ApiClient(configuration))
namespace = 'namespace_example' # str | object name and auth scope, such as for teams and projects
body = openshift.client.V1Route() # V1Route | 

try: 
    api_response = api_instance.create_namespaced_route(namespace, body, pretty=pretty)
    pprint(api_response)
except ApiException as e:
    print("Exception when calling RouteOpenshiftIoV1Api->create_namespaced_route: %s\n" % e)


I am used to the kubernetes python client where you can pass a dictionary as body.
I want to use create_namespaced_route and not the string with yaml load method.
My questions are:

  1. Why is the yaml.load() method presented in the READ.md and not the second option which is in the spirit of the k8s python client?
    2)What is the configuration information needed here:
    # Configure API key authorization: BearerToken configuration = openshift.client.Configuration() configuration.api_key['authorization'] = 'YOUR_API_KEY' Uncomment below to setup prefix (e.g. Bearer) for API key, if needed# configuration.api_key_prefix['authorization'] = 'Bearer' Configure OAuth2 access token for authorization: Oauth2AccessToken configuration = openshift.client.Configuration() configuration.access_token = 'YOUR_ACCESS_TOKEN' Configure OAuth2 access token for authorization: Oauth2Implicit configuration = openshift.client.Configuration() configuration.access_token = 'YOUR_ACCESS_TOKEN'

Any example you can share would be great. Thanks!

Thank you for the issue. I will start with a little background.

The examples that you see featured so prominently are using a dynamic client. This client uses a single model and client to generically interact with resources in the cluster. If you look closely at the source you'll see that it's primary responsibility is to build URLs in order to pass the requests directly to the kubernetes API server.

  1. second method found in
    https://github.com/openshift/openshift-restclient-python/blob/master/openshift/docs/RouteOpenshiftIoV1Api.md
    uses an api client with configuration that includes API_KEY (not sure what this is exactly - my kube/config info?)

Here you are referencing our, now deprecated, generated client. In our README, way down at the bottom, you can see reference to our Generated client usage. We aren't actively supporting/maintaining this client because of it's limitations.

There are a lot of reasons for the move to a dynamic client but I believe the two strongest reasons are:

  1. Maintainability - the dynamic client is less than 700 lines, orders of magnitude smaller than the generated client
  2. The ability to talk to the k8s API server directly - using the dynamic client you can manage custom resources and talk to aggregated API servers

Now to try and answer questions.

I am used to the kubernetes python client where you can pass a dictionary as body.
I want to use create_namespaced_route and not the string with yaml load method.

yaml.load(string) returns a dictionary so this should not be dissimilar to what you would see from the kubernetes python client. I would highly recommend against using create_namespaced_route as it is deprecated and not long for this world. Looking at the create a route example, it could easily be modified to work without a string:

import yaml
from kubernetes import client, config
from openshift.dynamic import DynamicClient

k8s_client = config.new_client_from_config()
dyn_client = DynamicClient(k8s_client)

route = {
  'apiVersion': 'route.openshift.io/v1',
  'kind': 'Route',
  'metadata': { 'name': 'frontend'},
  'spec': { 'host': 'www.example.com', 'to': { 'kind': 'Service', 'name': 'my-service'}}
}

v1_routes = dyn_client.resources.get(api_version='route.openshift.io/v1', kind='Route')
resp = v1_routes.create(body=route_data, namespace='default')
  1. Why is the yaml.load() method presented in the READ.md and not the second option which is in the spirit of the k8s python client?

The second option is not mentioned in the README as, for reasons stated above, it is deprecated and no longer maintained/supported.

What is the configuration information needed here (referencing the configuration object).

Both clients, dynamic and generated, rely exclusively on the Kubernetes client. I think this portion from the Usage section of our Readme will be helpful to you:

The Kubernetes client object requires a Kubernetes Config that can be set in the Config class or using a helper utility. All of the examples that follow make use of the new_client_from_config() helper utility provided by the Kubernetes Client Config that returns an API client to be used with any API object. There are plenty of Kubernetes Client examples to examine other ways of accessing Kubernetes Clusters.

I hope that this helps to explain what you are seeing in the README and provides you with a path forward. I'm really excited about the dynamic client and think you should give it a shot. If you have any more questions or suggestions on how we could improve the README (like explaining the background some or more examples), please feel free to write an issue, or even better, submit a PR 😎

@michalrabinowitch was I able to answer your questions?

@djzager Thanks a lot for your detailed answer, super helpful ! I'm routing away :)