-
Notifications
You must be signed in to change notification settings - Fork 1.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Feature Request: Plugins Phase 2 #1378
Comments
A few comments on // Universe describes the entire state of file generation
type Universe struct {
// Config stores the project configuration
Config *config.Config `json:"config,omitempty"`
// Boilerplate is the copyright comment added at the top of scaffolded files
Boilerplate string `json:"boilerplate,omitempty"`
// Resource contains the information of the API that is being scaffolded
Resource *resource.Resource `json:"resource,omitempty"`
// Files contains the model of the files that are being scaffolded
Files map[string]*file.File `json:"files,omitempty"`
} One of the main goals behind those PRs is to have file update logic inside About passing the configuration file info, I do think that it should be passed in order to have the access to this file centralized. Also, this would allow plugins to update it, kubebuilder could make a diff of the passed and returned configuration to each plugin and decide to accept that change or not. For example, a plugin should probably not be able to update the repo, domain, version or plugins fields, but adding a resource may be allowed to some plugins, and thus we could have some sort of authorithation mechanism for plugins. |
@Adirio great to hear that you're working on integrating file Concerning out-of-execute file generation/updates: if we can figure out a general method of piping bytes from a binary into the Go runtime, sure. AFAIK that isn't possible for 2 reasons:
Having kubebuilder control what exists in |
Issues go stale after 90d of inactivity. If this issue is safe to close now please do so with Send feedback to sig-testing, kubernetes/test-infra and/or fejta. |
/lifecycle frozen |
So to refresh, the main requirements of plugins phase 2 is to have a true plugin architecture that supports:
The existing experimental plugin interface outlines these aims for the future to replace the in-process demo plugin with an external process plugin. I wanted to propose exploring the use of hasicorp's go-plugin system which allows you to write plugins that communicate over gRPC. This would fulfill our above requirements, plus it's been tested with other CLI tools like terraform, vault etc. Go has an official plugins package but as far as I am aware it does not have cross-language support and seems to be intended more for in-tree plugins than for external users to write their own plugin code. |
Go's plugin package is a bit of a mess, and basically not useful unless the plugins are built alongside the main process. The only thing I'm hesitant about for the hashicorp go-plugin library is that it seems like it's built for long-running plugins and not short-lived plugins, but if it works well for that case, that seems fine. The alternative is just passing JSON/proto back and forth across stdin/stdout, and logging on stderr. |
Based on the investigation on plugin libraries such as the built-in Go's plugin package and Hashicorp’s go-plugin library, we have come to the conclusion that it is more suitable to write our own custom typed plugin library. The built-in plugin library seems to be a non-starter as it is more suitable for in-tree plugins rather than out-of-tree plugins and it doesn’t offer cross language support. Hashicorp’s go-plugin system seems more suitable than built-in go-plugin library as it enables cross language/platform support. However, it is more suited for long running plugins as opposed to short lived plugins and it could be overkill with the usage of protobuf. The plugin specification will include type metadata to allow the potential for using other plugin libraries in the future if the need arises. From an implementation standpoint, we could create a new implementation of our plugin interface based on the type. We can do a type switch on the type of plugin the data is being passed to. For e.g. if it is native go, then we pass the universe directly & if it is a binary wrapper, then we pass the serialized stream of JSON bytes to it. |
just to share; The RFE #2198 seems more +1 motivation for this use case. |
It is partial done, and we have a meta issue which is required as follow up #2600 |
Overview
Phase 1 of the proposed scaffold plugin system is being implemented (#1290) at the time of writing. Progress on phase 2, which adds support for chaining plugins together (more below), will begin shortly afterwards, starting with a proposal doc. Before writing that doc, which will contain implementation details for chaining, I'd like to start a general discussion of how chaining will occur.
Phase 2 requirements, summarized from previous discussions
{name}/{version}
, or ordered map of{name}/{version}
to plugin-specific config.Initial thoughts
Hypothetical CLI setup: a global
--plugins
flag that takes an ordered list of plugin names. The subcommand invoked with--plugins
executes "downstream" plugins from that list that match those the kubebuilder binary knows about.Given that we want to pass some initial universe between plugins, that universe should be initialized by the plugin invoked via CLI (the "base" plugin). For example,
kubebuilder init --plugins addon
will invoke anInit
plugin, which passes its generated state to theaddon
plugin, modifying scaffolded files then writing them to disk.Open questions
Assuming this flow is what we want, a few questions pop up:
Run()
.filepath.Walk
the whole directory.controller-gen
orgo mod init
) will have modified on-disk state.Scaffold.Execute()
)model.Universe
and a node is amodel.File
.model.Universe
will have to be modified to guarantee node immutability.Run()
is not idempotent. A non-naive implementation may require aggregation of scaffold events.Run()
?Run()
to return a list of files to add/delete from a universe rather than havingRun()
write such logic itself.PROJECT
to be present in the universe passed between plugins?Read()
vs.Load()
.For 1., the first approach makes the most sense to me given its pros, but reading the full directory after
Run()
completes feels like a heavy cost to incur for one plugin execution.More context
Related issues: #1249
Related PR's: #1250, #1290
/kind feature
The text was updated successfully, but these errors were encountered: