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

Command tree and exported env in kubectl plugins #45981

Merged

Conversation

fabianofranz
Copy link
Contributor

@fabianofranz fabianofranz commented May 17, 2017

This is part of kubectl plugins V1:

  • Adds support to several env vars passing context information to the plugin. Plugins can make use of them to connect to the REST API, access global flags, get the path of the plugin caller (so that kubectl can be invoked) and so on. Exported env vars include
    • KUBECTL_PLUGINS_DESCRIPTOR_*: the plugin descriptor fields
    • KUBECTL_PLUGINS_GLOBAL_FLAG_*: one for each global flag, useful to access namespace, context, etc
    • KUBECTL_PLUGINS_REST_CLIENT_CONFIG_*: one for most fields in rest.Config so that a REST client can be built.
    • KUBECTL_PLUGINS_CALLER: path to kubectl
    • KUBECTL_PLUGINS_CURRENT_NAMESPACE: namespace in use
  • Adds support for plugins as child of other plugins so that a tree of commands can be built (e.g. kubectl myplugin list, kubectl myplugin add, etc)

Release note:

Added support to a hierarchy of kubectl plugins (a tree of plugins as children of other plugins).

Added exported env vars to kubectl plugins so that plugin developers have access to global flags, namespace, the plugin descriptor and the full path to the caller binary.

@kubernetes/sig-cli-pr-reviews

@k8s-ci-robot k8s-ci-robot added sig/cli Categorizes an issue or PR as relevant to SIG CLI. cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. labels May 17, 2017
@k8s-github-robot k8s-github-robot added size/L Denotes a PR that changes 100-499 lines, ignoring generated files. release-note Denotes a PR that will be considered when it comes time to generate release notes. labels May 17, 2017
@fabianofranz
Copy link
Contributor Author

@k8s-bot bazel test this

@fabianofranz fabianofranz force-pushed the kubectl_plugins_v1_part1 branch 2 times, most recently from 357be18 to a9e790a Compare May 17, 2017 21:18
@fabianofranz
Copy link
Contributor Author

@monopole a couple pieces for V1 here.

Copy link
Contributor

@monopole monopole left a comment

Choose a reason for hiding this comment

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

nice progress

env = append(env, FieldToEnv("ShortDesc", p.Plugin.ShortDesc, prefix))
env = append(env, FieldToEnv("LongDesc", p.Plugin.LongDesc, prefix))
env = append(env, FieldToEnv("Example", p.Plugin.Example, prefix))
env = append(env, FieldToEnv("Command", p.Plugin.Command, prefix))
Copy link
Contributor

Choose a reason for hiding this comment

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

Given that one starts from a literal string, might as well use the final result here rather than have all the reflection-y camelcase and period interpretation, i.e.

env = env.append(env, makePair(prefix + "NAME", p.Plugin.Name))
env = env.append(env, makePair(prefix + "SHORT_DESC", p.Plugin.ShortDesc))

that way one can find this code with a code search on SHORT_DESC.

As it is the code has the complexity of reflection without actually reading from variables.

Plus, if FieldToEnvName doesn't exist, it doesn't need test coverage.

setSource(path, fileInfo, child)
}
}
setSource(path, fileInfo, plugin)
Copy link
Contributor

Choose a reason for hiding this comment

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

well, this looks clever! if you want to add code for subtrees, please also add test coverage.

command trees and env var propagation are orthogonal. RPs that don't mix orthogonal things are easier to review, right? :)

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 have subtrees covered in test-cmd, will also add some unit tests.

Copy link
Contributor

Choose a reason for hiding this comment

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

kthnks.

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 have them in 2 separate commits here, but I'll remember that for the next ones. ;)

env = append(env, plugins.FieldToEnv("APIPath", p.cfg.APIPath, prefix))
env = append(env, plugins.FieldToEnv("Prefix", p.cfg.Prefix, prefix))
env = append(env, plugins.FieldToEnv("Username", p.cfg.Username, prefix))
env = append(env, plugins.FieldToEnv("Password", p.cfg.Password, prefix))
Copy link
Contributor

Choose a reason for hiding this comment

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

This enables a world of perl scripts passing around passwords, certs etc, building libraries that attempt to make restful calls without the benefit of apimachinery client libs.

Wouldn't it be better to fire up a proxy within kubectl, then make that available to the plugin? Pass the (local) port via an env var, and simplify the the job of the plugin author. Maybe hold off on this particular provider?

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'd like to provide plugin authors a way to access the api (other that invoking kubectl through the KUBECTL_PLUGINS_CALLER env we are introducing here), so both ideas work for me. I agree with the concerns of these sensitive data passing around and the proxy is definitely easier for plugin authors, but do you think it would be easier to get approved? If so, that was part of my original plugins R&D and should not be too hard to adjust/improve be added here or in a follow-up PR.

Copy link
Contributor

Choose a reason for hiding this comment

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

@pwittrock might weigh in. Personally I'd rather approve a PR that set up the proxy for the plugin and fed the plugin what it needed to know about the proxy via env vars, than the above code which is simple but enables bad behavior. A proxy would encourage simpler plugins that followed a particular recognizable pattern.

Copy link
Contributor

Choose a reason for hiding this comment

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

as you say - you did a bunch of research on the proxy idea already... just dust it off in a separate PR.

return []string{}, err
}
return []string{fmt.Sprintf("%s=%s", "KUBECTL_PLUGINS_CURRENT_NAMESPACE", cmdNamespace)}, nil
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Nice job on the env provider interface and various impls! Very clear.

One nit: at this level it makes sense to create an array of pair struct {n, v string} and push the

fmt.Sprintf("%s=%s",

(which occurs several times here) down into runner.Run, converting to the format exec.Command seems to need just before it is invoked. That odd detail shouldn't leak up this high.

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'm +1 about a struct pair, the caveat is that os.Environ() already returns []string and it's used in one of the env providers. I'd need to iterate over it and split to make the pairs that would be returned in the provider list. Do you think it's worth?

Copy link
Contributor

Choose a reason for hiding this comment

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

Sigh - didn't see that. Up to you. Seems a bit silly to unpack os.Environ.
OTHO, is osEnviron needed? I'd think a plugin running in subprocess has access to exported vars present in the parent process.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Setting os.Environ is needed, the subprocess only takes what you set there.

@k8s-github-robot k8s-github-robot added the approved Indicates a PR has been approved by an approver from all required OWNERS files. label May 18, 2017
@k8s-github-robot k8s-github-robot added size/XL Denotes a PR that changes 500-999 lines, ignoring generated files. and removed size/L Denotes a PR that changes 100-499 lines, ignoring generated files. labels May 19, 2017
@fabianofranz
Copy link
Contributor Author

@monopole Thanks for the review, PR updated. Addressing comments, more tests added, and the config env provider was removed. An additional way to access the API (likely through proxy) will be in a separate PR.

@monopole
Copy link
Contributor

/lgtm

Thanks!

@k8s-ci-robot k8s-ci-robot added the lgtm "Looks good to me", indicates that a PR is ready to be merged. label May 19, 2017
@k8s-github-robot
Copy link

[APPROVALNOTIFIER] This PR is APPROVED

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

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

@fabianofranz
Copy link
Contributor Author

@k8s-bot pull-kubernetes-federation-e2e-gce test this

1 similar comment
@fabianofranz
Copy link
Contributor Author

@k8s-bot pull-kubernetes-federation-e2e-gce test this

@k8s-ci-robot
Copy link
Contributor

@fabianofranz: The following test(s) failed:

Test name Commit Details Rerun command
pull-kubernetes-federation-e2e-gce 18cb56b link @k8s-bot pull-kubernetes-federation-e2e-gce test this

Full PR test history. Your PR dashboard. Please help us cut down on flakes by linking to an open issue when you hit one in your PR.

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes/test-infra repository. I understand the commands that are listed here.

@k8s-github-robot
Copy link

Automatic merge from submit-queue (batch tested with PRs 46033, 46122, 46053, 46018, 45981)

k8s-github-robot pushed a commit that referenced this pull request May 20, 2017
Automatic merge from submit-queue (batch tested with PRs 46033, 46122, 46053, 46018, 45981)

Command tree and exported env in kubectl plugins

This is part of `kubectl` plugins V1:
- Adds support to several env vars passing context information to the plugin. Plugins can make use of them to connect to the REST API, access global flags, get the path of the plugin caller (so that `kubectl` can be invoked) and so on. Exported env vars include
  - `KUBECTL_PLUGINS_DESCRIPTOR_*`: the plugin descriptor fields
  - `KUBECTL_PLUGINS_GLOBAL_FLAG_*`: one for each global flag, useful to access namespace, context, etc
  - ~`KUBECTL_PLUGINS_REST_CLIENT_CONFIG_*`: one for most fields in `rest.Config` so that a REST client can be built.~
  - `KUBECTL_PLUGINS_CALLER`: path to `kubectl`
  - `KUBECTL_PLUGINS_CURRENT_NAMESPACE`: namespace in use
- Adds support for plugins as child of other plugins so that a tree of commands can be built (e.g. `kubectl myplugin list`, `kubectl myplugin add`, etc)

**Release note**:

```release-note
Added support to a hierarchy of kubectl plugins (a tree of plugins as children of other plugins).

Added exported env vars to kubectl plugins so that plugin developers have access to global flags, namespace, the plugin descriptor and the full path to the caller binary.
```
@kubernetes/sig-cli-pr-reviews
@k8s-github-robot k8s-github-robot merged commit 8fe818b into kubernetes:master May 20, 2017
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/XL Denotes a PR that changes 500-999 lines, ignoring generated files.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants