Open API and Schema

The client-go library interacts with the Kubernetes API using the Open API specification. This specification defines the structure and behavior of the API, allowing client-go to generate clients and other tools that can interact with the API in a consistent and predictable manner.

The client-go library uses the k8s.io/kube-openapi package for interacting with the Open API specification. This package provides a set of tools and types for working with OpenAPI documents.

The following is an outline of how client-go interacts with the Open API and Schema:

1. Discovering the API:

  • The discovery package in client-go is used to discover the APIs supported by a Kubernetes API server.
  • The discovery package retrieves the Open API schema from the server using the /openapi/v2 endpoint.

2. Accessing the Open API Schema:

  • The OpenAPISchemaInterface interface in the discovery package provides a method for retrieving the Open API schema.
  • The OpenAPISchema() method on the DiscoveryClient retrieves the schema from the server and parses it into a openapi_v2.Document structure.
  • Example code from discovery/discovery_client.go:
// OpenAPISchema retrieves and parses the swagger API schema the server supports.
          func (d *DiscoveryClient) OpenAPISchema() (*openapi_v2.Document, error) {
              data, err := d.restClient.Get().AbsPath("/openapi/v2").SetHeader("Accept", openAPIV2mimePb).Do(context.TODO()).Raw()
              if err != nil {
                  return nil, err
              }
              document := &openapi_v2.Document{}
              err = proto.Unmarshal(data, document)
              if err != nil {
                  return nil, err
              }
              return document, nil
          }
          

3. Using the Open API Schema:

  • The Open API schema provides a comprehensive definition of the Kubernetes API, including:
    • Resource definitions
    • API operations (verbs)
    • Input and output data types
    • Error codes
  • The client-go library uses this schema to generate clients and other tools that can interact with the API in a type-safe and consistent manner.

4. Accessing OpenAPI V3 Schema:

  • The openapi3 package in client-go provides functionality for accessing and working with the Open API V3 schema.
  • The Root interface in the openapi3 package provides methods for accessing the Open API V3 schema for specific API GroupVersions.
  • Example code from openapi3/root.go:
// API Server relative url for all GroupVersions to the relative
          // url for the OpenAPI relative url. Example for single GroupVersion
          // apps/v1:
          //
          //	"apis/apps/v1": {
          //	    "ServerRelativeURL": "/openapi/v3/apis/apps/v1?hash="
          //	}
          type Root interface {
              // GroupVersions returns every GroupVersion for which there is an
              // OpenAPI V3 GroupVersion document. Returns an error for problems
              // retrieving or parsing the OpenAPI V3 root document.
              GroupVersions() ([]schema.GroupVersion, error)
              // GVSpec returns the specification for all the resources in a
              // GroupVersion as a pointer to a spec3.OpenAPI struct.
              // Returns an error for problems retrieving or parsing the root
              // document or GroupVersion OpenAPI V3 document.
              GVSpec(gv schema.GroupVersion) (*spec3.OpenAPI, error)
              // GVSpecAsMap returns the specification for all the resources in a
              // GroupVersion as unstructured bytes. Returns an error for
              // problems retrieving or parsing the root or GroupVersion
              // OpenAPI V3 document.
              GVSpecAsMap(gv schema.GroupVersion) (map[string]interface{}, error)
          }
          

5. Client Generation:

  • client-go provides a mechanism for generating clients based on the Open API schema.
  • These generated clients provide a type-safe and convenient way to interact with the Kubernetes API.
  • The generated clients are highly efficient and performant due to their code generation capabilities.

6. Example Code Snippet (Open API V2 schema retrieval):

package discovery
          
          import (
              "context"
              "encoding/json"
              "fmt"
              "net/http"
          
              openapi_v2 "github.com/googleapis/googleapis/google/api/annotations"
              "k8s.io/apimachinery/pkg/runtime/schema"
              "k8s.io/apimachinery/pkg/util/net"
              "k8s.io/client-go/rest"
          )
          
          // OpenAPISchemaInterface has a method to retrieve the open API schema.
          type OpenAPISchemaInterface interface {
              // OpenAPISchema retrieves and parses the swagger API schema the server supports.
              OpenAPISchema() (*openapi_v2.Document, error)
          }
          
          // OpenAPISchema fetches the open api v2 schema using a rest client and parses the proto.
          func (d *DiscoveryClient) OpenAPISchema() (*openapi_v2.Document, error) {
              data, err := d.restClient.Get().AbsPath("/openapi/v2").SetHeader("Accept", openAPIV2mimePb).Do(context.TODO()).Raw()
              if err != nil {
                  return nil, err
              }
              document := &openapi_v2.Document{}
              err = proto.Unmarshal(data, document)
              if err != nil {
                  return nil, err
              }
              return document, nil
          }
          

7. Example Code Snippet (Open API V3 schema retrieval):

package openapi3
          
          import (
              "context"
              "encoding/json"
              "fmt"
              "net/http"
          
              "k8s.io/apimachinery/pkg/runtime/schema"
              "k8s.io/apimachinery/pkg/util/net"
              "k8s.io/client-go/rest"
              "sigs.k8s.io/yaml"
          )
          
          // root implements the Root interface, and encapsulates the
          // fields to retrieve, store the parsed OpenAPI V3 root document.
          type root struct {
              // OpenAPI client to retrieve the OpenAPI V3 documents.
              client openapi.Client
          }
          
          // NewRoot returns a structure implementing the Root interface,
          // created with the passed rest client.
          func NewRoot(client openapi.Client) Root {
              return &root{client: client}
          }
          

Top-Level Directory Explanations

applyconfigurations/ - This directory contains examples and tests for applying Kubernetes configurations using the client-go library.

discovery/ - This directory contains code related to service discovery in Kubernetes.

dynamic/ - This directory contains code for working with dynamic resources in the Kubernetes API.

features/ - This directory contains experimental features that are not yet stable.

gentype/ - This directory contains generated Go types for the Kubernetes API.

informers/ - This directory contains code for caching Kubernetes resources using informers.

kubernetes/ - This directory contains the main package for the client-go library, which provides types and functions for interacting with the Kubernetes API.

listers/ - This directory contains interfaces and implementations for listing Kubernetes resources.

metadata/ - This directory contains code related to metadata in Kubernetes.

openapi/ - This directory contains OpenAPI definitions for the Kubernetes API.

pkg/ - This directory contains compiled Go packages for the client-go library.

plugin/ - This directory contains code for loading plugins for the client-go library.

rest/ - This directory contains code for working with the REST API in the client-go library.

scale/ - This directory contains code for working with scale and autoscaling in Kubernetes.

tools/ - This directory contains various tools for working with the client-go library.

util/ - This directory contains utility functions for the client-go library.