Change:
Is this a request for help? (If yes, you should use our troubleshooting guide and community support channels, see ): No What keywords did you search in Kubernetes issues before filing this one? (If you have found any duplicates, you should instead reply there.): describe psp Is this a BUG REPORT or FEATURE REQUEST? (choose one): FEATURE REQUEST Kubernetes version (use ): Environment: Doesn't matter. What happened: doesn't show PSP's fields: What you expected to happen: All PSP fields should be shown. How to reproduce it (as minimally and precisely as possible):
If you're agree with that than I (or :) ) could implement it.
yes, improve the describer. Look at the scc describer for formatting.
any ideas which SIG should own PSP?
In this case it should be sig-cli /sig cli
yeah, this is cli related. I'd go with sig-auth for actual behavior.

Discussion:
extensions.Kind("ReplicaSet"):                  &ReplicaSetDescriber{c}, extensions.Kind("NetworkPolicy"):               &ExtensionsNetworkPolicyDescriber{c}, <ins> extensions.Kind("PodSecurityPolicy"):           &PodSecurityPolicyDescriber{c}, </ins> autoscaling.Kind("HorizontalPodAutoscaler"):    &HorizontalPodAutoscalerDescriber{c}, extensions.Kind("DaemonSet"):                   &DaemonSetDescriber{c}, extensions.Kind("Deployment"):                  &DeploymentDescriber{c, versionedClientsetForDeployment(c)},

}) } <ins> // PodSecurityPolicyDescriber generates information about a PodSecurityPolicy. type PodSecurityPolicyDescriber struct { clientset.Interface } func (d *PodSecurityPolicyDescriber) Describe(namespace, name string, describerSettings printers.DescriberSettings) (string, error) { psp, err := d.Extensions().PodSecurityPolicies().Get(name, metav1.GetOptions{}) if err != nil { return "", err } return describePodSecurityPolicy(psp) } func describePodSecurityPolicy(psp *extensions.PodSecurityPolicy) (string, error) { return tabbedString(func(out io.Writer) error { w := NewPrefixWriter(out) w.Write(LEVEL_0, "Name:t%sn", psp.Name) w.Write(LEVEL_0, "nSettings:n") w.Write(LEVEL_1, "Allow Privileged:t%tn", psp.Spec.Privileged) w.Write(LEVEL_1, "Default Add Capabilities:t%vn", capsToString(psp.Spec.DefaultAddCapabilities)) w.Write(LEVEL_1, "Required Drop Capabilities:t%sn", capsToString(psp.Spec.RequiredDropCapabilities)) w.Write(LEVEL_1, "Allowed Capabilities:t%sn", capsToString(psp.Spec.AllowedCapabilities)) w.Write(LEVEL_1, "Allowed Volume Types:t%sn", fsTypeToString(psp.Spec.Volumes)) w.Write(LEVEL_1, "Allow Host Network:t%tn", psp.Spec.HostNetwork) w.Write(LEVEL_1, "Allow Host Ports:t%sn", hostPortRangeToString(psp.Spec.HostPorts)) w.Write(LEVEL_1, "Allow Host PID:t%tn", psp.Spec.HostPID) w.Write(LEVEL_1, "Allow Host IPC:t%tn", psp.Spec.HostIPC) w.Write(LEVEL_1, "Read Only Root Filesystem:t%vn", psp.Spec.ReadOnlyRootFilesystem) w.Write(LEVEL_1, "SELinux Context Strategy: %stn", string(psp.Spec.SELinux.Rule)) var user, role, seLinuxType, level string if psp.Spec.SELinux.SELinuxOptions != nil { user = psp.Spec.SELinux.SELinuxOptions.User role = psp.Spec.SELinux.SELinuxOptions.Role seLinuxType = psp.Spec.SELinux.SELinuxOptions.Type level = psp.Spec.SELinux.SELinuxOptions.Level } w.Write(LEVEL_2, "User:t%sn", stringOrNone(user)) w.Write(LEVEL_2, "Role:t%sn", stringOrNone(role)) w.Write(LEVEL_2, "Type:t%sn", stringOrNone(seLinuxType)) w.Write(LEVEL_2, "Level:t%sn", stringOrNone(level)) w.Write(LEVEL_1, "Run As User Strategy: %stn", string(psp.Spec.RunAsUser.Rule)) w.Write(LEVEL_2, "Ranges:t%sn", userIDRangeToString(psp.Spec.RunAsUser.Ranges)) w.Write(LEVEL_1, "FSGroup Strategy: %stn", string(psp.Spec.FSGroup.Rule)) w.Write(LEVEL_2, "Ranges:t%sn", groupIDRangeToString(psp.Spec.FSGroup.Ranges)) w.Write(LEVEL_1, "Supplemental Groups Strategy: %stn", string(psp.Spec.SupplementalGroups.Rule)) w.Write(LEVEL_2, "Ranges:t%sn", groupIDRangeToString(psp.Spec.SupplementalGroups.Ranges)) return nil }) } func stringOrAll(s string) string { if len(s) > 0 { return s } return "*" } func stringOrNone(s string) string { if len(s) > 0 { return s } return "<none>" } func fsTypeToString(volumes []extensions.FSType) string { strVolumes := []string{} for _, v := range volumes { strVolumes = append(strVolumes, string(v)) } return stringOrNone(strings.Join(strVolumes, ",")) } func hostPortRangeToString(ranges []extensions.HostPortRange) string { formattedString := "" if ranges != nil { strRanges := []string{} for _, r := range ranges { strRanges = append(strRanges, fmt.Sprintf("%d-%d", r.Min, r.Max)) } formattedString = strings.Join(strRanges, ",") } return stringOrNone(formattedString) } func userIDRangeToString(ranges []extensions.UserIDRange) string { formattedString := "" if ranges != nil { strRanges := []string{} for _, r := range ranges { strRanges = append(strRanges, fmt.Sprintf("%d-%d", r.Min, r.Max)) } formattedString = strings.Join(strRanges, ",") } return stringOrNone(formattedString) } func groupIDRangeToString(ranges []extensions.GroupIDRange) string { formattedString := "" if ranges != nil { strRanges := []string{} for _, r := range ranges { strRanges = append(strRanges, fmt.Sprintf("%d-%d", r.Min, r.Max)) } formattedString = strings.Join(strRanges, ",") } return stringOrNone(formattedString) } func capsToString(caps []api.Capability) string { formattedString := "" if caps != nil { strCaps := []string{} for _, c := range caps { strCaps = append(strCaps, string(c)) } formattedString = strings.Join(strCaps, ",") } return stringOrNone(formattedString) } </ins> // newErrNoDescriber creates a new ErrNoDescriber with the names of the provided types. func newErrNoDescriber(types ...reflect.Type) error { names := make([]string, 0, len(types))

"bytes" "fmt" "reflect" <ins> "regexp" </ins> "strings" "testing" "time"

} } <ins> func TestDescribePodSecurityPolicy(t *testing.T) { expected := []string{ "Name:t*mypsp", "Allow Privileged:t*false", "Default Add Capabilities:t*<none>", "Required Drop Capabilities:t*<none>", "Allowed Capabilities:t*<none>", "Allowed Volume Types:t*<none>", "Allow Host Network:t*false", "Allow Host Ports:t*<none>", "Allow Host PID:t*false", "Allow Host IPC:t*false", "Read Only Root Filesystem:t*false", "SELinux Context Strategy: RunAsAny", "User:t*<none>", "Role:t*<none>", "Type:t*<none>", "Level:t*<none>", "Run As User Strategy: RunAsAny", "FSGroup Strategy: RunAsAny", "Supplemental Groups Strategy: RunAsAny", } fake := fake.NewSimpleClientset(&extensions.PodSecurityPolicy{ ObjectMeta: metav1.ObjectMeta{ Name: "mypsp", }, Spec: extensions.PodSecurityPolicySpec{ SELinux: extensions.SELinuxStrategyOptions{ Rule: extensions.SELinuxStrategyRunAsAny, }, RunAsUser: extensions.RunAsUserStrategyOptions{ Rule: extensions.RunAsUserStrategyRunAsAny, }, FSGroup: extensions.FSGroupStrategyOptions{ Rule: extensions.FSGroupStrategyRunAsAny, }, SupplementalGroups: extensions.SupplementalGroupsStrategyOptions{ Rule: extensions.SupplementalGroupsStrategyRunAsAny, }, }, }) c := &describeClient{T: t, Namespace: "", Interface: fake} d := PodSecurityPolicyDescriber{c} out, err := d.Describe("", "mypsp", printers.DescriberSettings{}) if err != nil { t.Fatalf("unexpected error: %v", err) } for _, item := range expected { if matched, _ := regexp.MatchString(item, out); !matched { t.Errorf("Expected to find %q in: %q", item, out) } } } </ins> func TestDescribeResourceQuota(t *testing.T) { fake := fake.NewSimpleClientset(&api.ResourceQuota{ ObjectMeta: metav1.ObjectMeta{