add kubectl get rolebindings/clusterrolebindings -o wide

pull/6/head
xilabao 2016-11-08 16:19:57 +08:00
parent 6a88de9fe1
commit 93be603d8f
2 changed files with 100 additions and 2 deletions

View File

@ -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

View File

@ -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
}