From 99276cc1cffdaf124d40820a3911622509ee48be Mon Sep 17 00:00:00 2001
From: juanvallejo
Date: Tue, 24 Jul 2018 13:15:21 -0400
Subject: [PATCH] add kubectl plugins KEP
---
keps/NEXT_KEP_NUMBER | 2 +-
keps/sig-cli/0024-kubectl-plugins.md | 202 +++++++++++++++++++++++++++
2 files changed, 203 insertions(+), 1 deletion(-)
create mode 100644 keps/sig-cli/0024-kubectl-plugins.md
diff --git a/keps/NEXT_KEP_NUMBER b/keps/NEXT_KEP_NUMBER
index a45fd52cc58..7273c0fa8c5 100644
--- a/keps/NEXT_KEP_NUMBER
+++ b/keps/NEXT_KEP_NUMBER
@@ -1 +1 @@
-24
+25
diff --git a/keps/sig-cli/0024-kubectl-plugins.md b/keps/sig-cli/0024-kubectl-plugins.md
new file mode 100644
index 00000000000..79384dcaa34
--- /dev/null
+++ b/keps/sig-cli/0024-kubectl-plugins.md
@@ -0,0 +1,202 @@
+---
+kep-number: 24
+title: Kubectl Plugins
+authors:
+ - "@juanvallejo"
+owning-sig: sig-cli
+participating-sigs:
+ - sig-cli
+reviewers:
+ - "@pwittrock"
+ - "@deads2k"
+ - "@liggitt"
+ - "@soltysh"
+approvers:
+ - "@pwittrock"
+ - "@soltysh"
+editor: juanvallejo
+creation-date: 2018-07-24
+last-updated: yyyy-mm-dd
+status: provisional
+see-also:
+ - n/a
+replaces:
+ - "https://github.com/kubernetes/community/blob/master/contributors/design-proposals/cli/kubectl-extension.md"
+ - "https://github.com/kubernetes/community/pull/481"
+superseded-by:
+ - n/a
+---
+
+# Kubectl Plugins
+
+## Table of Contents
+
+* [Table of Contents](#table-of-contents)
+* [Summary](#summary)
+* [Motivation](#motivation)
+ * [Goals](#goals)
+ * [Non-Goals](#non-goals)
+* [Proposal](#proposal)
+ * [Scenarios](#scenarios)
+ * [Implementation Details/Design/Constraints](#implementation-detailsdesign)
+ * [Naming Conventions](#naming-conventions)
+ * [Implementation Notes/Constraints](#implementation-notesconstraints)
+ * [Risks and Mitigations](#risks-and-mitigations)
+* [Graduation Criteria](#graduation-criteria)
+* [Implementation History](#implementation-history)
+* [Drawbacks](#drawbacks)
+* [Future Improvements/Considerations](#future-improvementsconsiderations)
+
+## Summary
+
+This proposal introduces the main design for a plugin mechanism in `kubectl`.
+The mechanism is a git-style system, that looks for executables on a user's `$PATH` whose name begins with `kubectl-`.
+This allows plugin binaries to override existing command paths and add custom commands and subcommands to `kubectl`.
+
+## Motivation
+
+The existing alpha plugin system in `kubectl` presents a few limitations with its current design.
+It forces plugin scripts and executables to exist in a pre-determined location, requires a per-plugin metadata file for
+interpretation, and does not provide a clear way to override existing command paths or provide additional subcommands
+without having to override a top-level command.
+
+A re-design plugins system allows us to implement extensibility requests from users that the current system cannot address
+(See https://github.com/kubernetes/kubernetes/issues/53640 and https://github.com/kubernetes/kubernetes/issues/55708).
+
+### Goals
+
+* Avoid any kind of installation process (no additional config, users drop an executable in their `PATH`, for example,
+ and they are then able to use that plugin with `kubectl`).
+ No additional configuration is needed, only the plugin executable.
+ A plugin's filename determines the plugin's intention, such as which path in the command tree it applies to:
+ `/usr/bin/kubectl-educate-dolphins` would, for example be invoked under the command `kubectl educate dolphins --flag1 --flag2`.
+ It is up to a plugin to parse any arguments and flags given to it. A plugin decides when an argument is a
+ subcommand, as well as any limitations or constraints that its flags should have.
+* Relay all information given to `kubectl` (via command line args) to plugins as-is.
+ Plugins receive all arguments and flags provided by users and are responsible for adjusting their behavior
+ accordingly.
+* Provide a way to limit which command paths can and cannot be overriddden by plugins in the command tree.
+
+### Non-Goals
+
+* The new plugin mechanism will not be a "plugin installer" or wizard. It will not have specific or baked-in knowledge
+ regarding a plugin's location or composition, nor will it it provide a way to download or unpack plugins in a correct
+ location.
+* Plugin discovery is not a main focus of this mechanism. As such, it will not attempt to collect data about every
+ plugin that exists in an environment.
+* Plugin management is out of the scope of this design. A mechanism for updating and managing lifecycle of existing
+ plugins should be covered as a separate design (See https://github.com/kubernetes/community/pull/2340).
+* Provide a standard package of common cli utilities that is consumed by `kubectl` and plugins alike.
+ This should be done as an independent effort of this plugin mechanism.
+
+## Proposal
+
+### Scenarios
+
+* Developer wants to create and expose a plugin to `kubectl`.
+ They use a programming language of their choice and create an executable file.
+ The executable's filename consists of the command path to implement, and is prefixed with `kubectl-`.
+ The executable file is placed on the user's `PATH`.
+
+### Implementation Details/Design
+
+The proposed design passes through all environment variables, flags, input, and output streams exactly as they are given
+to the parent `kubectl` process. This has the effect of letting plugins run without the need for any special parsing
+or case-handling in `kubectl`.
+
+In essence, a plugin binary must be able to run as a standalone process, completely independent of `kubectl`.
+
+* When `kubectl` is executed with a subcommand _foo_ that does not exist exist in the command tree, it will attempt to look
+for a filename `kubectl-foo` (`kubectl-foo.exe` on Windows) in the user's `PATH` and execute it, relaying all arguments given
+as well as all environment variables to the plugin child-process.
+
+A brief example (not an actual prototype) is provided below to clarify the core logic of the proposed design:
+
+```go
+// treat all args given by the user as pieces of a plugin binary's filename
+// and short-circuit once we find an arg that appears to be a flag.
+remainingArgs := []string{} // all "non-flag" arguments
+
+for idx := range cmdArgs {
+ if strings.HasPrefix(cmdArgs[idx], "-") {
+ break
+ }
+ remainingArgs = append(remainingArgs, strings.Replace(cmdArgs[idx], "-", "_", -1))
+}
+
+foundBinaryPath := ""
+
+// find binary in the user's PATH, starting with the longest possible filename
+// based on the given non-flag arguments by the user
+for len(remainingArgs) > 0 {
+ path, err := exec.LookPath(fmt.Sprintf("kubectl-%s", strings.Join(remainingArgs, "-")))
+ if err != nil || len(path) == 0 {
+ remainingArgs = remainingArgs[:len(remainingArgs)-1]
+ continue
+ }
+
+ foundBinaryPath = path
+ break
+}
+
+// if we are able to find a suitable plugin executable, perform a syscall.Exec call
+// and relay all remaining arguments (in order given), as well as environment vars.
+syscall.Exec(foundBinaryPath, append([]string{foundBinaryPath}, cmdArgs[len(remainingArgs):]...), os.Environ())
+```
+
+#### Naming Conventions
+
+Under this proposal, `kubectl` would identify plugins by looking for filenames beginning with the `kubectl-` prefix.
+A search for these names would occur on a user's `PATH`. Only files that are executable and begin with this prefix
+would be identified.
+
+### Implementation Notes/Constraints
+
+The current implementation details for the proposed design rely on using a plugin executable's name to determine what
+command the plugin is adding.
+For a given command `kubectl foo --bar baz`, an executable `kubectl-foo` will be matched on a user's `PATH`,
+and the arguments `--bar baz` will be passed to it in that order.
+
+A potential limitation of this could present itself in the order of arguments provided by a user.
+A user could intend to run a plugin `kubectl-foo-bar` with the flag `--baz` with the following command
+`kubectl foo --baz bar`, but instead end up matching `kubectl-foo` with the flag `--baz` and the argument `bar` based
+on the placement of the flag `--baz`.
+
+A notable constraint of this design is that it excludes any form of plugin lifecycle management, or version compatibility.
+A plugin may depend on other plugins based on the decision of a plugin author, however the proposed design does nothing
+to facilitate such dependencies. It is up to the plugin's author (or a separate / independent plugin management system) to
+provide documentation or instructions on how to meet any dependencies required by a plugin.
+
+Further, with the proposed design, plugins that rely on multiple "helper" files to properly function, should provide an
+"entrypoint" executable (which is placed on a user's `PATH`), with any additional files located elsewhere (e.g. ~/.kubeplugins/myplugin/helper1.py).
+
+### Risks and Mitigations
+
+Unlike the existing alpha plugin mechanism, the proposed design does not constrain commands added by plugins to exist as subcommands of the
+`kubectl plugin` design. Commands provided by plugins under the new mechanism can be invoked as first-class commands (`/usr/bin/kubectl-foo` provides the `kubectl foo` parent command).
+
+A potential risk associated with this could present in the form of a "land-rush" by plugin providers.
+Multiple plugin authors would be incentivized to provide their own version of plugin `foo`.
+Users would be at the mercy of whichever variation of `kubectl-foo` is discovered in their `PATH` first when executing that command.
+
+A way to mitigate the above scenario would be to have users take advantage of the proposed plugin mechanism's design by renaming multiple variations of `kubectl-foo`
+to include the provider's name, for example: `kubectl-acme-foo`, or `kubectl-companyB-foo`.
+
+Conflicts such as this one could further be mitigated by a plugin manager, which could perform conflict resolution among similarly named plugins on behalf of a user.
+
+## Graduation Criteria
+
+* Make this mechanism a part of `kubectl`'s command-lookup logic.
+
+## Implementation History
+
+This plugin design closely follows major aspects of the plugin system design for `git`.
+
+## Drawbacks
+
+Implementing this design could potentially conflict with any ongoing work that depends on the current alpha plugin system.
+
+## Future Improvements/Considerations
+
+The proposed design is flexible enough to accommodate future updates that could allow certain command paths to be overwritten
+or extended (with the addition of subcommands) via plugins.