diff --git a/pkg/printers/internalversion/printers.go b/pkg/printers/internalversion/printers.go index 8b8581de640..18d27440a35 100644 --- a/pkg/printers/internalversion/printers.go +++ b/pkg/printers/internalversion/printers.go @@ -1377,7 +1377,7 @@ func printCSINode(obj *storage.CSINode, options printers.GenerateOptions) ([]met row := metav1.TableRow{ Object: runtime.RawExtension{Object: obj}, } - row.Cells = append(row.Cells, obj.Name, len(obj.Spec.Drivers), translateTimestampSince(obj.CreationTimestamp)) + row.Cells = append(row.Cells, obj.Name, int64(len(obj.Spec.Drivers)), translateTimestampSince(obj.CreationTimestamp)) return []metav1.TableRow{row}, nil } @@ -1481,7 +1481,7 @@ func printMutatingWebhook(obj *admissionregistration.MutatingWebhookConfiguratio row := metav1.TableRow{ Object: runtime.RawExtension{Object: obj}, } - row.Cells = append(row.Cells, obj.Name, len(obj.Webhooks), translateTimestampSince(obj.CreationTimestamp)) + row.Cells = append(row.Cells, obj.Name, int64(len(obj.Webhooks)), translateTimestampSince(obj.CreationTimestamp)) return []metav1.TableRow{row}, nil } @@ -1501,7 +1501,7 @@ func printValidatingWebhook(obj *admissionregistration.ValidatingWebhookConfigur row := metav1.TableRow{ Object: runtime.RawExtension{Object: obj}, } - row.Cells = append(row.Cells, obj.Name, len(obj.Webhooks), translateTimestampSince(obj.CreationTimestamp)) + row.Cells = append(row.Cells, obj.Name, int64(len(obj.Webhooks)), translateTimestampSince(obj.CreationTimestamp)) return []metav1.TableRow{row}, nil } @@ -2299,7 +2299,7 @@ func printStatus(obj *metav1.Status, options printers.GenerateOptions) ([]metav1 row := metav1.TableRow{ Object: runtime.RawExtension{Object: obj}, } - row.Cells = append(row.Cells, obj.Status, obj.Reason, obj.Message) + row.Cells = append(row.Cells, obj.Status, string(obj.Reason), obj.Message) return []metav1.TableRow{row}, nil } @@ -2528,7 +2528,7 @@ func printFlowSchema(obj *flowcontrol.FlowSchema, options printers.GenerateOptio break } } - row.Cells = append(row.Cells, name, plName, obj.Spec.MatchingPrecedence, distinguisherMethod, translateTimestampSince(obj.CreationTimestamp), badPLRef) + row.Cells = append(row.Cells, name, plName, int64(obj.Spec.MatchingPrecedence), distinguisherMethod, translateTimestampSince(obj.CreationTimestamp), badPLRef) return []metav1.TableRow{row}, nil } @@ -2628,7 +2628,7 @@ func printScale(obj *autoscaling.Scale, options printers.GenerateOptions) ([]met row := metav1.TableRow{ Object: runtime.RawExtension{Object: obj}, } - row.Cells = append(row.Cells, obj.Name, obj.Spec.Replicas, obj.Status.Replicas, translateTimestampSince(obj.CreationTimestamp)) + row.Cells = append(row.Cells, obj.Name, int64(obj.Spec.Replicas), int64(obj.Status.Replicas), translateTimestampSince(obj.CreationTimestamp)) return []metav1.TableRow{row}, nil } diff --git a/pkg/printers/internalversion/printers_test.go b/pkg/printers/internalversion/printers_test.go index ab811231fcb..0301a0d27b8 100644 --- a/pkg/printers/internalversion/printers_test.go +++ b/pkg/printers/internalversion/printers_test.go @@ -17,8 +17,10 @@ limitations under the License. package internalversion import ( + "fmt" "math" "reflect" + "runtime" "testing" "time" @@ -28,6 +30,7 @@ import ( "k8s.io/apimachinery/pkg/util/diff" "k8s.io/apimachinery/pkg/util/intstr" "k8s.io/client-go/util/certificate/csr" + "k8s.io/kubernetes/pkg/apis/admissionregistration" "k8s.io/kubernetes/pkg/apis/apiserverinternal" "k8s.io/kubernetes/pkg/apis/apps" "k8s.io/kubernetes/pkg/apis/autoscaling" @@ -5534,7 +5537,7 @@ func TestPrintFlowSchema(t *testing.T) { }, }, // Columns: Name, PriorityLevelName, MatchingPrecedence, DistinguisherMethod, Age, MissingPL - expected: []metav1.TableRow{{Cells: []interface{}{"all-matcher", "allee", int32(math.MaxInt32), "ByUser", "0s", "?"}}}, + expected: []metav1.TableRow{{Cells: []interface{}{"all-matcher", "allee", int64(math.MaxInt32), "ByUser", "0s", "?"}}}, }, { fs: flowcontrol.FlowSchema{ ObjectMeta: metav1.ObjectMeta{ @@ -5580,7 +5583,7 @@ func TestPrintFlowSchema(t *testing.T) { }, }, // Columns: Name, PriorityLevelName, MatchingPrecedence, DistinguisherMethod, Age, MissingPL - expected: []metav1.TableRow{{Cells: []interface{}{"some-matcher", "allee", int32(0), "ByNamespace", "5m", "True"}}}, + expected: []metav1.TableRow{{Cells: []interface{}{"some-matcher", "allee", int64(0), "ByNamespace", "5m", "True"}}}, }, { fs: flowcontrol.FlowSchema{ ObjectMeta: metav1.ObjectMeta{ @@ -5607,7 +5610,7 @@ func TestPrintFlowSchema(t *testing.T) { }, }, // Columns: Name, PriorityLevelName, MatchingPrecedence, DistinguisherMethod, Age, MissingPL - expected: []metav1.TableRow{{Cells: []interface{}{"exempt", "allee", int32(0), "", "5m", "?"}}}, + expected: []metav1.TableRow{{Cells: []interface{}{"exempt", "allee", int64(0), "", "5m", "?"}}}, }, } @@ -5841,7 +5844,7 @@ func TestPrintScale(t *testing.T) { }, expected: []metav1.TableRow{ { - Cells: []interface{}{"test-autoscaling", int32(2), int32(1), string("0s")}, + Cells: []interface{}{"test-autoscaling", int64(2), int64(1), string("0s")}, }, }, }, @@ -5860,3 +5863,324 @@ func TestPrintScale(t *testing.T) { } } } + +func TestTableRowDeepCopyShouldNotPanic(t *testing.T) { + tests := []struct { + name string + printer func() ([]metav1.TableRow, error) + }{ + { + name: "Pod", + printer: func() ([]metav1.TableRow, error) { + return printPod(&api.Pod{}, printers.GenerateOptions{}) + }, + }, + { + name: "PodTemplate", + printer: func() ([]metav1.TableRow, error) { + return printPodTemplate(&api.PodTemplate{}, printers.GenerateOptions{}) + }, + }, + { + name: "PodDisruptionBudget", + printer: func() ([]metav1.TableRow, error) { + return printPodDisruptionBudget(&policy.PodDisruptionBudget{}, printers.GenerateOptions{}) + }, + }, + { + name: "ReplicationController", + printer: func() ([]metav1.TableRow, error) { + return printReplicationController(&api.ReplicationController{}, printers.GenerateOptions{}) + }, + }, + { + name: "ReplicaSet", + printer: func() ([]metav1.TableRow, error) { + return printReplicaSet(&apps.ReplicaSet{}, printers.GenerateOptions{}) + }, + }, + { + name: "Job", + printer: func() ([]metav1.TableRow, error) { + return printJob(&batch.Job{}, printers.GenerateOptions{}) + }, + }, + { + name: "CronJob", + printer: func() ([]metav1.TableRow, error) { + return printCronJob(&batch.CronJob{}, printers.GenerateOptions{}) + }, + }, + { + name: "Service", + printer: func() ([]metav1.TableRow, error) { + return printService(&api.Service{}, printers.GenerateOptions{}) + }, + }, + { + name: "Ingress", + printer: func() ([]metav1.TableRow, error) { + return printIngress(&networking.Ingress{}, printers.GenerateOptions{}) + }, + }, + { + name: "IngressClass", + printer: func() ([]metav1.TableRow, error) { + return printIngressClass(&networking.IngressClass{}, printers.GenerateOptions{}) + }, + }, + { + name: "StatefulSet", + printer: func() ([]metav1.TableRow, error) { + return printStatefulSet(&apps.StatefulSet{}, printers.GenerateOptions{}) + }, + }, + { + name: "DaemonSet", + printer: func() ([]metav1.TableRow, error) { + return printDaemonSet(&apps.DaemonSet{}, printers.GenerateOptions{}) + }, + }, + { + name: "Endpoints", + printer: func() ([]metav1.TableRow, error) { + return printEndpoints(&api.Endpoints{}, printers.GenerateOptions{}) + }, + }, + { + name: "EndpointSlice", + printer: func() ([]metav1.TableRow, error) { + return printEndpointSlice(&discovery.EndpointSlice{}, printers.GenerateOptions{}) + }, + }, + { + name: "CSINode", + printer: func() ([]metav1.TableRow, error) { + return printCSINode(&storage.CSINode{}, printers.GenerateOptions{}) + }, + }, + { + name: "CSIDriver", + printer: func() ([]metav1.TableRow, error) { + return printCSIDriver(&storage.CSIDriver{}, printers.GenerateOptions{}) + }, + }, + { + name: "CSIStorageCapacity", + printer: func() ([]metav1.TableRow, error) { + return printCSIStorageCapacity(&storage.CSIStorageCapacity{}, printers.GenerateOptions{}) + }, + }, + { + name: "MutatingWebhookConfiguration", + printer: func() ([]metav1.TableRow, error) { + return printMutatingWebhook(&admissionregistration.MutatingWebhookConfiguration{}, printers.GenerateOptions{}) + }, + }, + { + name: "ValidatingWebhookConfiguration", + printer: func() ([]metav1.TableRow, error) { + return printValidatingWebhook(&admissionregistration.ValidatingWebhookConfiguration{}, printers.GenerateOptions{}) + }, + }, + { + name: "Namespace", + printer: func() ([]metav1.TableRow, error) { + return printNamespace(&api.Namespace{}, printers.GenerateOptions{}) + }, + }, + { + name: "Secret", + printer: func() ([]metav1.TableRow, error) { + return printSecret(&api.Secret{}, printers.GenerateOptions{}) + }, + }, + { + name: "ServiceAccount", + printer: func() ([]metav1.TableRow, error) { + return printServiceAccount(&api.ServiceAccount{}, printers.GenerateOptions{}) + }, + }, + { + name: "Node", + printer: func() ([]metav1.TableRow, error) { + return printNode(&api.Node{}, printers.GenerateOptions{}) + }, + }, + { + name: "PersistentVolume", + printer: func() ([]metav1.TableRow, error) { + return printPersistentVolume(&api.PersistentVolume{}, printers.GenerateOptions{}) + }, + }, + { + name: "PersistentVolumeClaim", + printer: func() ([]metav1.TableRow, error) { + return printPersistentVolumeClaim(&api.PersistentVolumeClaim{}, printers.GenerateOptions{}) + }, + }, + { + name: "Event", + printer: func() ([]metav1.TableRow, error) { + return printEvent(&api.Event{}, printers.GenerateOptions{}) + }, + }, + { + name: "RoleBinding", + printer: func() ([]metav1.TableRow, error) { + return printRoleBinding(&rbac.RoleBinding{}, printers.GenerateOptions{}) + }, + }, + { + name: "ClusterRoleBinding", + printer: func() ([]metav1.TableRow, error) { + return printClusterRoleBinding(&rbac.ClusterRoleBinding{}, printers.GenerateOptions{}) + }, + }, + { + name: "CertificateSigningRequest", + printer: func() ([]metav1.TableRow, error) { + return printCertificateSigningRequest(&certificates.CertificateSigningRequest{}, printers.GenerateOptions{}) + }, + }, + { + name: "ComponentStatus", + printer: func() ([]metav1.TableRow, error) { + return printComponentStatus(&api.ComponentStatus{}, printers.GenerateOptions{}) + }, + }, + { + name: "Deployment", + printer: func() ([]metav1.TableRow, error) { + return printDeployment(&apps.Deployment{}, printers.GenerateOptions{}) + }, + }, + { + name: "HorizontalPodAutoscaler", + printer: func() ([]metav1.TableRow, error) { + return printHorizontalPodAutoscaler(&autoscaling.HorizontalPodAutoscaler{}, printers.GenerateOptions{}) + }, + }, + { + name: "ConfigMap", + printer: func() ([]metav1.TableRow, error) { + return printConfigMap(&api.ConfigMap{}, printers.GenerateOptions{}) + }, + }, + { + name: "PodSecurityPolicy", + printer: func() ([]metav1.TableRow, error) { + return printPodSecurityPolicy(&policy.PodSecurityPolicy{}, printers.GenerateOptions{}) + }, + }, + { + name: "NetworkPolicy", + printer: func() ([]metav1.TableRow, error) { + return printNetworkPolicy(&networking.NetworkPolicy{}, printers.GenerateOptions{}) + }, + }, + { + name: "StorageClass", + printer: func() ([]metav1.TableRow, error) { + return printStorageClass(&storage.StorageClass{}, printers.GenerateOptions{}) + }, + }, + { + name: "Lease", + printer: func() ([]metav1.TableRow, error) { + return printLease(&coordination.Lease{}, printers.GenerateOptions{}) + }, + }, + { + name: "ControllerRevision", + printer: func() ([]metav1.TableRow, error) { + return printControllerRevision(&apps.ControllerRevision{}, printers.GenerateOptions{}) + }, + }, + { + name: "ResourceQuota", + printer: func() ([]metav1.TableRow, error) { + return printResourceQuota(&api.ResourceQuota{}, printers.GenerateOptions{}) + }, + }, + { + name: "PriorityClass", + printer: func() ([]metav1.TableRow, error) { + return printPriorityClass(&scheduling.PriorityClass{}, printers.GenerateOptions{}) + }, + }, + { + name: "RuntimeClass", + printer: func() ([]metav1.TableRow, error) { + return printRuntimeClass(&nodeapi.RuntimeClass{}, printers.GenerateOptions{}) + }, + }, + { + name: "VolumeAttachment", + printer: func() ([]metav1.TableRow, error) { + return printVolumeAttachment(&storage.VolumeAttachment{}, printers.GenerateOptions{}) + }, + }, + { + name: "FlowSchema", + printer: func() ([]metav1.TableRow, error) { + return printFlowSchema(&flowcontrol.FlowSchema{}, printers.GenerateOptions{}) + }, + }, + { + name: "StorageVersion", + printer: func() ([]metav1.TableRow, error) { + return printStorageVersion(&apiserverinternal.StorageVersion{}, printers.GenerateOptions{}) + }, + }, + { + name: "PriorityLevelConfiguration", + printer: func() ([]metav1.TableRow, error) { + return printPriorityLevelConfiguration(&flowcontrol.PriorityLevelConfiguration{}, printers.GenerateOptions{}) + }, + }, + { + name: "Scale", + printer: func() ([]metav1.TableRow, error) { + return printScale(&autoscaling.Scale{}, printers.GenerateOptions{}) + }, + }, + { + name: "Status", + printer: func() ([]metav1.TableRow, error) { + return printStatus(&metav1.Status{}, printers.GenerateOptions{}) + }, + }, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + rows, err := test.printer() + if err != nil { + t.Fatalf("expected no error, but got: %#v", err) + } + if len(rows) <= 0 { + t.Fatalf("expected to have at least one TableRow, but got: %d", len(rows)) + } + + func() { + defer func() { + if err := recover(); err != nil { + // Same as stdlib http server code. Manually allocate stack + // trace buffer size to prevent excessively large logs + const size = 64 << 10 + buf := make([]byte, size) + buf = buf[:runtime.Stack(buf, false)] + err = fmt.Errorf("%q stack:\n%s", err, buf) + + t.Errorf("Expected no panic, but got: %v", err) + } + }() + + // should not panic + rows[0].DeepCopy() + }() + + }) + } +}