Skip to content

Repository files navigation

kubernetes-api

Clojars Project

kubernetes-api is a Clojure library that acts as a kubernetes client

Motivation

We had a good experience with cognitect-labs/aws-api, and missed something like that for Kubernetes API. We had some client libraries that generated a lot of code, but it lacked discoverability and documentation.

clojure.deps

{:deps {nubank/k8s-api {:mvn/version "1.1.0"}}}

Leiningen

[nubank/k8s-api "1.1.0"]
;; In your ns statement
(ns my.ns
  (:require [kubernetes-api.core :as k8s]))

Usage

Instantiate a client

There're multiple options for authentication while instantiating a client. You can explicit set a token:

(def k8s (k8s/client "http://some.host" {:token "..."}))

Or a function that returns the token

(def k8s (k8s/client "http://some.host" {:token-fn (constantly "...")}))

You can also define client certificates

(def k8s (k8s/client "http://some.host" {:ca-cert     "/some/path/ca-docker.crt"
                                         :client-cert "/some/path/client-cert.pem"
                                         :client-key  "/some/path/client-java.key"}))

kubeconfig loader

You can load configuration from a kubeconfig file, either by explicit setting it, or by setting the environment variable KUBECONFIG. It also supports multiple files

(def k8s (->> (loader.kubeconfig/load-context
                {:kubeconfig "/path/to/some/kubeconfig.yaml"
                 :context "prod-xpto-000-context"})
              (k8s/from-context)))

; load from KUBECONFIG or defaulting to ~/.kube/config
(def k8s (->> (loader.kubeconfig/load-context
                {:context "prod-xpto-000-context"})
              (k8s/from-context)))

; load multiple files. It will find the first context that matches.
(def k8s (->> (loader.kubeconfig/load-context
                {:kubeconfig ["/path/to/some/kubeconfig.yaml"
                              "/path/to/another/kubeconfig.yaml"]
                 :context "prod-xpto-000-context"})
              (k8s/from-context)))

OpenAPI config

Discovery

It's possible but NOT RECOMMENDED to disable the OpenAPI specification discovery. This will prevent requests to /openapi/... endpoints and use the specification from the resources folder. This specification has no guarantees in terms of versioning, so it will be outdated.

(def k8s (k8s/client "http://some.host" {:token "..."
                                         :openapi {:discovery :disabled}}))
Filter paths from api

You can filter the paths from the OpenAPI specification. This is useful when you want to use a specific version of the api, or when you want to use a specific group of resources.

(def k8s (k8s/client "http://some.host" {:token "..."
                                         :apis  ["some.api/v1alpha1", "another.api"]}))

Discover

You can list all operations with

(k8s/explore k8s)

or specify a specific entity

(k8s/explore k8s :Deployment)
;=>
[:Deployment
 [:get "read the specified Deployment"]
 [:update "replace the specified Deployment"]
 [:delete "delete a Deployment"]
 [:patch "partially update the specified Deployment"]
 [:list "list or watch objects of kind Deployment"]
 [:create "create a Deployment"]
 [:deletecollection "delete collection of Deployment"]
 [:list-all "list or watch objects of kind Deployment"]]

get info on an operation

(k8s/info k8s {:kind :Deployment
               :action :create})
;=>
{:summary "create a Deployment",
 :parameters {:namespace java.lang.String,
              #schema.core.OptionalKey{:k :pretty} (maybe Str),
              #schema.core.OptionalKey{:k :dry-run} (maybe Str),
              #schema.core.OptionalKey{:k :field-manager} (maybe Str),
              :body ...},
 :returns {200 {#schema.core.OptionalKey{:k :apiVersion} (maybe Str),
                #schema.core.OptionalKey{:k :kind} (maybe Str),
                #schema.core.OptionalKey{:k :metadata} ...,
                #schema.core.OptionalKey{:k :spec} ...,
                #schema.core.OptionalKey{:k :status} ...},
           201 {#schema.core.OptionalKey{:k :apiVersion} (maybe Str),
                #schema.core.OptionalKey{:k :kind} (maybe Str),
                #schema.core.OptionalKey{:k :metadata} ...,
                #schema.core.OptionalKey{:k :spec} ...,
                #schema.core.OptionalKey{:k :status} ...},
           202 {#schema.core.OptionalKey{:k :apiVersion} (maybe Str),
                #schema.core.OptionalKey{:k :kind} (maybe Str),
                #schema.core.OptionalKey{:k :metadata} ...,
                #schema.core.OptionalKey{:k :spec} ...,
                #schema.core.OptionalKey{:k :status} ...},
           401 Any}}

Invoke

You can call an operation with

(k8s/invoke k8s {:kind    :ConfigMap
                 :action  :create
                 :request {:namespace "default"
                           :body      {:api-version "v1"
                                       :data       {"foo" "bar"}}}})

invoke it will return the body, with :request and :response in metadata

(meta (k8s/invoke ...))
;=>
{:request ...
 :response {:status ...
            :body ...}}

You can debug the request map with

(k8s/request k8s {:kind    :ConfigMap
                  :action  :create
                  :request {:namespace "default"
                            :body      {:api-version "v1"
                                        :data       {"foo" "bar"}}}})

If you want to read more about all different patch strategies Kubernetes offers, check this document

About

Kubernetes client, data driven

Topics

Resources

Stars

164 stars

Watchers

742 watching

Forks

Releases

Packages

Used by

Contributors

Languages