Adding a new API

To scaffold out a new Kind (you were paying attention to the lastchapter, right?) and correspondingcontroller, we can use kubebuilder create api:

  1. kubebuilder create api --group batch --version v1 --kind CronJob

The first time we call this command for each group-version, it will createa directory for the new group-version.

In this case, theapi/v1/directory is created, corresponding to thebatch.tutorial.kubebuilder.io/v1 (remember our —domainsetting from thebeginning?).

It has also added a file for our CronJob Kind,api/v1/cronjob_types.go. Each time we call the command with a differentkind, it’ll add a corresponding new file.

Let’s take a look at what we’ve been given out of the box, then we canmove on to filling it out.

Apache License

Licensed under the Apache License, Version 2.0 (the “License”);you may not use this file except in compliance with the License.You may obtain a copy of the License at

  1. http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, softwaredistributed under the License is distributed on an “AS IS” BASIS,WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.See the License for the specific language governing permissions andlimitations under the License.

We start out simply enough: we import the meta/v1 API group, which is notnormally exposed by itself, but instead contains metadata common to allKubernetes Kinds.

  1. package v1
  2. import (
  3. metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
  4. )

Next, we get types for the Spec and Status of our Kind. Kubernetes functionsby reconciling desired state (Spec) with actual cluster state (other objects’Status) and external state, and then recording what it observed (Status).Thus, every functional object includes spec and status. A few types, likeConfigMap don’t follow this pattern, since they don’t encode desired state,but most types do.

  1. // EDIT THIS FILE! THIS IS SCAFFOLDING FOR YOU TO OWN!
  2. // NOTE: json tags are required. Any new fields you add must have json tags for the fields to be serialized.
  3. // CronJobSpec defines the desired state of CronJob
  4. type CronJobSpec struct {
  5. // INSERT ADDITIONAL SPEC FIELDS - desired state of cluster
  6. // Important: Run "make" to regenerate code after modifying this file
  7. }
  8. // CronJobStatus defines the observed state of CronJob
  9. type CronJobStatus struct {
  10. // INSERT ADDITIONAL STATUS FIELD - define observed state of cluster
  11. // Important: Run "make" to regenerate code after modifying this file
  12. }

Next, we get the types corresponding to actual Kinds, CronJob and CronJobList.CronJob is our root type, and describes the CronJob kind. Like all Kubernetes objects, it containsTypeMeta (which describes API version and Kind), and also contains ObjectMeta, which holds thingslike name, namespace, and labels.

CronJobList is simply a container for multiple CronJobs. It’s the Kind used in bulk operations,like LIST.

In general, we never modify either of these — all modifications go in either Spec or Status

That little +kubebuilder:object:root comment is called a marker. We’ll seemore of them in a bit, but know that they act as extra metadata, tellingcontroller-tools (our code and YAML generator) extra information.This particular one tells the object generator that this type representsa Kind. Then, the object generator generates an implementation of theruntime.Object interface for us, which is the standardinterface that all types representing Kinds must implement.

  1. // +kubebuilder:object:root=true
  2. // CronJob is the Schema for the cronjobs API
  3. type CronJob struct {
  4. metav1.TypeMeta `json:",inline"`
  5. metav1.ObjectMeta `json:"metadata,omitempty"`
  6. Spec CronJobSpec `json:"spec,omitempty"`
  7. Status CronJobStatus `json:"status,omitempty"`
  8. }
  9. // +kubebuilder:object:root=true
  10. // CronJobList contains a list of CronJob
  11. type CronJobList struct {
  12. metav1.TypeMeta `json:",inline"`
  13. metav1.ListMeta `json:"metadata,omitempty"`
  14. Items []CronJob `json:"items"`
  15. }

Finally, we add the Go types to the API group. This allows us to add thetypes in this API group to any Scheme.

  1. func init() {
  2. SchemeBuilder.Register(&CronJob{}, &CronJobList{})
  3. }

Now that we’ve seen the basic structure, let’s fill it out!