-
Notifications
You must be signed in to change notification settings - Fork 21
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
docs: plugin concept docu #1122
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,151 @@ | ||||||||||||||||||||||
# The OCM Library Plugin Concept | ||||||||||||||||||||||
|
||||||||||||||||||||||
The ocm library supports a plugin mechanism to provide further variants | ||||||||||||||||||||||
for OCM and library extension points without the need of extending and recompiling | ||||||||||||||||||||||
the OCM CLI (and other applications using this library). | ||||||||||||||||||||||
|
||||||||||||||||||||||
This plugin concept is not part of the OCM specification, because it is | ||||||||||||||||||||||
a feature of this library implementation. | ||||||||||||||||||||||
|
||||||||||||||||||||||
The following extension points are supported: | ||||||||||||||||||||||
|
||||||||||||||||||||||
- Access methods | ||||||||||||||||||||||
- Uploaders | ||||||||||||||||||||||
- Downloaders | ||||||||||||||||||||||
- Actions | ||||||||||||||||||||||
- Value sets (for example for routing slip entries) | ||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why do we have routing slips in OCM? |
||||||||||||||||||||||
- Config types | ||||||||||||||||||||||
- Value Merge Handler (for example for label values in delta transports) | ||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What does this mean? I am missing explanation on what these points should be able to do. Is that available somewhere else? if so we should link it here I think |
||||||||||||||||||||||
- CLI Commands (for OCM CLI) | ||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I dont understand why we can add CLI Commands to a plugin infrastructure that is supposedly an interface of the library. To me that means the plugin system is not confined to the library, but to the entire codebase.
|
||||||||||||||||||||||
- (transfer handlers) | ||||||||||||||||||||||
- (signing tools) | ||||||||||||||||||||||
- (input types for component version composition) | ||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||||||||||||||
|
||||||||||||||||||||||
## Plugin Technology | ||||||||||||||||||||||
|
||||||||||||||||||||||
A plugin is a simple executable, which might be written in any program language. | ||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||||||||||||||
The plugin has to provide a set of CLI commands for every extension point it provides new variations for. | ||||||||||||||||||||||
|
||||||||||||||||||||||
The data transfer between the library and the plugin is done via | ||||||||||||||||||||||
|
||||||||||||||||||||||
- command options (for inbound information) | ||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What is a command option? something like |
||||||||||||||||||||||
- standard input (for potentially large inbound content (streaming)) | ||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What if a plugin needs multiple data streams? in that case STDIN would not be feasible for both. |
||||||||||||||||||||||
- standard output (for structured outbound information) | ||||||||||||||||||||||
- standard output (for unstructured data (streaming) | ||||||||||||||||||||||
|
||||||||||||||||||||||
The commands and their interface are described in the [plugin reference](../../../docs/pluginreference/plugin.md). | ||||||||||||||||||||||
|
||||||||||||||||||||||
Every plugin must provide the [`info`](../../../docs/pluginreference/plugin_info.md) command. It has to provide information | ||||||||||||||||||||||
about the supported features as JSOn document on standard output. | ||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||||||||||||||
The structure of this document is described by the descriptor type in package [`api/ocm/plugin/descriptor`](descriptor/descriptor.go) | ||||||||||||||||||||||
|
||||||||||||||||||||||
Plugin are searched in a plugin folder (typically `.ocm/plugins`), This default location can be changed by the `plugincachedir` attribute. | ||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
Could you add an example on how this attribute can be changed? |
||||||||||||||||||||||
|
||||||||||||||||||||||
## Plugin-related CLI Commands | ||||||||||||||||||||||
|
||||||||||||||||||||||
The OCM CLI provides commands to | ||||||||||||||||||||||
|
||||||||||||||||||||||
- [install](../../../docs/reference/ocm_install_plugins.md) | ||||||||||||||||||||||
- [update](../../../docs/reference/ocm_install_plugins.md) | ||||||||||||||||||||||
- [list](../../../docs/reference/ocm_get_plugins.md) | ||||||||||||||||||||||
- [examine](../../../docs/reference/ocm_describe_plugins.md) | ||||||||||||||||||||||
- [remove](../../../docs/reference/ocm_install_plugins.md) | ||||||||||||||||||||||
|
||||||||||||||||||||||
plugins. | ||||||||||||||||||||||
|
||||||||||||||||||||||
Plugins can either be installed manually, just by copying the plugin executable to the plugin directory, or by using the CLI commands. They use OCM component versions as installation source. Plugins must have the artifact type `ocmPlugin` and follow the rules for providing multi-platform executables by using separate | ||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. To me it does not make sense that plugins can only be installed as as a component version as an installation source, shouldnt the source be able to come from anything? If I read this it sounds like if I want to use the cli install command and I have a file on the FS my options are
Another naming thing: wouldnt the plugin have a "resource type" instead of an "artifact type"? maybe im confusing things here though |
||||||||||||||||||||||
resources with the same name by different platform attributes as extended identity. (see Go platform and architecture names). | ||||||||||||||||||||||
|
||||||||||||||||||||||
The commands extract the correct variant for the platform the command is running. | ||||||||||||||||||||||
If the given reference does not include a resource identity, the first resource with the correct artifact type is used. | ||||||||||||||||||||||
|
||||||||||||||||||||||
## Support for writing Plugins | ||||||||||||||||||||||
|
||||||||||||||||||||||
To write an OCM plugin in Go, the provided [support library](ppi) can be used. | ||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
checked the relative link, thats working There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why is this library inside the OCM core? That means that every go plugin has to compile the entirety of OCM itself while building, making the Plugins quite big. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This go section deserves its own README.md just about the ppi and is not really part of a concept imo. Happy to hear other opinions |
||||||||||||||||||||||
It provides a complete set of commands for all extension points and a main | ||||||||||||||||||||||
function to run the plugin. | ||||||||||||||||||||||
|
||||||||||||||||||||||
It can be used by a `main` function to run the plugin: | ||||||||||||||||||||||
|
||||||||||||||||||||||
```Go | ||||||||||||||||||||||
package main | ||||||||||||||||||||||
|
||||||||||||||||||||||
import ( | ||||||||||||||||||||||
"os" | ||||||||||||||||||||||
|
||||||||||||||||||||||
"ocm.software/ocm/api/ocm/plugin/ppi" | ||||||||||||||||||||||
"ocm.software/ocm/api/ocm/plugin/ppi/cmds" | ||||||||||||||||||||||
"ocm.software/ocm/api/version" | ||||||||||||||||||||||
"ocm.software/ocm/cmds/demoplugin/accessmethods" | ||||||||||||||||||||||
"ocm.software/ocm/cmds/demoplugin/config" | ||||||||||||||||||||||
"ocm.software/ocm/cmds/demoplugin/uploaders" | ||||||||||||||||||||||
"ocm.software/ocm/cmds/demoplugin/valuesets" | ||||||||||||||||||||||
) | ||||||||||||||||||||||
|
||||||||||||||||||||||
func main() { | ||||||||||||||||||||||
p := ppi.NewPlugin("demo", version.Get().String()) | ||||||||||||||||||||||
|
||||||||||||||||||||||
p.SetShort("demo plugin") | ||||||||||||||||||||||
p.SetLong("plugin providing access to temp files and a check routing slip entry.") | ||||||||||||||||||||||
p.SetConfigParser(config.GetConfig) | ||||||||||||||||||||||
|
||||||||||||||||||||||
p.RegisterAccessMethod(accessmethods.New()) | ||||||||||||||||||||||
u := uploaders.New() | ||||||||||||||||||||||
p.RegisterUploader("testArtifact", "", u) | ||||||||||||||||||||||
p.RegisterValueSet(valuesets.New()) | ||||||||||||||||||||||
err := cmds.NewPluginCommand(p).Execute(os.Args[1:]) | ||||||||||||||||||||||
if err != nil { | ||||||||||||||||||||||
os.Exit(1) | ||||||||||||||||||||||
} | ||||||||||||||||||||||
} | ||||||||||||||||||||||
``` | ||||||||||||||||||||||
|
||||||||||||||||||||||
The library provides an interface type [Plugin](ppi/interface.go) and a standard [implementation](ppi/plugin.go) for this interface. | ||||||||||||||||||||||
|
||||||||||||||||||||||
It is used to configure the desired extension point implementations. Every extension point provides an extension interface and supporting types. | ||||||||||||||||||||||
By implementing and registering such an interface the plugin object gets | ||||||||||||||||||||||
informed about the implemented extension point variants and how they are implemented. | ||||||||||||||||||||||
Comment on lines
+105
to
+107
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||||||||||||||
|
||||||||||||||||||||||
This information is then used by the standard implementation of the `info` command | ||||||||||||||||||||||
to provide an appropriate plugin descriptor. | ||||||||||||||||||||||
Comment on lines
+109
to
+110
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||||||||||||||
|
||||||||||||||||||||||
The support provides a complete command set. Therefore, the extension point implementation have never to deal with the command line interface, everything is described by the provided extension point interfaces. | ||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||||||||||||||
|
||||||||||||||||||||||
The implemented standard commands have access to the plugin object and therefore | ||||||||||||||||||||||
determine whether there is an implementation for an extension point variant requested via the command execution. | ||||||||||||||||||||||
Comment on lines
+114
to
+115
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
I think examples would help here. |
||||||||||||||||||||||
|
||||||||||||||||||||||
If there is an implementation, the CLI interface is just mapped to calls to interface functions of the particular extension point functionality. | ||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
This is quite obvious from the 2 paragraphs above and I vote to remove it |
||||||||||||||||||||||
|
||||||||||||||||||||||
The standard implementation od the commands can be found below the package | ||||||||||||||||||||||
[`api/plugin/ppi/cmds](ppi/cmds), structured by the extension point name and its | ||||||||||||||||||||||
interface operation. (for example [upload/put](ppi/cmds/upload/put/cmd.go)) | ||||||||||||||||||||||
Comment on lines
+119
to
+121
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||||||||||||||
|
||||||||||||||||||||||
## How plugins are used in the library | ||||||||||||||||||||||
|
||||||||||||||||||||||
The library includes the counterpart of the plugin-side support. It is found directly in package [`api/ocm/plugin](.). It shared the descriptor package for the plugin descriptor and provides a separate [Plugin](plugin.go) object type. | ||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why is it part of the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||||||||||||||
|
||||||||||||||||||||||
Such an object provides methods for all extension point functions, which can the appropriate CLI command for its plugin executable. Again, it shields the CLI interface by providing an appropriate Go interface. | ||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why does the OCM Side of the Plugin need a CLI interface at all? |
||||||||||||||||||||||
|
||||||||||||||||||||||
To enable the usage of plugins in an [api/ocm/Context](../internal/context.go), | ||||||||||||||||||||||
the plugins must be registered at this context by calling [api/ocm/plugin/registration/RegisterExtensions](registration/registration.go). | ||||||||||||||||||||||
It used the plugin cache die attribute to setup a plugin cache by reading all the plugin descriptors of the configured plugins and providing appropriate plugin objects. | ||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
whats a die attribute? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What is |
||||||||||||||||||||||
|
||||||||||||||||||||||
For extension points requiring a static registration (like access method) it uses | ||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What is the difference between a static and dynamic registration? this is not covered in this document. And when do you require what? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What is |
||||||||||||||||||||||
the information from the descriptors to determine the provided variants and registers appropriate proxy type implementations at the context. | ||||||||||||||||||||||
|
||||||||||||||||||||||
For extension points supporting an on-demand registration it use | ||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. it is not specified |
||||||||||||||||||||||
the registration handler registration feature of those extension points | ||||||||||||||||||||||
to register an appropriate registration handler using the namespace prefix `plugin`. This handler evaluate sub names to determine the plugin name and extension name in this plugin to provide an extension handler implementation proxy to for ward the handler functionality to the appropriate plugin. | ||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I am missing examples here. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
This sentence is hard to understand because its large. it would be good to break it up |
||||||||||||||||||||||
|
||||||||||||||||||||||
### Extension Proxies | ||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I dont understand the need for an extension proxy because that mapping should be resolvable without it imo. It isnt clear to me from the concept |
||||||||||||||||||||||
|
||||||||||||||||||||||
Regardless, whether it is a static type proxy or handler proxy, the proxy implementation keeps track of it plugin and extension name and maps | ||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
The combination of plugin+extension name does not become clear in this concept doc and I am missing the contract description |
||||||||||||||||||||||
the extension point functionality to the Go interface of the plugin representation, which the calls the appropriate CLI command of the plugin executable. | ||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This sentence is convoluted and basically only says: "An Extension Proxy uses the Plugin & Extension name to call the go interface for the plugin that in turn calls the CLI command on the Plugin Executable" Also im missing flow diagrams for this (and many other) interactions here. |
||||||||||||||||||||||
|
||||||||||||||||||||||
The proxy implementation are found in `plugin` packages below the extension point package (for example the [access method plugin proxy](../extensions/accessmethods/plugin)). | ||||||||||||||||||||||
|
||||||||||||||||||||||
The registration handler registries are typically found in the extension point packages in (for example)) [registrations.go](../extensions/download/registration.go). The general registration handler registration handling is implemented in package [api/utils/registrations](../../utils/registrations). | ||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. registration handler registries and dynamic registrations are not covered well in this document imo and need additional explanation. |
||||||||||||||||||||||
It is called registration handler registry, because it is a registry which provides a namespace to name the types of handlers. It is possible to register registration handlers for a sub namespace, which then handle the registration (and creation) of handlers for a particular extension point (for example download handler). | ||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If that is really why it is called, then this is a very strange concept. Why cant the registration be done natively on the underlying registry? |
||||||||||||||||||||||
|
||||||||||||||||||||||
The `command` extension point is implemented by the CLI package [cmds/ocm/commands/ocmcmds/plugins](../../../cmds/ocm/commands/ocmcmds/plugins). | ||||||||||||||||||||||
Command extensions can be registered for any verb and object type name (even those not yet existing) and are automatically added to the command tree of the CLI. | ||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why do we need this? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.