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

fix: Bind kube client configuration flags before instantiating a kube client #42

Merged
merged 1 commit into from
Aug 21, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
94 changes: 36 additions & 58 deletions pkg/cmd/list.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ type Action struct {
nonResourceURL string
subResource string
resourceName string
gr schema.GroupResource
gr schema.GroupResource

namespace string
allNamespaces bool
Expand Down Expand Up @@ -96,67 +96,44 @@ type whoCan struct {
clioptions.IOStreams
}

func NewWhoCanOptions(configFlags *clioptions.ConfigFlags,
clientConfig clientcmd.ClientConfig,
clientNamespace clientcore.NamespaceInterface,
clientRBAC clientrbac.RbacV1Interface,
namespaceValidator NamespaceValidator,
resourceResolver ResourceResolver,
accessChecker AccessChecker,
policyRuleMatcher PolicyRuleMatcher,
streams clioptions.IOStreams) *whoCan {
return &whoCan{
configFlags: configFlags,
clientConfig: clientConfig,
clientNamespace: clientNamespace,
clientRBAC: clientRBAC,
namespaceValidator: namespaceValidator,
resourceResolver: resourceResolver,
accessChecker: accessChecker,
policyRuleMatcher: policyRuleMatcher,
IOStreams: streams,
}
}

func NewCmdWhoCan(streams clioptions.IOStreams) (*cobra.Command, error) {
configFlags := clioptions.NewConfigFlags(true)

clientConfig, err := configFlags.ToRESTConfig()
if err != nil {
return nil, fmt.Errorf("getting config: %v", err)
}

client, err := kubernetes.NewForConfig(clientConfig)
if err != nil {
return nil, fmt.Errorf("creating client: %v", err)
}

mapper, err := configFlags.ToRESTMapper()
if err != nil {
return nil, fmt.Errorf("getting mapper: %v", err)
}

clientNamespace := client.CoreV1().Namespaces()
accessChecker := NewAccessChecker(client.AuthorizationV1().SelfSubjectAccessReviews())
namespaceValidator := NewNamespaceValidator(clientNamespace)
resourceResolver := NewResourceResolver(client.Discovery(), mapper)

o := NewWhoCanOptions(configFlags,
configFlags.ToRawKubeConfigLoader(),
clientNamespace,
client.RbacV1(),
namespaceValidator,
resourceResolver,
accessChecker,
NewPolicyRuleMatcher(),
streams)
var configFlags *clioptions.ConfigFlags
var o whoCan

cmd := &cobra.Command{
Use: whoCanUsage,
Long: whoCanLong,
Example: whoCanExample,
SilenceUsage: true,
RunE: func(cmd *cobra.Command, args []string) error {
clientConfig, err := configFlags.ToRESTConfig()
if err != nil {
return fmt.Errorf("getting config: %v", err)
}

client, err := kubernetes.NewForConfig(clientConfig)
if err != nil {
return fmt.Errorf("creating client: %v", err)
}

mapper, err := configFlags.ToRESTMapper()
if err != nil {
return fmt.Errorf("getting mapper: %v", err)
}

clientNamespace := client.CoreV1().Namespaces()
namespaceValidator := NewNamespaceValidator(clientNamespace)

o.configFlags = configFlags
o.clientConfig = configFlags.ToRawKubeConfigLoader()
o.clientNamespace = clientNamespace
o.clientRBAC = client.RbacV1()
o.namespaceValidator = namespaceValidator
o.resourceResolver = NewResourceResolver(client.Discovery(), mapper)
o.accessChecker = NewAccessChecker(client.AuthorizationV1().SelfSubjectAccessReviews())
o.policyRuleMatcher = NewPolicyRuleMatcher()
o.IOStreams = streams

if err := o.Complete(args); err != nil {
return err
}
Expand All @@ -171,14 +148,15 @@ func NewCmdWhoCan(streams clioptions.IOStreams) (*cobra.Command, error) {
},
}

cmd.PersistentFlags().StringVar(&o.subResource, "subresource", o.subResource,
cmd.Flags().StringVar(&o.subResource, "subresource", o.subResource,
lizrice marked this conversation as resolved.
Show resolved Hide resolved
"SubResource such as pod/log or deployment/scale")
cmd.PersistentFlags().BoolVarP(&o.allNamespaces, "all-namespaces", "A", false,
cmd.Flags().BoolVarP(&o.allNamespaces, "all-namespaces", "A", o.allNamespaces,
"If true, check the specified action in all namespaces.")

flag.CommandLine.VisitAll(func(goflag *flag.Flag) {
cmd.PersistentFlags().AddGoFlag(goflag)
flag.CommandLine.VisitAll(func(gf *flag.Flag) {
cmd.Flags().AddGoFlag(gf)
})
configFlags = clioptions.NewConfigFlags(true)
configFlags.AddFlags(cmd.Flags())

return cmd, nil
Expand Down
52 changes: 29 additions & 23 deletions pkg/cmd/list_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -219,19 +219,21 @@ func TestComplete(t *testing.T) {
}

// given
o := NewWhoCanOptions(configFlags,
clientConfig,
kubeClient.CoreV1().Namespaces(),
kubeClient.RbacV1(),
namespaceValidator,
resourceResolver,
accessChecker,
policyRuleMatcher,
clioptions.NewTestIOStreamsDiscard())

// and
o.namespace = tt.flags.namespace
o.allNamespaces = tt.flags.allNamespaces
o := whoCan{
Action: Action{
namespace: tt.flags.namespace,
allNamespaces: tt.flags.allNamespaces,
},
configFlags: configFlags,
clientConfig: clientConfig,
clientNamespace: kubeClient.CoreV1().Namespaces(),
clientRBAC: kubeClient.RbacV1(),
namespaceValidator: namespaceValidator,
resourceResolver: resourceResolver,
accessChecker: accessChecker,
policyRuleMatcher: policyRuleMatcher,
IOStreams: clioptions.NewTestIOStreamsDiscard(),
}

// when
err := o.Complete(tt.args)
Expand Down Expand Up @@ -398,16 +400,20 @@ func TestWhoCan_checkAPIAccess(t *testing.T) {

// given
configFlags := &clioptions.ConfigFlags{}
wc := NewWhoCanOptions(configFlags,
configFlags.ToRawKubeConfigLoader(),
client.CoreV1().Namespaces(),
client.RbacV1(),
namespaceValidator,
resourceResolver,
accessChecker,
policyRuleMatcher,
clioptions.NewTestIOStreamsDiscard())
wc.namespace = tt.namespace
wc := whoCan{
Action: Action{
namespace: tt.namespace,
},
configFlags: configFlags,
clientConfig: configFlags.ToRawKubeConfigLoader(),
clientNamespace: client.CoreV1().Namespaces(),
clientRBAC: client.RbacV1(),
namespaceValidator: namespaceValidator,
resourceResolver: resourceResolver,
accessChecker: accessChecker,
policyRuleMatcher: policyRuleMatcher,
IOStreams: clioptions.NewTestIOStreamsDiscard(),
}

// when
warnings, err := wc.checkAPIAccess()
Expand Down
3 changes: 3 additions & 0 deletions pkg/cmd/resource_resolver.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package cmd

import (
"fmt"
"github.com/golang/glog"
rbac "k8s.io/api/rbac/v1"
"k8s.io/apimachinery/pkg/api/meta"
apismeta "k8s.io/apimachinery/pkg/apis/meta/v1"
Expand Down Expand Up @@ -43,11 +44,13 @@ func (rv *resourceResolver) Resolve(verb, resource, subResource string) (schema.

gvr, err := rv.resolveGVR(resource)
if err != nil {
glog.V(3).Infof("Error while resolving GVR for resource %s: %v", resource, err)
return schema.GroupResource{}, fmt.Errorf("the server doesn't have a resource type \"%s\"", name)
}

apiResource, err := rv.resolveAPIResource(gvr, subResource)
if err != nil {
glog.V(3).Infof("Error while resolving APIResource for GVR %v and subResource %s: %v", gvr, subResource, err)
return schema.GroupResource{}, fmt.Errorf("the server doesn't have a resource type \"%s\"", name)
}

Expand Down