Skip to content

Commit 99276cc

Browse files
committed
add kubectl plugins KEP
1 parent 189d493 commit 99276cc

File tree

2 files changed

+203
-1
lines changed

2 files changed

+203
-1
lines changed

keps/NEXT_KEP_NUMBER

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
24
1+
25

keps/sig-cli/0024-kubectl-plugins.md

Lines changed: 202 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,202 @@
1+
---
2+
kep-number: 24
3+
title: Kubectl Plugins
4+
authors:
5+
- "@juanvallejo"
6+
owning-sig: sig-cli
7+
participating-sigs:
8+
- sig-cli
9+
reviewers:
10+
- "@pwittrock"
11+
- "@deads2k"
12+
- "@liggitt"
13+
- "@soltysh"
14+
approvers:
15+
- "@pwittrock"
16+
- "@soltysh"
17+
editor: juanvallejo
18+
creation-date: 2018-07-24
19+
last-updated: yyyy-mm-dd
20+
status: provisional
21+
see-also:
22+
- n/a
23+
replaces:
24+
- "https://github.com/kubernetes/community/blob/master/contributors/design-proposals/cli/kubectl-extension.md"
25+
- "https://github.com/kubernetes/community/pull/481"
26+
superseded-by:
27+
- n/a
28+
---
29+
30+
# Kubectl Plugins
31+
32+
## Table of Contents
33+
34+
* [Table of Contents](#table-of-contents)
35+
* [Summary](#summary)
36+
* [Motivation](#motivation)
37+
* [Goals](#goals)
38+
* [Non-Goals](#non-goals)
39+
* [Proposal](#proposal)
40+
* [Scenarios](#scenarios)
41+
* [Implementation Details/Design/Constraints](#implementation-detailsdesign)
42+
* [Naming Conventions](#naming-conventions)
43+
* [Implementation Notes/Constraints](#implementation-notesconstraints)
44+
* [Risks and Mitigations](#risks-and-mitigations)
45+
* [Graduation Criteria](#graduation-criteria)
46+
* [Implementation History](#implementation-history)
47+
* [Drawbacks](#drawbacks)
48+
* [Future Improvements/Considerations](#future-improvementsconsiderations)
49+
50+
## Summary
51+
52+
This proposal introduces the main design for a plugin mechanism in `kubectl`.
53+
The mechanism is a git-style system, that looks for executables on a user's `$PATH` whose name begins with `kubectl-`.
54+
This allows plugin binaries to override existing command paths and add custom commands and subcommands to `kubectl`.
55+
56+
## Motivation
57+
58+
The existing alpha plugin system in `kubectl` presents a few limitations with its current design.
59+
It forces plugin scripts and executables to exist in a pre-determined location, requires a per-plugin metadata file for
60+
interpretation, and does not provide a clear way to override existing command paths or provide additional subcommands
61+
without having to override a top-level command.
62+
63+
A re-design plugins system allows us to implement extensibility requests from users that the current system cannot address
64+
(See https://github.com/kubernetes/kubernetes/issues/53640 and https://github.com/kubernetes/kubernetes/issues/55708).
65+
66+
### Goals
67+
68+
* Avoid any kind of installation process (no additional config, users drop an executable in their `PATH`, for example,
69+
and they are then able to use that plugin with `kubectl`).
70+
No additional configuration is needed, only the plugin executable.
71+
A plugin's filename determines the plugin's intention, such as which path in the command tree it applies to:
72+
`/usr/bin/kubectl-educate-dolphins` would, for example be invoked under the command `kubectl educate dolphins --flag1 --flag2`.
73+
It is up to a plugin to parse any arguments and flags given to it. A plugin decides when an argument is a
74+
subcommand, as well as any limitations or constraints that its flags should have.
75+
* Relay all information given to `kubectl` (via command line args) to plugins as-is.
76+
Plugins receive all arguments and flags provided by users and are responsible for adjusting their behavior
77+
accordingly.
78+
* Provide a way to limit which command paths can and cannot be overriddden by plugins in the command tree.
79+
80+
### Non-Goals
81+
82+
* The new plugin mechanism will not be a "plugin installer" or wizard. It will not have specific or baked-in knowledge
83+
regarding a plugin's location or composition, nor will it it provide a way to download or unpack plugins in a correct
84+
location.
85+
* Plugin discovery is not a main focus of this mechanism. As such, it will not attempt to collect data about every
86+
plugin that exists in an environment.
87+
* Plugin management is out of the scope of this design. A mechanism for updating and managing lifecycle of existing
88+
plugins should be covered as a separate design (See https://github.com/kubernetes/community/pull/2340).
89+
* Provide a standard package of common cli utilities that is consumed by `kubectl` and plugins alike.
90+
This should be done as an independent effort of this plugin mechanism.
91+
92+
## Proposal
93+
94+
### Scenarios
95+
96+
* Developer wants to create and expose a plugin to `kubectl`.
97+
They use a programming language of their choice and create an executable file.
98+
The executable's filename consists of the command path to implement, and is prefixed with `kubectl-`.
99+
The executable file is placed on the user's `PATH`.
100+
101+
### Implementation Details/Design
102+
103+
The proposed design passes through all environment variables, flags, input, and output streams exactly as they are given
104+
to the parent `kubectl` process. This has the effect of letting plugins run without the need for any special parsing
105+
or case-handling in `kubectl`.
106+
107+
In essence, a plugin binary must be able to run as a standalone process, completely independent of `kubectl`.
108+
109+
* When `kubectl` is executed with a subcommand _foo_ that does not exist exist in the command tree, it will attempt to look
110+
for a filename `kubectl-foo` (`kubectl-foo.exe` on Windows) in the user's `PATH` and execute it, relaying all arguments given
111+
as well as all environment variables to the plugin child-process.
112+
113+
A brief example (not an actual prototype) is provided below to clarify the core logic of the proposed design:
114+
115+
```go
116+
// treat all args given by the user as pieces of a plugin binary's filename
117+
// and short-circuit once we find an arg that appears to be a flag.
118+
remainingArgs := []string{} // all "non-flag" arguments
119+
120+
for idx := range cmdArgs {
121+
if strings.HasPrefix(cmdArgs[idx], "-") {
122+
break
123+
}
124+
remainingArgs = append(remainingArgs, strings.Replace(cmdArgs[idx], "-", "_", -1))
125+
}
126+
127+
foundBinaryPath := ""
128+
129+
// find binary in the user's PATH, starting with the longest possible filename
130+
// based on the given non-flag arguments by the user
131+
for len(remainingArgs) > 0 {
132+
path, err := exec.LookPath(fmt.Sprintf("kubectl-%s", strings.Join(remainingArgs, "-")))
133+
if err != nil || len(path) == 0 {
134+
remainingArgs = remainingArgs[:len(remainingArgs)-1]
135+
continue
136+
}
137+
138+
foundBinaryPath = path
139+
break
140+
}
141+
142+
// if we are able to find a suitable plugin executable, perform a syscall.Exec call
143+
// and relay all remaining arguments (in order given), as well as environment vars.
144+
syscall.Exec(foundBinaryPath, append([]string{foundBinaryPath}, cmdArgs[len(remainingArgs):]...), os.Environ())
145+
```
146+
147+
#### Naming Conventions
148+
149+
Under this proposal, `kubectl` would identify plugins by looking for filenames beginning with the `kubectl-` prefix.
150+
A search for these names would occur on a user's `PATH`. Only files that are executable and begin with this prefix
151+
would be identified.
152+
153+
### Implementation Notes/Constraints
154+
155+
The current implementation details for the proposed design rely on using a plugin executable's name to determine what
156+
command the plugin is adding.
157+
For a given command `kubectl foo --bar baz`, an executable `kubectl-foo` will be matched on a user's `PATH`,
158+
and the arguments `--bar baz` will be passed to it in that order.
159+
160+
A potential limitation of this could present itself in the order of arguments provided by a user.
161+
A user could intend to run a plugin `kubectl-foo-bar` with the flag `--baz` with the following command
162+
`kubectl foo --baz bar`, but instead end up matching `kubectl-foo` with the flag `--baz` and the argument `bar` based
163+
on the placement of the flag `--baz`.
164+
165+
A notable constraint of this design is that it excludes any form of plugin lifecycle management, or version compatibility.
166+
A plugin may depend on other plugins based on the decision of a plugin author, however the proposed design does nothing
167+
to facilitate such dependencies. It is up to the plugin's author (or a separate / independent plugin management system) to
168+
provide documentation or instructions on how to meet any dependencies required by a plugin.
169+
170+
Further, with the proposed design, plugins that rely on multiple "helper" files to properly function, should provide an
171+
"entrypoint" executable (which is placed on a user's `PATH`), with any additional files located elsewhere (e.g. ~/.kubeplugins/myplugin/helper1.py).
172+
173+
### Risks and Mitigations
174+
175+
Unlike the existing alpha plugin mechanism, the proposed design does not constrain commands added by plugins to exist as subcommands of the
176+
`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).
177+
178+
A potential risk associated with this could present in the form of a "land-rush" by plugin providers.
179+
Multiple plugin authors would be incentivized to provide their own version of plugin `foo`.
180+
Users would be at the mercy of whichever variation of `kubectl-foo` is discovered in their `PATH` first when executing that command.
181+
182+
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`
183+
to include the provider's name, for example: `kubectl-acme-foo`, or `kubectl-companyB-foo`.
184+
185+
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.
186+
187+
## Graduation Criteria
188+
189+
* Make this mechanism a part of `kubectl`'s command-lookup logic.
190+
191+
## Implementation History
192+
193+
This plugin design closely follows major aspects of the plugin system design for `git`.
194+
195+
## Drawbacks
196+
197+
Implementing this design could potentially conflict with any ongoing work that depends on the current alpha plugin system.
198+
199+
## Future Improvements/Considerations
200+
201+
The proposed design is flexible enough to accommodate future updates that could allow certain command paths to be overwritten
202+
or extended (with the addition of subcommands) via plugins.

0 commit comments

Comments
 (0)