From 93be603d8f900bd07ef101d54ced6b8be7648970 Mon Sep 17 00:00:00 2001 From: xilabao Date: Tue, 8 Nov 2016 16:19:57 +0800 Subject: [PATCH] add kubectl get rolebindings/clusterrolebindings -o wide --- pkg/apis/rbac/helpers.go | 26 +++++++++++ pkg/kubectl/resource_printer.go | 76 ++++++++++++++++++++++++++++++++- 2 files changed, 100 insertions(+), 2 deletions(-) diff --git a/pkg/apis/rbac/helpers.go b/pkg/apis/rbac/helpers.go index 93ed6f99546..c198e348d3c 100644 --- a/pkg/apis/rbac/helpers.go +++ b/pkg/apis/rbac/helpers.go @@ -97,6 +97,32 @@ func NonResourceURLMatches(rule PolicyRule, requestedURL string) bool { return false } +// subjectsStrings returns users, groups, serviceaccounts, unknown for display purposes. +func SubjectsStrings(subjects []Subject) ([]string, []string, []string, []string) { + users := []string{} + groups := []string{} + sas := []string{} + others := []string{} + + for _, subject := range subjects { + switch subject.Kind { + case ServiceAccountKind: + sas = append(sas, fmt.Sprintf("%s/%s", subject.Namespace, subject.Name)) + + case UserKind: + users = append(users, subject.Name) + + case GroupKind: + groups = append(groups, subject.Name) + + default: + others = append(others, fmt.Sprintf("%s/%s/%s", subject.Kind, subject.Namespace, subject.Name)) + } + } + + return users, groups, sas, others +} + // +k8s:deepcopy-gen=false // PolicyRuleBuilder let's us attach methods. A no-no for API types. // We use it to construct rules in code. It's more compact than trying to write them diff --git a/pkg/kubectl/resource_printer.go b/pkg/kubectl/resource_printer.go index afb40ab31c6..27700878d64 100644 --- a/pkg/kubectl/resource_printer.go +++ b/pkg/kubectl/resource_printer.go @@ -1727,7 +1727,41 @@ func printRoleList(list *rbac.RoleList, w io.Writer, options PrintOptions) error } func printRoleBinding(roleBinding *rbac.RoleBinding, w io.Writer, options PrintOptions) error { - return printObjectMeta(roleBinding.ObjectMeta, w, options, true) + meta := roleBinding.ObjectMeta + name := formatResourceName(options.Kind, meta.Name, options.WithKind) + + if options.WithNamespace { + if _, err := fmt.Fprintf(w, "%s\t", meta.Namespace); err != nil { + return err + } + } + + if _, err := fmt.Fprintf( + w, "%s\t%s", + name, + translateTimestamp(meta.CreationTimestamp), + ); err != nil { + return err + } + + if options.Wide { + roleRef := fmt.Sprintf("%s/%s", roleBinding.RoleRef.Kind, roleBinding.RoleRef.Name) + users, groups, sas, _ := rbac.SubjectsStrings(roleBinding.Subjects) + if _, err := fmt.Fprintf(w, "\t%s\t%v\t%v\t%v", + roleRef, + strings.Join(users, ", "), + strings.Join(groups, ", "), + strings.Join(sas, ", "), + ); err != nil { + return err + } + } + + if _, err := fmt.Fprint(w, AppendLabels(meta.Labels, options.ColumnLabels)); err != nil { + return err + } + _, err := fmt.Fprint(w, AppendAllLabels(options.ShowLabels, meta.Labels)) + return err } // Prints the RoleBinding in a human-friendly format. @@ -1755,7 +1789,39 @@ func printClusterRoleList(list *rbac.ClusterRoleList, w io.Writer, options Print } func printClusterRoleBinding(clusterRoleBinding *rbac.ClusterRoleBinding, w io.Writer, options PrintOptions) error { - return printObjectMeta(clusterRoleBinding.ObjectMeta, w, options, false) + meta := clusterRoleBinding.ObjectMeta + name := formatResourceName(options.Kind, meta.Name, options.WithKind) + + if options.WithNamespace { + return fmt.Errorf("clusterRoleBinding is not namespaced") + } + + if _, err := fmt.Fprintf( + w, "%s\t%s", + name, + translateTimestamp(meta.CreationTimestamp), + ); err != nil { + return err + } + + if options.Wide { + roleRef := clusterRoleBinding.RoleRef.Name + users, groups, sas, _ := rbac.SubjectsStrings(clusterRoleBinding.Subjects) + if _, err := fmt.Fprintf(w, "\t%s\t%v\t%v\t%v", + roleRef, + strings.Join(users, ", "), + strings.Join(groups, ", "), + strings.Join(sas, ", "), + ); err != nil { + return err + } + } + + if _, err := fmt.Fprint(w, AppendLabels(meta.Labels, options.ColumnLabels)); err != nil { + return err + } + _, err := fmt.Fprint(w, AppendAllLabels(options.ShowLabels, meta.Labels)) + return err } // Prints the ClusterRoleBinding in a human-friendly format. @@ -2224,6 +2290,12 @@ func formatWideHeaders(wide bool, t reflect.Type) []string { if t.String() == "*api.Node" || t.String() == "*api.NodeList" { return []string{"EXTERNAL-IP"} } + if t.String() == "*rbac.RoleBinding" || t.String() == "*rbac.RoleBindingList" { + return []string{"ROLE", "USERS", "GROUPS", "SERVICEACCOUNTS"} + } + if t.String() == "*rbac.ClusterRoleBinding" || t.String() == "*rbac.ClusterRoleBindingList" { + return []string{"ROLE", "USERS", "GROUPS", "SERVICEACCOUNTS"} + } } return nil }