The previous chapters explored how the Kubernetes API works at the HTTP level. They also explored the Kubernetes API Library, which defines the resources served by the Kubenretes API in Go.
The API objects embed a common metadata structure, TypeMeta, containing two fields: APIVersion and Kind.
The API objects are provided in a separate package.
The API objects are versioned.
Conversion functions are provided to convert between versions.
- A Scheme abstraction, used to:
Register the API objects as Group-Version-Kinds
Convert between API Objects of different versions
Serialize/deserialize API Objects
A RESTMapper, mapping between API Objects (based on embedded APIVersion and Kind) and resource names (in the REST sense).
This chapter details the functions provided by the API Machinery.
The Schema Package
The structures GroupVersionResource, GroupVersionKind, GroupVersion, GroupResource, and GroupKind are defined, with methods to pass from one to another.
Scheme
A Scheme is an abstraction used to register the API objects as Group-Version-Kinds, convert between API Objects of various versions, and serialize/deserialize API Objects. The Scheme is a structure provided by the API Machinery in the runtime package. All the fields of this structure are unexported.
Initialization
By doing this, the API Machinery will be able to know that the Group-Version-Kind core-v1-Pod to be used when executing requests related to pods must be the corev1.Pod structure, and the core-v1-ConfigMap to be used when executing requests related to configmaps must be the corev1.ConfigMap structure.
It is advisable to initialize the Scheme structure and to add known types to it at the very beginning of the execution—for example, using the init functions.
Mapping
KnownTypes(gv schema.GroupVersion) map[string]reflect.Type – gets all the Go types registered for a specific Group-Version—here apps/v1:
VersionsForGroupKind(gk schema.GroupKind) []schema.GroupVersion – gets all the Group-Versions registered for a specific Kind—here the Deployment:
ObjectKinds(obj Object) ([]schema.GroupVersionKind, bool, error) – gets all the possible Group-Version-Kinds for a given object—here an appsv1.Deployment:
New(kind schema.GroupVersionKind) (Object, error) – builds an object, given a Group-Version-Kind:
This method returns a value of type runtime.Object, which is an interface implemented by all the API objects. The concrete type of the value will be the object mapping the Group-Version-Kind—here appsv1.Deployment.
Conversion
The Scheme structure registers Kinds by Group-Version. By providing to the Scheme conversion functions between kinds of the same Group and different Versions, it is then possible to convert between any kinds of the same Group.
It is possible to define conversion functions of two levels: conversion functions and generated conversion functions. Conversion functions are functions written by hand, when generated conversion functions are generated using the conversion-gen tool.
When converting between two versions, the conversion function, if it exists, will take priority over the generated conversion function.
Adding Conversion Functions
As for registering known types to the scheme, the recommendation is to register conversion functions at the very beginning of the execution—for example, using init functions.
Converting
Serialization
Packages of the API Machinery Library provide serializers for various formats: JSON, YAML, and Protobuf. These serializers implement the Serializer interface, which embeds the Encoder and Decoder interfaces. First, you can see how to instantiate serializers for different formats, then how to use them to encode and decode API objects.
JSON and YAML Serializer
Protobuf Serializer
Encoding and Decoding
Encode(obj Object, w io.Writer) error – the Encode function takes an API object as a parameter, encodes the object, and writes the result using the writer.
Decode(
- this function takes an array of bytes as a parameter and tries to decode its content. If the content to decode does not specify apiVersion and Kind, the default GroupVersionKind (GVK) will be used.
The result will be placed in the into object if not nil and if the concrete type of into matches the content GVK (either the initial one, or the defaults one). In any case, the result will be returned as an Object, and the GVK applied to it will be returned as a GroupVersionKind structure.
RESTMapper
As Chapter 1 discussed, a GVR (Group-Version-Resource, or Resource for short) is used to build the path to which to make a request. For example, to get the list of deployments in all namespaces, you will use the path /apis/apps/v1/deployments, where apps is the Group, v1 is the Version, and deployments is the (plural) Resource name. So, a resource managed by an API can be uniquely identified by its GVR.
When making requests to this path, generally you want to exchange data, either in the request to create or update a resource, or in the response to get or list resources. The format of this exchanged data is called the Kind (or GroupVersionKind), associated with the resource.
Kind to Resource
The RESTMapping and RESTMappings methods return an element or an array of RESTMapping structures as a result, given a Group and Kind. An optional list of versions indicates the preferred versions.
The RESTMappings method returns all matches, the RESTMapping method returns a single match or an error if there are multiple matches. The resulting RESTMapping elements will contain the fully qualified Kind (including the version) and the fully qualified Resource.
To sum up, these methods are used to map a Kind to a Resource.
Resource to Kind
The KindFor and KindsFor methods return an element or an array of GroupVersionKind, given a partial Group-Version-Resource. Partial means that you can omit the group, the version, or both. The resource name can be the singular or the plural name of the resource.
The KindsFor method returns all matches, the KindFor method returns a single match or an error if there are multiple matches.
To sum up, these methods are used to map a Resource to a Kind.
Finding Resources
The ResourceFor and ResourcesFor methods return an element or an array of GroupVersionResource, given a partial Group-Version-Resource. Partial means that you can omit the group, the version, or both. The resource name can be the singular or the plural name of the resource.
The ResourcesFor method returns all matches, the ResourceFor method returns a single match or an error if there are multiple matches.
To sum up, these methods are used to find fully qualified resources based on a singular or plural resource name.
The DefaultRESTMapper Implementation
NewDefaultRESTMapper(
- this factory method is used to build a new DefaultRESTMapper, and accepts a list of default Group-Versions, which will be used to find Resources or Kinds when the provided GVR is partial.
Add(kind schema.GroupVersionKind, scope RESTScope) – this method is used to add a mapping between a Kind and a Resource. The resource name will be guessed from the Kind, by getting the lowercase word, and by pluralizing it (adding “es” to words ending with “s,” replacing terminal “y” with “ies” to words ending with “y,” and adding “s” to other words).
- AddSpecific(kind schema.GroupVersionKind,plural, singular schema.GroupVersionResource,scope RESTScope)
- this method is used to add a mapping between a Kind and a Resource, by giving the singular and plural names explicitly.
After creating a DefaultRESTMapper instance, you can use it as a RESTMapper by calling the methods defined in the interface of the same name.
Conclusion
This chapter has explored the API Machinery, introducing the Scheme abstraction used to serialize resources between Go and JSON or YAML, and to convert resources between several versions. The chapter also covered the RESTMapper interface to help map between resources and kinds.
The next chapter covers the Client-go Library, a high-level one used by developers to call the Kubernetes API without needing to work with HTTP calls.