Creating your own plugins

Overview

You can extend the Kubebuilder API to create your own plugins. If extending the CLI, your plugin will be implemented in your project and registered to the CLI as has been done by the SDK project. See its CLI code as an example.

When it is useful?

  • If you are looking to create plugins which support and work with another language.
  • If you would like to create helpers and integrations on top of the scaffolds done by the plugins provided by Kubebuiler.
  • If you would like to have customized layouts according to your needs.

How the plugins can be used?

Kubebuilder provides a set of plugins to scaffold the projects, to help you extend and re-use its implementation to provide additional features. For further information see Available Plugins.

Therefore, if you have a need you might want to propose a solution by adding a new plugin which would be shipped with Kubebuilder by default.

However, you might also want to have your own tool to address your specific scenarios and by taking advantage of what is provided by Kubebuilder as a library. That way, you can focus on addressing your needs and keep your solutions easier to maintain.

Note that by using Kubebuilder as a library, you can import its plugins and then create your own plugins that do customizations on top. For instance, Operator-SDK does with the plugins manifest and scorecard to add its features. Also see here.

Another option implemented with the Extensible CLI and Scaffolding Plugins - Phase 2 is to extend Kibebuilder as a LIB to create only a specific plugin that can be called and used with Kubebuilder as well.

Language-based Plugins

Kubebuilder offers the Golang-based operator plugins, which will help its CLI tool users create projects following the Operator Pattern.

The SDK project, for example, has language plugins for Ansible and Helm, which are similar options but for users who would like to work with these respective languages and stacks instead of Golang.

Note that Kubebuilder provides the kustomize.common.kubebuilder.io to help in these efforts. This plugin will scaffold the common base without any specific language scaffold file to allow you to extend the Kubebuilder style for your plugins.

In this way, currently, you can Extend the CLI and use the Bundle Plugin to create your language plugins such as:

  mylanguagev1Bundle, _ := plugin.NewBundle(plugin.WithName(language.DefaultNameQualifier), 
    plugin.WithVersion(plugin.Version{Number: 1}),
		plugin.WithPlugins(kustomizecommonv1.Plugin{}, mylanguagev1.Plugin{}), // extend the common base from Kubebuilder
		// your plugin language which will do the scaffolds for the specific language on top of the common base
	)

If you do not want to develop your plugin using Golang, you can follow its standard by using the binary as follows:

kubebuilder init --plugins=kustomize

Then you can, for example, create your implementations for the sub-commands create api and create webhook using your language of preference.

Custom Plugins

Note that users are also able to use plugins to customize their scaffolds and address specific needs.

See that Kubebuilder provides the deploy-image plugin that allows the user to create the controller & CRs which will deploy and manage an image on the cluster:

kubebuilder create api --group example.com --version v1alpha1 --kind Memcached --image=memcached:1.6.15-alpine --image-container-command="memcached,-m=64,modern,-v" --image-container-port="11211" --run-as-user="1001" --plugins="deploy-image/v1-alpha"

This plugin will perform a custom scaffold following the Operator Pattern.

Another example is the grafana plugin that scaffolds a new folder container manifests to visualize operator status on Grafana Web UI:

kubebuilder edit --plugins="grafana.kubebuilder.io/v1-alpha"

In this way, by Extending the Kubebuilder CLI, you can also create custom plugins such this one.

Feel free to check the implementation under:

Plugin Scaffolding

Your plugin may add code on top of what is scaffolded by default with Kubebuilder sub-commands(init, create, …). This is common as you may expect your plugin to:

  • Create API
  • Update controller manager logic
  • Generate corresponding manifests

Boilerplates

The Kubebuilder internal plugins use boilerplates to generate the files of code.

For instance, the go/v3 scaffolds the main.go file by defining an object that implements the machinery interface. In the implementation of Template.SetTemplateDefaults, the raw template is set to the body. Such object that implements the machinery interface will later pass to the execution of scaffold.

Similar, you may also design your code of plugin implementation by such reference. You can also view the other parts of the code file given by the links above.

If your plugin is expected to modify part of the existing files with its scaffold, you may use functions provided by sigs.k8s.io/kubebuilder/v3/pkg/plugin/util. See example of deploy-image. In brief, the util package helps you customize your scaffold in a lower level.

Use Kubebuilder Machinery Lib

Notice that Kubebuilder also provides machinery pkg where you can:

  • Define file I/O behavior.
  • Add markers to the scaffolded file.
  • Define the template for scaffolding.

Overwrite A File

You might want for example to overwrite a scaffold done by using the option:

	f.IfExistsAction = machinery.OverwriteFile

Let’s imagine that you would like to have a helper plugin that would be called in a chain with go/v4 to add customizations on top. Therefore after we generate the code calling the subcommand to init from go/v4 we would like to overwrite the Makefile to change this scaffold via our plugin. In this way, we would implement the Bollerplate for our Makefile and then use this option to ensure that it would be overwritten.

See example of deploy-image.

A Combination of Multiple Plugins

Since your plugin may work frequently with other plugins, the executing command for scaffolding may become cumbersome, e.g:

kubebuilder create api --plugins=go/v3,kustomize/v1,yourplugin/v1

You can probably define a method to your scaffolder that calls the plugin scaffolding method in order. See example of deploy-image.

Define Plugin Bundles

Alternatively, you can create a plugin bundle to include the target plugins. For instance:

  mylanguagev1Bundle, _ := plugin.NewBundle(plugin.WithName(language.DefaultNameQualifier), 
        plugin.WithVersion(plugin.Version{Number: 1}),
        plugin.WithPlugins(kustomizecommonv1.Plugin{}, mylanguagev1.Plugin{}), // extend the common base from Kuebebuilder
        // your plugin language which will do the scaffolds for the specific language on top of the common base
    )