Skip to content
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

kubectl binary plugins #37499

Merged
merged 2 commits into from
Apr 28, 2017
Merged

Conversation

fabianofranz
Copy link
Contributor

@fabianofranz fabianofranz commented Nov 25, 2016

What this PR does / why we need it:

Introduces the ability to extend kubectl by adding third-party plugins that will be exposed through kubectl.

Plugins are executable commands written in any language. To be included as a plugin, a binary or script file has to

  1. be located under one of the supported plugin path locations:
    1.1 ~/.kubectl/plugins dir
    1.2. one or more directory set in the KUBECTL_PLUGINS_PATH env var
    1.3. the kubectl/plugins dir under one or more directory set in the XDG_DATA_DIRS env var, which defaults to /usr/local/share:/usr/share
  2. in any of the plugin path above, have a subfolder with the plugin file(s)
  3. in the subfolder, contain at least a plugin.yaml file that describes the plugin

Example:

$ cat ~/.kube/plugins/myplugin/plugin.yaml
name: "myplugin"
shortDesc: "My plugin's short description"
command: "echo Hello plugins!"

$ kubectl myplugin
Hello plugins!

In case the plugin declares tunnel: true, the plugin engine will pass the KUBECTL_PLUGIN_API_HOST env var when calling the plugin binary. Plugins can then access the Kube REST API in "http://$KUBECTL_PLUGIN_API_HOST/api" using the same context currently in use by kubectl.

Test plugins are provided in pkg/kubectl/plugins/examples. Just copy (or symlink) the files to ~/.kube/plugins to test.

Which issue this PR fixes:

Related to the discussions in the proposal document: #30086 and kubernetes/community#122.

Release note:

Introduces the ability to extend kubectl by adding third-party plugins. Developer preview, please refer to the documentation for instructions about how to use it.

This change is Reviewable

@k8s-ci-robot k8s-ci-robot added the cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. label Nov 25, 2016
@k8s-github-robot k8s-github-robot added size/L Denotes a PR that changes 100-499 lines, ignoring generated files. release-note-label-needed labels Nov 25, 2016
@fabianofranz fabianofranz changed the title [WIP] [DO-NOT-MERGE] kubectl plugins [WIP] [DO-NOT-MERGE] kubectl binary plugins Nov 28, 2016
@fabianofranz fabianofranz force-pushed the kubectl_plugins branch 3 times, most recently from 3515f17 to 806fb34 Compare November 28, 2016 20:39
@k8s-ci-robot
Copy link
Contributor

Jenkins GCI GKE smoke e2e failed for commit 3515f173e82520fa67b134e85dda4c850f7dbc33. Full PR test history.

The magic incantation to run this job again is @k8s-bot gci gke e2e test this. Please help us cut down flakes by linking to an open flake issue when you hit one in your PR.

@k8s-ci-robot
Copy link
Contributor

Jenkins GKE smoke e2e failed for commit 3515f173e82520fa67b134e85dda4c850f7dbc33. Full PR test history.

The magic incantation to run this job again is @k8s-bot cvm gke e2e test this. Please help us cut down flakes by linking to an open flake issue when you hit one in your PR.

@k8s-ci-robot
Copy link
Contributor

Jenkins CRI GCE Node e2e failed for commit 3515f173e82520fa67b134e85dda4c850f7dbc33. Full PR test history.

The magic incantation to run this job again is @k8s-bot cri node e2e test this. Please help us cut down flakes by linking to an open flake issue when you hit one in your PR.

@k8s-github-robot k8s-github-robot added the needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. label Nov 30, 2016
@k8s-github-robot k8s-github-robot removed the needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. label Dec 2, 2016
@0xmichalis
Copy link
Contributor

@kubernetes/kubectl @kubernetes/sig-cli

@adohe-zz
Copy link

adohe-zz commented Dec 4, 2016

@fabianofranz 👍 I would take a deep look the next Monday.

@@ -47,8 +47,9 @@ const (
RecommendedSchemaName = "schema"
)

var RecommendedHomeFile = path.Join(homedir.HomeDir(), RecommendedHomeDir, RecommendedFileName)
var RecommendedSchemaFile = path.Join(homedir.HomeDir(), RecommendedHomeDir, RecommendedSchemaName)
var RecommenderConfigDir = path.Join(homedir.HomeDir(), RecommendedHomeDir)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

var (
...
)

please 😸

@@ -225,25 +227,25 @@ func NewKubectlCommand(f cmdutil.Factory, in io.Reader, out, err io.Writer) *cob
{
Message: "Basic Commands (Beginner):",
Commands: []*cobra.Command{
NewCmdCreate(f, out, err),
NewCmdCreate(f, out, errOut),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should be passing out and errOut to every single command, as a rule of thumb. Not all our commands write errors to stderr, but should.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, this should be a basic rule.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1


list := PluginList{}
err := filepath.Walk(l.pluginsDir, func(path string, fileInfo os.FileInfo, err error) error {
glog.V(9).Infof("Checking plugin in %s...", path)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd stick with 5 & 6 levels, 7 and above usually contain HTTP data, which will hide this log.


package plugin

type Plugin struct {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This needs to be documented in details so that the plugin writers know what to return here.

@@ -0,0 +1,21 @@
#!/usr/bin/env ruby

if ARGV[0] == "metadata"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If this serves as an example, put detailed comments what/why and where?

puts "I'm the magnificent foo plugin."
puts ""
puts "I can use the API from #{api_host}:"
puts `curl -s #{api_endpoint}`
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I liked this example, b/c it was simple and quite self-explanatory, why removing it?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wanted to make this one as dumb as possible (doesn't even access the API), and then I wrote the more complex kubectl aging which uses API data.

@soltysh
Copy link
Contributor

soltysh commented Dec 5, 2016

This is looking really nice, but most importantly thorough doc is needed for users writing the plugins.

@adohe-zz
Copy link

adohe-zz commented Dec 5, 2016

@soltysh this is just a PoC, still a lot to do, and of course thorough doc is necessary.

@adohe-zz
Copy link

adohe-zz commented Dec 5, 2016

The Helm plugin guide could be a good reference:
https://github.com/kubernetes/helm/blob/master/docs/plugins.md

"github.com/golang/glog"
)

type Plugin struct {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

some comments are necessary here.

return nil
}

cmd := exec.Command(path, "metadata")
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Compared with Helm file based metadata, I am worrying the performance, since this lookup happens every time command execute.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@adohe Absolutely, this is one of my major concerns. While this makes plugins much more portable (everything is in the executable), if definitely doesn't scale well. I'll think about an intermediate idea, maybe cache the metadata, look for a descriptor file first and fallback to the metadata call, something like that.

@fabianofranz
Copy link
Contributor Author

This is looking really nice, but most importantly thorough doc is needed for users writing the plugins.

some comments are necessary here

Definitely, I just didn't do it given the PoC nature of this PR. But it needs both docs and very good inline comments. ;)

@k8s-github-robot k8s-github-robot added release-note Denotes a PR that will be considered when it comes time to generate release notes. and removed release-note-label-needed labels Dec 10, 2016
@k8s-github-robot k8s-github-robot added the needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. label Jan 23, 2017
@fabianofranz
Copy link
Contributor Author

@liggitt @soltysh @pwittrock @monopole PTAL. Plugins are now loaded under kubectl plugin. In a separate commit for easier review.

@fabianofranz fabianofranz force-pushed the kubectl_plugins branch 2 times, most recently from 32b955c to 096285f Compare April 27, 2017 03:00
Copy link
Contributor

@soltysh soltysh left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A small nit, but overall lgtm!

plugin_long = templates.LongDesc(`
Runs a command-line plugin.

Plugins are subcommands that are not part of the major command-line distribution
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's worth mentioning from where these plugins are loaded, I think.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah it started like that but I didn't like the results, too clumsy for a command help. Ahead we'll probably want something better than relying on just the help as the default command run, then we can think of something better. And we will have proper docs which we can link to.

@soltysh
Copy link
Contributor

soltysh commented Apr 27, 2017

@fabianofranz you need to run hack/update-generated-docs.sh as well.

@fabianofranz fabianofranz force-pushed the kubectl_plugins branch 2 times, most recently from e4ca8b0 to 2ee97cb Compare April 27, 2017 15:22
@fabianofranz fabianofranz force-pushed the kubectl_plugins branch 2 times, most recently from 00f8f61 to 1c2b1ae Compare April 27, 2017 18:51
@fabianofranz
Copy link
Contributor Author

@k8s-bot verify test this

@fabianofranz
Copy link
Contributor Author

@k8s-bot unit test this

@fabianofranz
Copy link
Contributor Author

@k8s-bot unit test this

@fabianofranz
Copy link
Contributor Author

@k8s-bot gce etcd3 e2e test this
@k8s-bot unit test this

@fabianofranz
Copy link
Contributor Author

@soltysh @monopole @pwittrock @liggitt FYI on tests green, I'd like to get this merged. I'm already putting together the next PR that will include parts of post-V0 like global flags through env vars, better support for plugin flags and so on.

@0xmichalis
Copy link
Contributor

Very cool work @fabianofranz ! Can't wait to use this. lgtm but I will let one of the main reviewers tag it.

@monopole
Copy link
Contributor

/lgtm

@k8s-ci-robot k8s-ci-robot added the lgtm "Looks good to me", indicates that a PR is ready to be merged. label Apr 28, 2017
@fabianofranz fabianofranz added the approved Indicates a PR has been approved by an approver from all required OWNERS files. label Apr 28, 2017
@smarterclayton
Copy link
Contributor

/approve

for remaining code given agreement from sig owners and that this is initial

@k8s-github-robot
Copy link

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: fabianofranz, monopole, smarterclayton, soltysh

Needs approval from an approver in each of these OWNERS Files:

You can indicate your approval by writing /approve in a comment
You can cancel your approval by writing /approve cancel in a comment

@k8s-github-robot
Copy link

Automatic merge from submit-queue

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
approved Indicates a PR has been approved by an approver from all required OWNERS files. cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. lgtm "Looks good to me", indicates that a PR is ready to be merged. release-note Denotes a PR that will be considered when it comes time to generate release notes. sig/cli Categorizes an issue or PR as relevant to SIG CLI. size/XXL Denotes a PR that changes 1000+ lines, ignoring generated files.
Projects
None yet
Development

Successfully merging this pull request may close these issues.