Awesome
apiextensions
This library provides generated Kubernetes clients for the Giant Swarm infrastructure.
Usage
pkg/apis
: Contains data structures for custom resources in*.giantswarm.io
API groups. See full documentation here.
Contributing
Setup
While the generation scripts can run without a GitHub token defined, you may encounter rate limit errors without one. The
token will be loaded from the GITHUB_TOKEN
environment variable if it exists. Giant Swarm engineers can generally use
export GITHUB_TOKEN=$OPSCTL_GITHUB_TOKEN
to configure this before running make
.
Changing Existing Custom Resources
- Make the desired changes in
pkg/apis/<group>/<version>
. - Update generated files by calling
make generate
. - Review and commit all changes including generated code.
Naming Convention
Custom resource structs are placed in packages corresponding to the endpoints in
Kubernetes API. For example, structs in package
github.com/giantswarm/apiextensions/pkg/apis/infrastructure/v1alpha2
are created
from objects under /apis/infrastructure.giantswarm.io/v1alpha2/
endpoint.
As this is common to have name collisions between field type names in different
custom objects sharing the same group and version (e.g. Spec
or Status
) we prefix all type names
referenced inside custom object with the name of the parent object.
Example:
package v1alpha1
import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
type NewObj struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata"`
Spec NewObjSpec `json:"spec"`
}
type NewObjSpec struct {
Field string `json:"field"`
}
Adding a New Custom Resource
This is example skeleton for adding new object.
- Make sure group and version of the object to add exists (described in previous paragraph).
- Replace
NewObj
with your object name. - Put struct definitions inside a proper package denoted by group and version
in a file named
new_obj_types.go
. Replacenew_obj
with snake_case-formatted object name. - Add
NewObj
andNewObjList
toknownTypes
slice inregister.go
- Generate code for the resource by calling
make
. - Commit changes and create a release.
package v1alpha1
import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
// +genclient
// +genclient:noStatus
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
// NewObj godoc.
type NewObj struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata"`
Spec NewObjSpec `json:"spec"`
}
// NewObjSpec godoc.
type NewObjSpec struct {
FieldName string `json:"fieldName"`
}
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
// NewObjList godoc.
type NewObjList struct {
metav1.TypeMeta `json:",inline"`
metav1.ListMeta `json:"metadata"`
Items []NewObj `json:"items"`
}
Adding a New Group and/or Version
This is example skeleton for adding new group and/or version.
- Replace
GROUP
with new group name andVERSION
with new version name. - Create a new package
/pkg/apis/GROUP/VERSION/
. - Inside the package create a file
doc.go
(content below). - Inside the package create a file
register.go
(content below). - Add a new object (described in next paragraph).
Example doc.go
content.
// +k8s:openapi-gen=true
// +k8s:deepcopy-gen=package,register
// +groupName=GROUP.giantswarm.io
package VERSION
Example register.go
content.
package VERSION
import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
)
const (
group = "GROUP.giantswarm.io"
version = "VERSION"
)
// knownTypes is the full list of objects to register with the scheme. It
// should contain pointers of zero values of all custom objects and custom
// object lists in the group version.
var knownTypes = []runtime.Object{
//&Object{},
//&ObjectList{},
}
// SchemeGroupVersion is group version used to register these objects
var SchemeGroupVersion = schema.GroupVersion{
Group: group,
Version: version,
}
var (
schemeBuilder = runtime.NewSchemeBuilder(addKnownTypes)
// AddToScheme is used by the generated client.
AddToScheme = schemeBuilder.AddToScheme
)
// Adds the list of known types to api.Scheme.
func addKnownTypes(scheme *runtime.Scheme) error {
scheme.AddKnownTypes(SchemeGroupVersion, knownTypes...)
metav1.AddToGroupVersion(scheme, SchemeGroupVersion)
return nil
}
Updating dependencies
Upstream CRDs
apiextensions
generates Giant Swarm CRDs based on code in the pkg/apis
directory and also aggregates CRDs from
various sources. Any repository that publishes CRDs as a YAML-formatted manifest of CRDs attached as an asset to a
GitHub release ("upstream" CRDs) or in a source tree ("remote" CRDs) can be used. The current set of CRDs
including target version is defined in hack/assets.go
in the upstreamReleaseAssets
and remoteRepositories
variables
for upstream and remote CRDs respectively. Update the values and re-run make
to update the aggregated CRDs.
Code Generation Tools
To change the version of a tool, edit the version manually in hack/tools/<tool>/go.mod
and run go mod tidy
in
that directory so that go.sum
is updated.
Versioning
This library uses standard semantic versioning. Versioning of CRDs is a separate issue covered in the Kubernetes deprecation policy. In short, if an API field needs to be removed, a new version must be created, and any versions served concurrently must be convertible in both directions without data loss.
Code generation
This library uses code generation to generate several components so that they do not need to be maintained manually and to reduce the chance of mistakes such as when, for example, defining an OpenAPIV3 schema for a CRD.
Makefile
The Makefile
at the root of the repository ensures that required tools (defined below) are installed in
hack/tools/bin
and then runs each step of the code generation pipeline sequentially.
The main code generation steps are as follows:
generate-deepcopy
: Generateszz_generated.deepcopy.go
in each package inpkg/apis
with deep copy functions.generate-manifests
: Generates CRDs inconfig/crd
from CRs found inpkg/apis
.imports
: Sorts imports in all source files under./pkg
.patch
: Applies the git patchhack/generated.patch
to work around limitations in code generators.
These can all be run with make generate
or simply make
as generate
is the default rule.
Extra commands are provided including:
clean-tools
: Deletes all tools from the tools binary directory.clean-generated
: Deletes all generated files.verify
: Regenerates files and exits with a non-zero exit code if generated files don't matchHEAD
in source control.
Tools
Tools are third-party executables which perform a particular action as part of the code generation pipeline. They are
defined in hack/tools
in separate directories. Versions for the tools are defined in the go.mod
file in their
respective directories. A common go.mod
isn't used so that their dependencies don't interfere.
controller-gen
Generates a custom resource definition (CRD) for each custom resource using special comments such as
// +kubebuilder:validation:Optional
.
goimports
Updates Go import lines by adding missing ones and removing unreferenced ones. This is required because CI checks for imports ordered in three sections (standard library, third-party, local) but certain code generators only generate source files with two sections.
Annotation Documentation
Docs generator has support for documenting annotations. This is achieved by creating code annotations in YAML on the definition of the variables like:
// support:
// - crd: awsclusters.infrastructure.giantswarm.io
// apiversion: v1alpha2
// release: Since 14.0.0
// documentation:
// Here is the documentation related to this annotation
Check AWS Annotations for examples.
The documentation
is later on parsed as Markdown syntax.
Annotations that don't have this YAML format are ignored and not published to the public docs.
Annotations belong to specific API Version of the CRDs but they can be linked to multiple CRDs and multiple API Versions.