Skip to content

Commit b647850

Browse files
committed
add new interface system and link to feature branch
1 parent c284873 commit b647850

File tree

1 file changed

+34
-15
lines changed

1 file changed

+34
-15
lines changed

designs/extensible-cli-and-scaffolding-plugins.md

Lines changed: 34 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
# Extensible CLI and Scaffolding Plugins
22

33
## Overview
4+
45
I would like for Kubebuilder to become more extensible, such that it could be imported and used as a library in other projects. Specifically, I'm looking for a way to use Kubebuilder's existing CLI and scaffolding for Go projects, but to also be able to augment the Kubebuilder project structure with other custom project types so that I can support the Kubebuilder workflow with non-Go operators (e.g. operator-sdk's Ansible and Helm-based operators).
56

67
The idea is for Kubebuilder to define one or more plugin interfaces that can be used to drive what the `init`, `create api` and `create webhooks` subcommands do and to add a new `cli` package that other projects can use to integrate out-of-tree plugins with the Kubebuilder CLI in their own projects.
@@ -12,25 +13,29 @@ The idea is for Kubebuilder to define one or more plugin interfaces that can be
1213
* Possibly [#1218](https://github.com/kubernetes-sigs/kubebuilder/issues/1218)
1314

1415
## Prototype implementation
15-
https://github.com/joelanford/kubebuilder-exp
16+
17+
Barebones plugin refactor: https://github.com/joelanford/kubebuilder-exp
18+
Kubebuilder feature branch: https://github.com/kubernetes-sigs/kubebuilder/tree/feature/plugins-part-2-electric-boogaloo
1619

1720
## Plugin interfaces
1821

1922
### Required
23+
2024
Each plugin would minimally be required to implement the `Plugin` interface.
2125

2226
```go
2327
type Plugin interface {
2428
// Version returns the project version that this plugin implements.
2529
// For example, Kubebuilder's Go v2 plugin implementation would return 2.
26-
Version() uint
30+
Version() string
2731
// Name returns a name defining the plugin type.
2832
// For example, Kubebuilder's plugins would return "go".
2933
Name() string
3034
}
3135
```
3236

3337
### Optional
38+
3439
Next, a plugin could optionally implement further interfaces to declare its support for specific Kubebuilder subcommands. For example:
3540
* `InitPlugin` - to initialize new projects
3641
* `CreateAPIPlugin` - to create APIs (and possibly controllers) for existing projects
@@ -39,24 +44,37 @@ Next, a plugin could optionally implement further interfaces to declare its supp
3944
Each of these interfaces would follow the same pattern (see the `InitPlugin` interface example below).
4045

4146
```go
42-
type InitPlugin interface {
47+
type InitPluginGetter interface {
4348
Plugin
49+
// GetInitPlugin returns the underlying InitPlugin interface.
50+
GetInitPlugin() InitPlugin
51+
}
4452

45-
// InitDescription returns a description of what this plugin initializes
46-
// for a new project. It is used to display help.
47-
InitDescription() string
53+
type InitPlugin interface {
54+
GenericSubcommand
55+
}
56+
```
4857

49-
// InitHelp returns one or more examples of the command-line usage
50-
// of this plugin's project initialization support. It is used to display help.
51-
InitExample() string
58+
Each specialized plugin interface can leverage a generic subcommand interface, which prevents duplication of methods while permitting type checking and interface flexibility. A plugin context can be used to preserve default help text in case a plugin does not implement its own.
5259

53-
// BindInitFlags binds the plugin's init flags to the CLI. This allows each
54-
// plugin to define its own command line flags for the `kubebuilder init`
55-
// subcommand.
56-
BindInitFlags(fs *pflag.FlagSet)
60+
```go
61+
type GenericSubcommand interface {
62+
// UpdateContext updates a PluginContext with command-specific help text, like description and examples.
63+
// Can be a no-op if default help text is desired.
64+
UpdateContext(*PluginContext)
65+
// BindFlags binds the plugin's flags to the CLI. This allows each plugin to define its own
66+
// command line flags for the kubebuilder subcommand.
67+
BindFlags(fs *pflag.FlagSet)
68+
// Run runs the subcommand.
69+
Run() error
70+
}
5771

58-
// Init initializes a project.
59-
Init() error
72+
type PluginContext struct {
73+
// Description is a description of what this subcommand does. It is used to display help.
74+
Description string
75+
// Examples are one or more examples of the command-line usage
76+
// of this plugin's project subcommand support. It is used to display help.
77+
Examples string
6078
}
6179
```
6280

@@ -125,6 +143,7 @@ func main() {
125143
## Comments & Questions
126144

127145
### Cobra Commands
146+
128147
As discussed earlier as part of [#1148](https://github.com/kubernetes-sigs/kubebuilder/pull/1148), one goal is to eliminate the use of `cobra.Command` in the exported API of Kubebuilder since that is considered an internal implementation detail.
129148

130149
However, at some point, projects that make use of this extensibility will likely want to integrate their own subcommands. In this proposal, `cli.WithExtraCommands()` _DOES_ expose `cobra.Command` to allow callers to pass their own subcommands to the CLI.

0 commit comments

Comments
 (0)