Merge pull request #60991 from sttts/sttts-crd-columns

Automatic merge from submit-queue. If you want to cherry-pick this change to another branch, please follow the instructions <a href="https://github.com/kubernetes/community/blob/master/contributors/devel/cherry-picks.md">here</a>.

apiextensions-apiserver: add columns to CRD spec

Follow-up of https://github.com/kubernetes/kubernetes/pull/60269.

```release-note
Add spec. additionalPrinterColumns to CRDs to define server side printing columns.
```
pull/8/head
Kubernetes Submit Queue 2018-05-28 07:07:28 -07:00 committed by GitHub
commit 34383aa0a4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
23 changed files with 1227 additions and 212 deletions

View File

@ -85067,6 +85067,41 @@
} }
} }
}, },
"io.k8s.apiextensions-apiserver.pkg.apis.apiextensions.v1beta1.CustomResourceColumnDefinition": {
"description": "CustomResourceColumnDefinition specifies a column for server side printing.",
"required": [
"name",
"type",
"JSONPath"
],
"properties": {
"JSONPath": {
"description": "JSONPath is a simple JSON path, i.e. with array notation.",
"type": "string"
},
"description": {
"description": "description is a human readable description of this column.",
"type": "string"
},
"format": {
"description": "format is an optional OpenAPI type definition for this column. The 'name' format is applied to the primary identifier column to assist in clients identifying column is the resource name. See https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md#data-types for more.",
"type": "string"
},
"name": {
"description": "name is a human readable name for the column.",
"type": "string"
},
"priority": {
"description": "priority is an integer defining the relative importance of this column compared to others. Lower numbers are considered higher priority. Columns that may be omitted in limited space scenarios should be given a higher priority.",
"type": "integer",
"format": "int32"
},
"type": {
"description": "type is an OpenAPI type definition for this column. See https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md#data-types for more.",
"type": "string"
}
}
},
"io.k8s.apiextensions-apiserver.pkg.apis.apiextensions.v1beta1.CustomResourceDefinition": { "io.k8s.apiextensions-apiserver.pkg.apis.apiextensions.v1beta1.CustomResourceDefinition": {
"description": "CustomResourceDefinition represents a resource that should be exposed on the API server. Its name MUST be in the format \u003c.spec.name\u003e.\u003c.spec.group\u003e.", "description": "CustomResourceDefinition represents a resource that should be exposed on the API server. Its name MUST be in the format \u003c.spec.name\u003e.\u003c.spec.group\u003e.",
"properties": { "properties": {
@ -85207,6 +85242,13 @@
"scope" "scope"
], ],
"properties": { "properties": {
"additionalPrinterColumns": {
"description": "AdditionalPrinterColumns are additional columns shown e.g. in kubectl next to the name. Defaults to a created-at column.",
"type": "array",
"items": {
"$ref": "#/definitions/io.k8s.apiextensions-apiserver.pkg.apis.apiextensions.v1beta1.CustomResourceColumnDefinition"
}
},
"group": { "group": {
"description": "Group is the group this resource belongs in", "description": "Group is the group this resource belongs in",
"type": "string" "type": "string"

View File

@ -12,6 +12,7 @@ go_library(
deps = [ deps = [
"//vendor/github.com/google/gofuzz:go_default_library", "//vendor/github.com/google/gofuzz:go_default_library",
"//vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions:go_default_library", "//vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime/serializer:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime/serializer:go_default_library",
], ],
) )

View File

@ -23,9 +23,12 @@ import (
"github.com/google/gofuzz" "github.com/google/gofuzz"
"k8s.io/apiextensions-apiserver/pkg/apis/apiextensions" "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
runtimeserializer "k8s.io/apimachinery/pkg/runtime/serializer" runtimeserializer "k8s.io/apimachinery/pkg/runtime/serializer"
) )
var swaggerMetadataDescriptions = metav1.ObjectMeta{}.SwaggerDoc()
// Funcs returns the fuzzer functions for the apiextensions apis. // Funcs returns the fuzzer functions for the apiextensions apis.
func Funcs(codecs runtimeserializer.CodecFactory) []interface{} { func Funcs(codecs runtimeserializer.CodecFactory) []interface{} {
return []interface{}{ return []interface{}{
@ -53,6 +56,11 @@ func Funcs(codecs runtimeserializer.CodecFactory) []interface{} {
} else if len(obj.Versions) != 0 { } else if len(obj.Versions) != 0 {
obj.Version = obj.Versions[0].Name obj.Version = obj.Versions[0].Name
} }
if len(obj.AdditionalPrinterColumns) == 0 {
obj.AdditionalPrinterColumns = []apiextensions.CustomResourceColumnDefinition{
{Name: "Age", Type: "date", Description: swaggerMetadataDescriptions["creationTimestamp"], JSONPath: ".metadata.creationTimestamp"},
}
}
}, },
func(obj *apiextensions.CustomResourceDefinition, c fuzz.Continue) { func(obj *apiextensions.CustomResourceDefinition, c fuzz.Continue) {
c.FuzzNoCustom(obj) c.FuzzNoCustom(obj)

View File

@ -49,6 +49,8 @@ type CustomResourceDefinitionSpec struct {
// major version, then minor version. An example sorted list of versions: // major version, then minor version. An example sorted list of versions:
// v10, v2, v1, v11beta2, v10beta3, v3beta1, v12alpha1, v11alpha2, foo1, foo10. // v10, v2, v1, v11beta2, v10beta3, v3beta1, v12alpha1, v11alpha2, foo1, foo10.
Versions []CustomResourceDefinitionVersion Versions []CustomResourceDefinitionVersion
// AdditionalPrinterColumns are additional columns shown e.g. in kubectl next to the name. Defaults to a created-at column.
AdditionalPrinterColumns []CustomResourceColumnDefinition
} }
type CustomResourceDefinitionVersion struct { type CustomResourceDefinitionVersion struct {
@ -61,6 +63,28 @@ type CustomResourceDefinitionVersion struct {
Storage bool Storage bool
} }
// CustomResourceColumnDefinition specifies a column for server side printing.
type CustomResourceColumnDefinition struct {
// name is a human readable name for the column.
Name string
// type is an OpenAPI type definition for this column.
// See https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md#data-types for more.
Type string
// format is an optional OpenAPI type definition for this column. The 'name' format is applied
// to the primary identifier column to assist in clients identifying column is the resource name.
// See https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md#data-types for more.
Format string
// description is a human readable description of this column.
Description string
// priority is an integer defining the relative importance of this column compared to others. Lower
// numbers are considered higher priority. Columns that may be omitted in limited space scenarios
// should be given a higher priority.
Priority int32
// JSONPath is a simple JSON path, i.e. without array notation.
JSONPath string
}
// CustomResourceDefinitionNames indicates the names to serve this CustomResourceDefinition // CustomResourceDefinitionNames indicates the names to serve this CustomResourceDefinition
type CustomResourceDefinitionNames struct { type CustomResourceDefinitionNames struct {
// Plural is the plural name of the resource to serve. It must match the name of the CustomResourceDefinition-registration // Plural is the plural name of the resource to serve. It must match the name of the CustomResourceDefinition-registration

View File

@ -19,9 +19,12 @@ package v1beta1
import ( import (
"strings" "strings"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime"
) )
var swaggerMetadataDescriptions = metav1.ObjectMeta{}.SwaggerDoc()
func addDefaultingFuncs(scheme *runtime.Scheme) error { func addDefaultingFuncs(scheme *runtime.Scheme) error {
scheme.AddTypeDefaultingFunc(&CustomResourceDefinition{}, func(obj interface{}) { SetDefaults_CustomResourceDefinition(obj.(*CustomResourceDefinition)) }) scheme.AddTypeDefaultingFunc(&CustomResourceDefinition{}, func(obj interface{}) { SetDefaults_CustomResourceDefinition(obj.(*CustomResourceDefinition)) })
// TODO figure out why I can't seem to get my defaulter generated // TODO figure out why I can't seem to get my defaulter generated
@ -63,4 +66,9 @@ func SetDefaults_CustomResourceDefinitionSpec(obj *CustomResourceDefinitionSpec)
if len(obj.Version) == 0 && len(obj.Versions) != 0 { if len(obj.Version) == 0 && len(obj.Versions) != 0 {
obj.Version = obj.Versions[0].Name obj.Version = obj.Versions[0].Name
} }
if len(obj.AdditionalPrinterColumns) == 0 {
obj.AdditionalPrinterColumns = []CustomResourceColumnDefinition{
{Name: "Age", Type: "date", Description: swaggerMetadataDescriptions["creationTimestamp"], JSONPath: ".metadata.creationTimestamp"},
}
}
} }

View File

@ -25,6 +25,7 @@ limitations under the License.
k8s.io/kubernetes/vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1/generated.proto k8s.io/kubernetes/vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1/generated.proto
It has these top-level messages: It has these top-level messages:
CustomResourceColumnDefinition
CustomResourceDefinition CustomResourceDefinition
CustomResourceDefinitionCondition CustomResourceDefinitionCondition
CustomResourceDefinitionList CustomResourceDefinitionList
@ -67,99 +68,106 @@ var _ = math.Inf
// proto package needs to be updated. // proto package needs to be updated.
const _ = proto.GoGoProtoPackageIsVersion2 // please upgrade the proto package const _ = proto.GoGoProtoPackageIsVersion2 // please upgrade the proto package
func (m *CustomResourceColumnDefinition) Reset() { *m = CustomResourceColumnDefinition{} }
func (*CustomResourceColumnDefinition) ProtoMessage() {}
func (*CustomResourceColumnDefinition) Descriptor() ([]byte, []int) {
return fileDescriptorGenerated, []int{0}
}
func (m *CustomResourceDefinition) Reset() { *m = CustomResourceDefinition{} } func (m *CustomResourceDefinition) Reset() { *m = CustomResourceDefinition{} }
func (*CustomResourceDefinition) ProtoMessage() {} func (*CustomResourceDefinition) ProtoMessage() {}
func (*CustomResourceDefinition) Descriptor() ([]byte, []int) { func (*CustomResourceDefinition) Descriptor() ([]byte, []int) {
return fileDescriptorGenerated, []int{0} return fileDescriptorGenerated, []int{1}
} }
func (m *CustomResourceDefinitionCondition) Reset() { *m = CustomResourceDefinitionCondition{} } func (m *CustomResourceDefinitionCondition) Reset() { *m = CustomResourceDefinitionCondition{} }
func (*CustomResourceDefinitionCondition) ProtoMessage() {} func (*CustomResourceDefinitionCondition) ProtoMessage() {}
func (*CustomResourceDefinitionCondition) Descriptor() ([]byte, []int) { func (*CustomResourceDefinitionCondition) Descriptor() ([]byte, []int) {
return fileDescriptorGenerated, []int{1} return fileDescriptorGenerated, []int{2}
} }
func (m *CustomResourceDefinitionList) Reset() { *m = CustomResourceDefinitionList{} } func (m *CustomResourceDefinitionList) Reset() { *m = CustomResourceDefinitionList{} }
func (*CustomResourceDefinitionList) ProtoMessage() {} func (*CustomResourceDefinitionList) ProtoMessage() {}
func (*CustomResourceDefinitionList) Descriptor() ([]byte, []int) { func (*CustomResourceDefinitionList) Descriptor() ([]byte, []int) {
return fileDescriptorGenerated, []int{2} return fileDescriptorGenerated, []int{3}
} }
func (m *CustomResourceDefinitionNames) Reset() { *m = CustomResourceDefinitionNames{} } func (m *CustomResourceDefinitionNames) Reset() { *m = CustomResourceDefinitionNames{} }
func (*CustomResourceDefinitionNames) ProtoMessage() {} func (*CustomResourceDefinitionNames) ProtoMessage() {}
func (*CustomResourceDefinitionNames) Descriptor() ([]byte, []int) { func (*CustomResourceDefinitionNames) Descriptor() ([]byte, []int) {
return fileDescriptorGenerated, []int{3} return fileDescriptorGenerated, []int{4}
} }
func (m *CustomResourceDefinitionSpec) Reset() { *m = CustomResourceDefinitionSpec{} } func (m *CustomResourceDefinitionSpec) Reset() { *m = CustomResourceDefinitionSpec{} }
func (*CustomResourceDefinitionSpec) ProtoMessage() {} func (*CustomResourceDefinitionSpec) ProtoMessage() {}
func (*CustomResourceDefinitionSpec) Descriptor() ([]byte, []int) { func (*CustomResourceDefinitionSpec) Descriptor() ([]byte, []int) {
return fileDescriptorGenerated, []int{4} return fileDescriptorGenerated, []int{5}
} }
func (m *CustomResourceDefinitionStatus) Reset() { *m = CustomResourceDefinitionStatus{} } func (m *CustomResourceDefinitionStatus) Reset() { *m = CustomResourceDefinitionStatus{} }
func (*CustomResourceDefinitionStatus) ProtoMessage() {} func (*CustomResourceDefinitionStatus) ProtoMessage() {}
func (*CustomResourceDefinitionStatus) Descriptor() ([]byte, []int) { func (*CustomResourceDefinitionStatus) Descriptor() ([]byte, []int) {
return fileDescriptorGenerated, []int{5} return fileDescriptorGenerated, []int{6}
} }
func (m *CustomResourceDefinitionVersion) Reset() { *m = CustomResourceDefinitionVersion{} } func (m *CustomResourceDefinitionVersion) Reset() { *m = CustomResourceDefinitionVersion{} }
func (*CustomResourceDefinitionVersion) ProtoMessage() {} func (*CustomResourceDefinitionVersion) ProtoMessage() {}
func (*CustomResourceDefinitionVersion) Descriptor() ([]byte, []int) { func (*CustomResourceDefinitionVersion) Descriptor() ([]byte, []int) {
return fileDescriptorGenerated, []int{6} return fileDescriptorGenerated, []int{7}
} }
func (m *CustomResourceSubresourceScale) Reset() { *m = CustomResourceSubresourceScale{} } func (m *CustomResourceSubresourceScale) Reset() { *m = CustomResourceSubresourceScale{} }
func (*CustomResourceSubresourceScale) ProtoMessage() {} func (*CustomResourceSubresourceScale) ProtoMessage() {}
func (*CustomResourceSubresourceScale) Descriptor() ([]byte, []int) { func (*CustomResourceSubresourceScale) Descriptor() ([]byte, []int) {
return fileDescriptorGenerated, []int{7} return fileDescriptorGenerated, []int{8}
} }
func (m *CustomResourceSubresourceStatus) Reset() { *m = CustomResourceSubresourceStatus{} } func (m *CustomResourceSubresourceStatus) Reset() { *m = CustomResourceSubresourceStatus{} }
func (*CustomResourceSubresourceStatus) ProtoMessage() {} func (*CustomResourceSubresourceStatus) ProtoMessage() {}
func (*CustomResourceSubresourceStatus) Descriptor() ([]byte, []int) { func (*CustomResourceSubresourceStatus) Descriptor() ([]byte, []int) {
return fileDescriptorGenerated, []int{8} return fileDescriptorGenerated, []int{9}
} }
func (m *CustomResourceSubresources) Reset() { *m = CustomResourceSubresources{} } func (m *CustomResourceSubresources) Reset() { *m = CustomResourceSubresources{} }
func (*CustomResourceSubresources) ProtoMessage() {} func (*CustomResourceSubresources) ProtoMessage() {}
func (*CustomResourceSubresources) Descriptor() ([]byte, []int) { func (*CustomResourceSubresources) Descriptor() ([]byte, []int) {
return fileDescriptorGenerated, []int{9} return fileDescriptorGenerated, []int{10}
} }
func (m *CustomResourceValidation) Reset() { *m = CustomResourceValidation{} } func (m *CustomResourceValidation) Reset() { *m = CustomResourceValidation{} }
func (*CustomResourceValidation) ProtoMessage() {} func (*CustomResourceValidation) ProtoMessage() {}
func (*CustomResourceValidation) Descriptor() ([]byte, []int) { func (*CustomResourceValidation) Descriptor() ([]byte, []int) {
return fileDescriptorGenerated, []int{10} return fileDescriptorGenerated, []int{11}
} }
func (m *ExternalDocumentation) Reset() { *m = ExternalDocumentation{} } func (m *ExternalDocumentation) Reset() { *m = ExternalDocumentation{} }
func (*ExternalDocumentation) ProtoMessage() {} func (*ExternalDocumentation) ProtoMessage() {}
func (*ExternalDocumentation) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{11} } func (*ExternalDocumentation) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{12} }
func (m *JSON) Reset() { *m = JSON{} } func (m *JSON) Reset() { *m = JSON{} }
func (*JSON) ProtoMessage() {} func (*JSON) ProtoMessage() {}
func (*JSON) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{12} } func (*JSON) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{13} }
func (m *JSONSchemaProps) Reset() { *m = JSONSchemaProps{} } func (m *JSONSchemaProps) Reset() { *m = JSONSchemaProps{} }
func (*JSONSchemaProps) ProtoMessage() {} func (*JSONSchemaProps) ProtoMessage() {}
func (*JSONSchemaProps) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{13} } func (*JSONSchemaProps) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{14} }
func (m *JSONSchemaPropsOrArray) Reset() { *m = JSONSchemaPropsOrArray{} } func (m *JSONSchemaPropsOrArray) Reset() { *m = JSONSchemaPropsOrArray{} }
func (*JSONSchemaPropsOrArray) ProtoMessage() {} func (*JSONSchemaPropsOrArray) ProtoMessage() {}
func (*JSONSchemaPropsOrArray) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{14} } func (*JSONSchemaPropsOrArray) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{15} }
func (m *JSONSchemaPropsOrBool) Reset() { *m = JSONSchemaPropsOrBool{} } func (m *JSONSchemaPropsOrBool) Reset() { *m = JSONSchemaPropsOrBool{} }
func (*JSONSchemaPropsOrBool) ProtoMessage() {} func (*JSONSchemaPropsOrBool) ProtoMessage() {}
func (*JSONSchemaPropsOrBool) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{15} } func (*JSONSchemaPropsOrBool) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{16} }
func (m *JSONSchemaPropsOrStringArray) Reset() { *m = JSONSchemaPropsOrStringArray{} } func (m *JSONSchemaPropsOrStringArray) Reset() { *m = JSONSchemaPropsOrStringArray{} }
func (*JSONSchemaPropsOrStringArray) ProtoMessage() {} func (*JSONSchemaPropsOrStringArray) ProtoMessage() {}
func (*JSONSchemaPropsOrStringArray) Descriptor() ([]byte, []int) { func (*JSONSchemaPropsOrStringArray) Descriptor() ([]byte, []int) {
return fileDescriptorGenerated, []int{16} return fileDescriptorGenerated, []int{17}
} }
func init() { func init() {
proto.RegisterType((*CustomResourceColumnDefinition)(nil), "k8s.io.apiextensions_apiserver.pkg.apis.apiextensions.v1beta1.CustomResourceColumnDefinition")
proto.RegisterType((*CustomResourceDefinition)(nil), "k8s.io.apiextensions_apiserver.pkg.apis.apiextensions.v1beta1.CustomResourceDefinition") proto.RegisterType((*CustomResourceDefinition)(nil), "k8s.io.apiextensions_apiserver.pkg.apis.apiextensions.v1beta1.CustomResourceDefinition")
proto.RegisterType((*CustomResourceDefinitionCondition)(nil), "k8s.io.apiextensions_apiserver.pkg.apis.apiextensions.v1beta1.CustomResourceDefinitionCondition") proto.RegisterType((*CustomResourceDefinitionCondition)(nil), "k8s.io.apiextensions_apiserver.pkg.apis.apiextensions.v1beta1.CustomResourceDefinitionCondition")
proto.RegisterType((*CustomResourceDefinitionList)(nil), "k8s.io.apiextensions_apiserver.pkg.apis.apiextensions.v1beta1.CustomResourceDefinitionList") proto.RegisterType((*CustomResourceDefinitionList)(nil), "k8s.io.apiextensions_apiserver.pkg.apis.apiextensions.v1beta1.CustomResourceDefinitionList")
@ -178,6 +186,47 @@ func init() {
proto.RegisterType((*JSONSchemaPropsOrBool)(nil), "k8s.io.apiextensions_apiserver.pkg.apis.apiextensions.v1beta1.JSONSchemaPropsOrBool") proto.RegisterType((*JSONSchemaPropsOrBool)(nil), "k8s.io.apiextensions_apiserver.pkg.apis.apiextensions.v1beta1.JSONSchemaPropsOrBool")
proto.RegisterType((*JSONSchemaPropsOrStringArray)(nil), "k8s.io.apiextensions_apiserver.pkg.apis.apiextensions.v1beta1.JSONSchemaPropsOrStringArray") proto.RegisterType((*JSONSchemaPropsOrStringArray)(nil), "k8s.io.apiextensions_apiserver.pkg.apis.apiextensions.v1beta1.JSONSchemaPropsOrStringArray")
} }
func (m *CustomResourceColumnDefinition) Marshal() (dAtA []byte, err error) {
size := m.Size()
dAtA = make([]byte, size)
n, err := m.MarshalTo(dAtA)
if err != nil {
return nil, err
}
return dAtA[:n], nil
}
func (m *CustomResourceColumnDefinition) MarshalTo(dAtA []byte) (int, error) {
var i int
_ = i
var l int
_ = l
dAtA[i] = 0xa
i++
i = encodeVarintGenerated(dAtA, i, uint64(len(m.Name)))
i += copy(dAtA[i:], m.Name)
dAtA[i] = 0x12
i++
i = encodeVarintGenerated(dAtA, i, uint64(len(m.Type)))
i += copy(dAtA[i:], m.Type)
dAtA[i] = 0x1a
i++
i = encodeVarintGenerated(dAtA, i, uint64(len(m.Format)))
i += copy(dAtA[i:], m.Format)
dAtA[i] = 0x22
i++
i = encodeVarintGenerated(dAtA, i, uint64(len(m.Description)))
i += copy(dAtA[i:], m.Description)
dAtA[i] = 0x28
i++
i = encodeVarintGenerated(dAtA, i, uint64(m.Priority))
dAtA[i] = 0x32
i++
i = encodeVarintGenerated(dAtA, i, uint64(len(m.JSONPath)))
i += copy(dAtA[i:], m.JSONPath)
return i, nil
}
func (m *CustomResourceDefinition) Marshal() (dAtA []byte, err error) { func (m *CustomResourceDefinition) Marshal() (dAtA []byte, err error) {
size := m.Size() size := m.Size()
dAtA = make([]byte, size) dAtA = make([]byte, size)
@ -431,6 +480,18 @@ func (m *CustomResourceDefinitionSpec) MarshalTo(dAtA []byte) (int, error) {
i += n i += n
} }
} }
if len(m.AdditionalPrinterColumns) > 0 {
for _, msg := range m.AdditionalPrinterColumns {
dAtA[i] = 0x42
i++
i = encodeVarintGenerated(dAtA, i, uint64(msg.Size()))
n, err := msg.MarshalTo(dAtA[i:])
if err != nil {
return 0, err
}
i += n
}
}
return i, nil return i, nil
} }
@ -1257,6 +1318,23 @@ func encodeVarintGenerated(dAtA []byte, offset int, v uint64) int {
dAtA[offset] = uint8(v) dAtA[offset] = uint8(v)
return offset + 1 return offset + 1
} }
func (m *CustomResourceColumnDefinition) Size() (n int) {
var l int
_ = l
l = len(m.Name)
n += 1 + l + sovGenerated(uint64(l))
l = len(m.Type)
n += 1 + l + sovGenerated(uint64(l))
l = len(m.Format)
n += 1 + l + sovGenerated(uint64(l))
l = len(m.Description)
n += 1 + l + sovGenerated(uint64(l))
n += 1 + sovGenerated(uint64(m.Priority))
l = len(m.JSONPath)
n += 1 + l + sovGenerated(uint64(l))
return n
}
func (m *CustomResourceDefinition) Size() (n int) { func (m *CustomResourceDefinition) Size() (n int) {
var l int var l int
_ = l _ = l
@ -1350,6 +1428,12 @@ func (m *CustomResourceDefinitionSpec) Size() (n int) {
n += 1 + l + sovGenerated(uint64(l)) n += 1 + l + sovGenerated(uint64(l))
} }
} }
if len(m.AdditionalPrinterColumns) > 0 {
for _, e := range m.AdditionalPrinterColumns {
l = e.Size()
n += 1 + l + sovGenerated(uint64(l))
}
}
return n return n
} }
@ -1651,6 +1735,21 @@ func sovGenerated(x uint64) (n int) {
func sozGenerated(x uint64) (n int) { func sozGenerated(x uint64) (n int) {
return sovGenerated(uint64((x << 1) ^ uint64((int64(x) >> 63)))) return sovGenerated(uint64((x << 1) ^ uint64((int64(x) >> 63))))
} }
func (this *CustomResourceColumnDefinition) String() string {
if this == nil {
return "nil"
}
s := strings.Join([]string{`&CustomResourceColumnDefinition{`,
`Name:` + fmt.Sprintf("%v", this.Name) + `,`,
`Type:` + fmt.Sprintf("%v", this.Type) + `,`,
`Format:` + fmt.Sprintf("%v", this.Format) + `,`,
`Description:` + fmt.Sprintf("%v", this.Description) + `,`,
`Priority:` + fmt.Sprintf("%v", this.Priority) + `,`,
`JSONPath:` + fmt.Sprintf("%v", this.JSONPath) + `,`,
`}`,
}, "")
return s
}
func (this *CustomResourceDefinition) String() string { func (this *CustomResourceDefinition) String() string {
if this == nil { if this == nil {
return "nil" return "nil"
@ -1715,6 +1814,7 @@ func (this *CustomResourceDefinitionSpec) String() string {
`Validation:` + strings.Replace(fmt.Sprintf("%v", this.Validation), "CustomResourceValidation", "CustomResourceValidation", 1) + `,`, `Validation:` + strings.Replace(fmt.Sprintf("%v", this.Validation), "CustomResourceValidation", "CustomResourceValidation", 1) + `,`,
`Subresources:` + strings.Replace(fmt.Sprintf("%v", this.Subresources), "CustomResourceSubresources", "CustomResourceSubresources", 1) + `,`, `Subresources:` + strings.Replace(fmt.Sprintf("%v", this.Subresources), "CustomResourceSubresources", "CustomResourceSubresources", 1) + `,`,
`Versions:` + strings.Replace(strings.Replace(fmt.Sprintf("%v", this.Versions), "CustomResourceDefinitionVersion", "CustomResourceDefinitionVersion", 1), `&`, ``, 1) + `,`, `Versions:` + strings.Replace(strings.Replace(fmt.Sprintf("%v", this.Versions), "CustomResourceDefinitionVersion", "CustomResourceDefinitionVersion", 1), `&`, ``, 1) + `,`,
`AdditionalPrinterColumns:` + strings.Replace(strings.Replace(fmt.Sprintf("%v", this.AdditionalPrinterColumns), "CustomResourceColumnDefinition", "CustomResourceColumnDefinition", 1), `&`, ``, 1) + `,`,
`}`, `}`,
}, "") }, "")
return s return s
@ -1932,6 +2032,220 @@ func valueToStringGenerated(v interface{}) string {
pv := reflect.Indirect(rv).Interface() pv := reflect.Indirect(rv).Interface()
return fmt.Sprintf("*%v", pv) return fmt.Sprintf("*%v", pv)
} }
func (m *CustomResourceColumnDefinition) Unmarshal(dAtA []byte) error {
l := len(dAtA)
iNdEx := 0
for iNdEx < l {
preIndex := iNdEx
var wire uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowGenerated
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
wire |= (uint64(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
fieldNum := int32(wire >> 3)
wireType := int(wire & 0x7)
if wireType == 4 {
return fmt.Errorf("proto: CustomResourceColumnDefinition: wiretype end group for non-group")
}
if fieldNum <= 0 {
return fmt.Errorf("proto: CustomResourceColumnDefinition: illegal tag %d (wire type %d)", fieldNum, wire)
}
switch fieldNum {
case 1:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Name", wireType)
}
var stringLen uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowGenerated
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
stringLen |= (uint64(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
intStringLen := int(stringLen)
if intStringLen < 0 {
return ErrInvalidLengthGenerated
}
postIndex := iNdEx + intStringLen
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.Name = string(dAtA[iNdEx:postIndex])
iNdEx = postIndex
case 2:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Type", wireType)
}
var stringLen uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowGenerated
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
stringLen |= (uint64(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
intStringLen := int(stringLen)
if intStringLen < 0 {
return ErrInvalidLengthGenerated
}
postIndex := iNdEx + intStringLen
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.Type = string(dAtA[iNdEx:postIndex])
iNdEx = postIndex
case 3:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Format", wireType)
}
var stringLen uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowGenerated
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
stringLen |= (uint64(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
intStringLen := int(stringLen)
if intStringLen < 0 {
return ErrInvalidLengthGenerated
}
postIndex := iNdEx + intStringLen
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.Format = string(dAtA[iNdEx:postIndex])
iNdEx = postIndex
case 4:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Description", wireType)
}
var stringLen uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowGenerated
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
stringLen |= (uint64(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
intStringLen := int(stringLen)
if intStringLen < 0 {
return ErrInvalidLengthGenerated
}
postIndex := iNdEx + intStringLen
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.Description = string(dAtA[iNdEx:postIndex])
iNdEx = postIndex
case 5:
if wireType != 0 {
return fmt.Errorf("proto: wrong wireType = %d for field Priority", wireType)
}
m.Priority = 0
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowGenerated
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
m.Priority |= (int32(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
case 6:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field JSONPath", wireType)
}
var stringLen uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowGenerated
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
stringLen |= (uint64(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
intStringLen := int(stringLen)
if intStringLen < 0 {
return ErrInvalidLengthGenerated
}
postIndex := iNdEx + intStringLen
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.JSONPath = string(dAtA[iNdEx:postIndex])
iNdEx = postIndex
default:
iNdEx = preIndex
skippy, err := skipGenerated(dAtA[iNdEx:])
if err != nil {
return err
}
if skippy < 0 {
return ErrInvalidLengthGenerated
}
if (iNdEx + skippy) > l {
return io.ErrUnexpectedEOF
}
iNdEx += skippy
}
}
if iNdEx > l {
return io.ErrUnexpectedEOF
}
return nil
}
func (m *CustomResourceDefinition) Unmarshal(dAtA []byte) error { func (m *CustomResourceDefinition) Unmarshal(dAtA []byte) error {
l := len(dAtA) l := len(dAtA)
iNdEx := 0 iNdEx := 0
@ -2846,6 +3160,37 @@ func (m *CustomResourceDefinitionSpec) Unmarshal(dAtA []byte) error {
return err return err
} }
iNdEx = postIndex iNdEx = postIndex
case 8:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field AdditionalPrinterColumns", wireType)
}
var msglen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowGenerated
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
msglen |= (int(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
if msglen < 0 {
return ErrInvalidLengthGenerated
}
postIndex := iNdEx + msglen
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.AdditionalPrinterColumns = append(m.AdditionalPrinterColumns, CustomResourceColumnDefinition{})
if err := m.AdditionalPrinterColumns[len(m.AdditionalPrinterColumns)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
return err
}
iNdEx = postIndex
default: default:
iNdEx = preIndex iNdEx = preIndex
skippy, err := skipGenerated(dAtA[iNdEx:]) skippy, err := skipGenerated(dAtA[iNdEx:])
@ -5529,143 +5874,150 @@ func init() {
} }
var fileDescriptorGenerated = []byte{ var fileDescriptorGenerated = []byte{
// 2200 bytes of a gzipped FileDescriptorProto // 2306 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xc4, 0x59, 0xcd, 0x6f, 0x1c, 0x49, 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xc4, 0x59, 0xdd, 0x6f, 0x5b, 0x49,
0x15, 0x77, 0xcf, 0x78, 0xfc, 0x51, 0xb6, 0x63, 0xbb, 0x12, 0x87, 0x8e, 0x49, 0x66, 0xec, 0x59, 0x15, 0xef, 0xb5, 0xe3, 0xc4, 0x19, 0x27, 0x4d, 0x32, 0x6d, 0xca, 0x6d, 0x68, 0xed, 0xd4, 0x65,
0x76, 0x65, 0x60, 0x33, 0x43, 0xf6, 0x83, 0x5d, 0x56, 0xe2, 0xe0, 0xb1, 0x0d, 0xca, 0x62, 0xc7, 0x57, 0x01, 0xb6, 0x36, 0xed, 0xee, 0xb2, 0xcb, 0x4a, 0x3c, 0xc4, 0x49, 0x41, 0x5d, 0x9a, 0x26,
0x56, 0x4d, 0x12, 0x04, 0xfb, 0x59, 0xee, 0xae, 0x19, 0x77, 0xdc, 0x5f, 0xe9, 0xaa, 0x9e, 0xd8, 0x1a, 0xb7, 0x45, 0xb0, 0x9f, 0x13, 0x7b, 0xe2, 0xdc, 0xe6, 0x7e, 0x75, 0x66, 0xae, 0x9b, 0x48,
0x12, 0x20, 0x3e, 0xb4, 0x42, 0x42, 0xc0, 0x22, 0x88, 0x90, 0x90, 0xb8, 0x80, 0xc4, 0x05, 0x21, 0x80, 0xf8, 0xd0, 0x0a, 0x09, 0x01, 0x0b, 0x6c, 0x85, 0x84, 0xc4, 0x0b, 0x48, 0xbc, 0x20, 0x04,
0x38, 0xc0, 0x91, 0x3f, 0x20, 0xc7, 0x95, 0xb8, 0xec, 0x69, 0x44, 0x86, 0x7f, 0x01, 0x09, 0xc9, 0x0f, 0xf0, 0x06, 0x7f, 0x40, 0x1f, 0xf7, 0x71, 0x9f, 0x2c, 0x6a, 0xfe, 0x05, 0x24, 0xa4, 0x3c,
0x27, 0x54, 0x1f, 0x5d, 0xdd, 0x3d, 0xe3, 0xd9, 0x44, 0xda, 0x99, 0xcd, 0xcd, 0xfd, 0xde, 0xab, 0xa1, 0xf9, 0xb8, 0x73, 0xef, 0xb5, 0xe3, 0x6d, 0xb5, 0x6b, 0x6f, 0xdf, 0x7c, 0xcf, 0x39, 0x73,
0xf7, 0xfb, 0xd5, 0xab, 0x57, 0xaf, 0xde, 0x1b, 0x83, 0xd6, 0xf1, 0xeb, 0xb4, 0xe6, 0x04, 0xf5, 0x7e, 0xbf, 0x39, 0x73, 0xe6, 0xcc, 0x39, 0x09, 0xd8, 0x3b, 0x78, 0x95, 0xd5, 0x9c, 0xa0, 0x7e,
0xe3, 0xf8, 0x90, 0x44, 0x3e, 0x61, 0x84, 0xd6, 0x3b, 0xc4, 0xb7, 0x83, 0xa8, 0xae, 0x14, 0x38, 0x10, 0xed, 0x12, 0xea, 0x13, 0x4e, 0x58, 0xbd, 0x4b, 0xfc, 0x76, 0x40, 0xeb, 0x5a, 0x81, 0x43,
0x74, 0xc8, 0x09, 0x23, 0x3e, 0x75, 0x02, 0x9f, 0x5e, 0xc7, 0xa1, 0x43, 0x49, 0xd4, 0x21, 0x51, 0x87, 0x1c, 0x72, 0xe2, 0x33, 0x27, 0xf0, 0xd9, 0x15, 0x1c, 0x3a, 0x8c, 0xd0, 0x2e, 0xa1, 0xf5,
0x3d, 0x3c, 0x6e, 0x73, 0x1d, 0xcd, 0x1b, 0xd4, 0x3b, 0x37, 0x0e, 0x09, 0xc3, 0x37, 0xea, 0x6d, 0xf0, 0xa0, 0x23, 0x74, 0x2c, 0x6b, 0x50, 0xef, 0x5e, 0xdd, 0x25, 0x1c, 0x5f, 0xad, 0x77, 0x88,
0xe2, 0x93, 0x08, 0x33, 0x62, 0xd7, 0xc2, 0x28, 0x60, 0x01, 0xfc, 0xba, 0x74, 0x57, 0xcb, 0x59, 0x4f, 0x28, 0xe6, 0xa4, 0x5d, 0x0b, 0x69, 0xc0, 0x03, 0xf8, 0x75, 0xe5, 0xae, 0x96, 0xb1, 0x7e,
0xbf, 0xa7, 0xdd, 0xd5, 0xc2, 0xe3, 0x36, 0xd7, 0xd1, 0xbc, 0x41, 0x4d, 0xb9, 0x5b, 0xbd, 0xde, 0xc7, 0xb8, 0xab, 0x85, 0x07, 0x1d, 0xa1, 0x63, 0x59, 0x83, 0x9a, 0x76, 0xb7, 0x72, 0xa5, 0xe3,
0x76, 0xd8, 0x51, 0x7c, 0x58, 0xb3, 0x02, 0xaf, 0xde, 0x0e, 0xda, 0x41, 0x5d, 0x78, 0x3d, 0x8c, 0xf0, 0xfd, 0x68, 0xb7, 0xd6, 0x0a, 0xbc, 0x7a, 0x27, 0xe8, 0x04, 0x75, 0xe9, 0x75, 0x37, 0xda,
0x5b, 0xe2, 0x4b, 0x7c, 0x88, 0xbf, 0x24, 0xda, 0xea, 0x2b, 0x29, 0x79, 0x0f, 0x5b, 0x47, 0x8e, 0x93, 0x5f, 0xf2, 0x43, 0xfe, 0x52, 0x68, 0x2b, 0x2f, 0x25, 0xe4, 0x3d, 0xdc, 0xda, 0x77, 0x7c,
0x4f, 0xa2, 0xd3, 0x94, 0xb1, 0x47, 0x18, 0xae, 0x77, 0x06, 0x38, 0xae, 0xd6, 0x87, 0xad, 0x8a, 0x42, 0x8f, 0x12, 0xc6, 0x1e, 0xe1, 0xb8, 0xde, 0x1d, 0xe2, 0xb8, 0x52, 0x1f, 0xb5, 0x8a, 0x46,
0x62, 0x9f, 0x39, 0x1e, 0x19, 0x58, 0xf0, 0xd5, 0x27, 0x2d, 0xa0, 0xd6, 0x11, 0xf1, 0xf0, 0xc0, 0x3e, 0x77, 0x3c, 0x32, 0xb4, 0xe0, 0xab, 0x4f, 0x5a, 0xc0, 0x5a, 0xfb, 0xc4, 0xc3, 0x43, 0xeb,
0xba, 0x97, 0x87, 0xad, 0x8b, 0x99, 0xe3, 0xd6, 0x1d, 0x9f, 0x51, 0x16, 0xf5, 0x2f, 0xaa, 0xfe, 0x5e, 0x1c, 0xb5, 0x2e, 0xe2, 0x8e, 0x5b, 0x77, 0x7c, 0xce, 0x38, 0x1d, 0x5c, 0x54, 0xfd, 0x20,
0xa4, 0x08, 0xcc, 0xad, 0x98, 0xb2, 0xc0, 0x43, 0x84, 0x06, 0x71, 0x64, 0x91, 0x6d, 0xd2, 0x72, 0x07, 0xca, 0x1b, 0x11, 0xe3, 0x81, 0x87, 0x08, 0x0b, 0x22, 0xda, 0x22, 0x1b, 0x81, 0x1b, 0x79,
0x7c, 0x87, 0x39, 0x81, 0x0f, 0xdf, 0x07, 0x33, 0x7c, 0x57, 0x36, 0x66, 0xd8, 0x34, 0xd6, 0x8c, 0xfe, 0x26, 0xd9, 0x73, 0x7c, 0x87, 0x3b, 0x81, 0x0f, 0x57, 0xc1, 0x94, 0x8f, 0x3d, 0x62, 0x5b,
0x8d, 0xb9, 0x97, 0xbe, 0x52, 0x4b, 0x23, 0xae, 0x41, 0xd2, 0x30, 0x73, 0xeb, 0x5a, 0xe7, 0x46, 0xab, 0xd6, 0xda, 0x6c, 0x63, 0xee, 0x51, 0xaf, 0x72, 0xaa, 0xdf, 0xab, 0x4c, 0xdd, 0xc2, 0x1e,
0x6d, 0xff, 0xf0, 0x1e, 0xb1, 0xd8, 0x1e, 0x61, 0xb8, 0x01, 0x1f, 0x75, 0x2b, 0x13, 0xbd, 0x6e, 0x41, 0x52, 0x23, 0x2c, 0xf8, 0x51, 0x48, 0xec, 0x5c, 0xd6, 0xe2, 0xf6, 0x51, 0x48, 0x90, 0xd4,
0x05, 0xa4, 0x32, 0xa4, 0xbd, 0xc2, 0xef, 0x83, 0x49, 0x1a, 0x12, 0xcb, 0x2c, 0x08, 0xef, 0x6f, 0xc0, 0xe7, 0xc1, 0xf4, 0x5e, 0x40, 0x3d, 0xcc, 0xed, 0xbc, 0xb4, 0x39, 0xad, 0x6d, 0xa6, 0xbf,
0xd5, 0x3e, 0xd5, 0x79, 0xd6, 0x86, 0x6d, 0xa4, 0x19, 0x12, 0xab, 0x31, 0xaf, 0x88, 0x4c, 0xf2, 0x21, 0xa5, 0x48, 0x6b, 0xe1, 0xcb, 0xa0, 0xd4, 0x26, 0xac, 0x45, 0x9d, 0x50, 0x40, 0xdb, 0x53,
0x2f, 0x24, 0x60, 0xe1, 0x07, 0x06, 0x98, 0xa2, 0x0c, 0xb3, 0x98, 0x9a, 0x45, 0xc1, 0xe0, 0x9d, 0xd2, 0xf8, 0x8c, 0x36, 0x2e, 0x6d, 0x26, 0x2a, 0x94, 0xb6, 0x83, 0x2f, 0x80, 0x62, 0x48, 0x9d,
0x71, 0x31, 0x10, 0x20, 0x8d, 0x0b, 0x8a, 0xc3, 0x94, 0xfc, 0x46, 0x0a, 0xbc, 0xfa, 0xdf, 0x02, 0x80, 0x3a, 0xfc, 0xc8, 0x2e, 0xac, 0x5a, 0x6b, 0x85, 0xc6, 0xa2, 0x5e, 0x53, 0xdc, 0xd1, 0x72,
0x58, 0x1f, 0xb6, 0x74, 0x2b, 0xf0, 0x6d, 0x79, 0x1c, 0x37, 0xc1, 0x24, 0x3b, 0x0d, 0x89, 0x38, 0x64, 0x2c, 0xe0, 0x2a, 0x28, 0xbe, 0xde, 0xdc, 0xbe, 0xb5, 0x83, 0xf9, 0xbe, 0x3d, 0x2d, 0x11,
0x8a, 0xd9, 0xc6, 0xab, 0xc9, 0x7e, 0x6e, 0x9f, 0x86, 0xe4, 0xac, 0x5b, 0x79, 0xfe, 0x89, 0x0e, 0xa6, 0x84, 0x35, 0x2a, 0xde, 0xd3, 0xd2, 0xea, 0x4f, 0xf2, 0xc0, 0xce, 0x46, 0x25, 0x15, 0x8f,
0xb8, 0x21, 0x12, 0x2e, 0xe0, 0xd7, 0xf4, 0xbe, 0x0b, 0xc2, 0xd9, 0x7a, 0x9e, 0xd8, 0x59, 0xb7, 0x77, 0x41, 0x51, 0x9c, 0x75, 0x1b, 0x73, 0x2c, 0x63, 0x52, 0xba, 0xf6, 0x95, 0x5a, 0x92, 0x87,
0xb2, 0xa8, 0x97, 0xe5, 0xb9, 0xc2, 0x0e, 0x80, 0x2e, 0xa6, 0xec, 0x76, 0x84, 0x7d, 0x2a, 0xdd, 0x26, 0xf4, 0x49, 0xf2, 0x09, 0xeb, 0x5a, 0xf7, 0x6a, 0x6d, 0x7b, 0xf7, 0x1e, 0x69, 0xf1, 0x2d,
0x3a, 0x1e, 0x51, 0xe1, 0xfb, 0xd2, 0xd3, 0xa5, 0x07, 0x5f, 0xd1, 0x58, 0x55, 0x90, 0x70, 0x77, 0xc2, 0x71, 0x03, 0x6a, 0x7a, 0x20, 0x91, 0x21, 0xe3, 0x15, 0x7e, 0x1f, 0x4c, 0xb1, 0x90, 0xb4,
0xc0, 0x1b, 0x3a, 0x07, 0x01, 0xbe, 0x00, 0xa6, 0x22, 0x82, 0x69, 0xe0, 0x9b, 0x93, 0x82, 0xb2, 0x64, 0x3c, 0x4b, 0xd7, 0xde, 0xa8, 0x7d, 0xaa, 0x2c, 0xaf, 0x8d, 0xda, 0x48, 0x33, 0x24, 0xad,
0x8e, 0x25, 0x12, 0x52, 0xa4, 0xb4, 0xf0, 0x8b, 0x60, 0xda, 0x23, 0x94, 0xe2, 0x36, 0x31, 0x4b, 0xe4, 0xb0, 0xc4, 0x17, 0x92, 0xb0, 0xf0, 0x3d, 0x0b, 0x4c, 0x33, 0x8e, 0x79, 0xc4, 0xe4, 0x69,
0xc2, 0x70, 0x51, 0x19, 0x4e, 0xef, 0x49, 0x31, 0x4a, 0xf4, 0xd5, 0x33, 0x03, 0x5c, 0x1d, 0x16, 0x95, 0xae, 0xbd, 0x35, 0x29, 0x06, 0x12, 0x24, 0x49, 0x06, 0xf5, 0x8d, 0x34, 0x78, 0xf5, 0xbf,
0xb5, 0x5d, 0x87, 0x32, 0xf8, 0xf6, 0xc0, 0x05, 0xa8, 0x3d, 0xdd, 0x0e, 0xf9, 0x6a, 0x91, 0xfe, 0x39, 0x70, 0x69, 0xd4, 0xd2, 0x8d, 0xc0, 0x6f, 0xab, 0xe3, 0xb8, 0xa1, 0x93, 0x4f, 0xa5, 0xe7,
0x4b, 0x0a, 0x7c, 0x26, 0x91, 0x64, 0x92, 0xff, 0x7b, 0xa0, 0xe4, 0x30, 0xe2, 0xf1, 0x33, 0x28, 0xcb, 0xe9, 0xe4, 0x3b, 0xee, 0x55, 0x9e, 0x7b, 0xa2, 0x83, 0x54, 0x96, 0x7e, 0xcd, 0xec, 0x5b,
0x6e, 0xcc, 0xbd, 0xf4, 0xed, 0x31, 0xe5, 0x5e, 0x63, 0x41, 0x71, 0x28, 0xdd, 0xe4, 0x68, 0x48, 0x65, 0xf2, 0xa5, 0x2c, 0xb1, 0xe3, 0x5e, 0x65, 0xc1, 0x2c, 0xcb, 0x72, 0x85, 0x5d, 0x00, 0x5d,
0x82, 0x56, 0xff, 0x54, 0x00, 0xd7, 0x86, 0x2d, 0xb9, 0x85, 0x3d, 0x42, 0x79, 0xc4, 0x43, 0x37, 0xcc, 0xf8, 0x6d, 0x8a, 0x7d, 0xa6, 0xdc, 0x3a, 0x1e, 0xd1, 0xe1, 0xfb, 0xd2, 0xd3, 0xa5, 0x87,
0x8e, 0xb0, 0xab, 0x32, 0x4e, 0x47, 0xfc, 0x40, 0x48, 0x91, 0xd2, 0xc2, 0x17, 0xc1, 0x0c, 0x75, 0x58, 0xd1, 0x58, 0xd1, 0x90, 0xf0, 0xe6, 0x90, 0x37, 0x74, 0x02, 0x82, 0xb8, 0x58, 0x94, 0x60,
0xfc, 0x76, 0xec, 0xe2, 0x48, 0xa5, 0x93, 0xde, 0x75, 0x53, 0xc9, 0x91, 0xb6, 0x80, 0x35, 0x00, 0x66, 0xee, 0x8a, 0x89, 0x25, 0x92, 0x52, 0xa4, 0xb5, 0xf0, 0x8b, 0x60, 0xc6, 0x23, 0x8c, 0xe1,
0xe8, 0x51, 0x10, 0x31, 0x81, 0x61, 0x16, 0xd7, 0x8a, 0xdc, 0x33, 0x2f, 0x10, 0x4d, 0x2d, 0x45, 0x0e, 0x91, 0x17, 0x64, 0xb6, 0xb1, 0xa0, 0x0d, 0x67, 0xb6, 0x94, 0x18, 0xc5, 0xfa, 0xea, 0xb1,
0x19, 0x0b, 0xb8, 0x06, 0x26, 0x8f, 0x1d, 0xdf, 0x56, 0xa7, 0xae, 0x6f, 0xf1, 0xb7, 0x1c, 0xdf, 0x05, 0x2e, 0x8c, 0x8a, 0xda, 0x4d, 0x87, 0x71, 0xf8, 0xe6, 0xd0, 0x05, 0xa8, 0x3d, 0xdd, 0x0e,
0x46, 0x42, 0xc3, 0xf1, 0x5d, 0x87, 0x32, 0x2e, 0x51, 0x47, 0x9e, 0x8b, 0xba, 0xb0, 0xd4, 0x16, 0xc5, 0x6a, 0x99, 0xfe, 0xe6, 0x76, 0xc6, 0x92, 0x54, 0xf2, 0x7f, 0x0f, 0x14, 0x1c, 0x4e, 0x3c,
0x1c, 0xdf, 0xc2, 0x8c, 0xb4, 0x83, 0xc8, 0x21, 0xd4, 0x9c, 0x4a, 0xf1, 0xb7, 0xb4, 0x14, 0x65, 0x71, 0x06, 0xf9, 0xb5, 0xd2, 0xb5, 0x6f, 0x4f, 0x28, 0xf7, 0x1a, 0xf3, 0x9a, 0x43, 0xe1, 0x86,
0x2c, 0xaa, 0xff, 0x2a, 0x0d, 0x4f, 0x12, 0x5e, 0x4a, 0xe0, 0x73, 0xa0, 0xd4, 0x8e, 0x82, 0x38, 0x40, 0x43, 0x0a, 0xb4, 0xfa, 0xa7, 0x1c, 0xb8, 0x38, 0x6a, 0x89, 0xa8, 0x78, 0x4c, 0x44, 0x3c,
0x54, 0x51, 0xd2, 0xd1, 0xfe, 0x26, 0x17, 0x22, 0xa9, 0xe3, 0x59, 0xd9, 0x21, 0x11, 0x3f, 0x30, 0x74, 0x23, 0x8a, 0x5d, 0x9d, 0x71, 0x26, 0xe2, 0x3b, 0x52, 0x8a, 0xb4, 0x56, 0xd4, 0x24, 0xe6,
0x15, 0x22, 0x9d, 0x95, 0x77, 0xa5, 0x18, 0x25, 0x7a, 0xf8, 0x23, 0x03, 0x94, 0x7c, 0x15, 0x1c, 0xf8, 0x9d, 0xc8, 0xc5, 0x54, 0xa7, 0x93, 0xd9, 0x75, 0x53, 0xcb, 0x91, 0xb1, 0x80, 0x35, 0x00,
0x9e, 0x72, 0x6f, 0x8f, 0x29, 0x2f, 0x44, 0x78, 0x53, 0xba, 0x32, 0xf2, 0x12, 0x19, 0xbe, 0x02, 0xd8, 0x7e, 0x40, 0xb9, 0xc4, 0xb0, 0xf3, 0xab, 0x79, 0xe1, 0x59, 0x14, 0x88, 0xa6, 0x91, 0xa2,
0x4a, 0xd4, 0x0a, 0x42, 0xa2, 0xa2, 0x5e, 0x4e, 0x8c, 0x9a, 0x5c, 0x78, 0xd6, 0xad, 0x2c, 0x24, 0x94, 0x85, 0x28, 0xb9, 0x07, 0x8e, 0xdf, 0xd6, 0xa7, 0x6e, 0x6e, 0xf1, 0xb7, 0x1c, 0xbf, 0x8d,
0xee, 0x84, 0x00, 0x49, 0x63, 0xf8, 0x53, 0x03, 0x80, 0x0e, 0x76, 0x1d, 0x1b, 0x73, 0xff, 0xe2, 0xa4, 0x46, 0xe0, 0xbb, 0x0e, 0xe3, 0x42, 0xa2, 0x8f, 0x3c, 0x13, 0x75, 0x69, 0x69, 0x2c, 0x04,
0x2c, 0x46, 0x9d, 0xd6, 0x77, 0xb5, 0x7b, 0x79, 0x68, 0xe9, 0x37, 0xca, 0x40, 0xc3, 0x0f, 0x0d, 0x7e, 0x0b, 0x73, 0xd2, 0x09, 0xa8, 0x43, 0x98, 0x3d, 0x9d, 0xe0, 0x6f, 0x18, 0x29, 0x4a, 0x59,
0x30, 0x4f, 0xe3, 0xc3, 0x48, 0xad, 0xe2, 0xe7, 0xcc, 0xb9, 0x7c, 0x67, 0xa4, 0x5c, 0x9a, 0x19, 0x54, 0x7f, 0x3d, 0x33, 0x3a, 0x49, 0x44, 0x29, 0x81, 0x97, 0x41, 0xa1, 0x43, 0x83, 0x28, 0xd4,
0x80, 0xc6, 0x52, 0xaf, 0x5b, 0x99, 0xcf, 0x4a, 0x50, 0x8e, 0x00, 0xfc, 0xb9, 0x01, 0x66, 0xd4, 0x51, 0x32, 0xd1, 0xfe, 0xa6, 0x10, 0x22, 0xa5, 0x13, 0x59, 0xd9, 0x25, 0x54, 0x1c, 0x98, 0x0e,
0x09, 0x53, 0x73, 0x5a, 0x5c, 0xf8, 0x77, 0xc7, 0x74, 0xb0, 0x2a, 0xa3, 0xd2, 0x5b, 0xa0, 0x04, 0x91, 0xc9, 0xca, 0xbb, 0x4a, 0x8c, 0x62, 0x3d, 0xfc, 0x91, 0x05, 0x0a, 0xbe, 0x0e, 0x8e, 0x48,
0x14, 0x69, 0x06, 0xd5, 0x0f, 0x8b, 0xa0, 0xfc, 0xc9, 0x8f, 0x15, 0x7c, 0x68, 0x00, 0x60, 0x25, 0xb9, 0x37, 0x27, 0x94, 0x17, 0x32, 0xbc, 0x09, 0x5d, 0x15, 0x79, 0x85, 0x0c, 0x5f, 0x02, 0x05,
0x8f, 0x00, 0x35, 0x0d, 0xc1, 0xf9, 0xfd, 0x31, 0x71, 0xd6, 0xaf, 0x4d, 0xda, 0x30, 0x68, 0x11, 0xd6, 0x0a, 0x42, 0xa2, 0xa3, 0x5e, 0x8e, 0x8d, 0x9a, 0x42, 0x78, 0xdc, 0xab, 0xcc, 0xc7, 0xee,
0xbf, 0x8f, 0xfa, 0x6f, 0xf8, 0x3b, 0x03, 0x2c, 0x60, 0xcb, 0x22, 0x21, 0x23, 0xb6, 0xac, 0x21, 0xa4, 0x00, 0x29, 0x63, 0xf8, 0x53, 0x0b, 0x80, 0x2e, 0x76, 0x9d, 0x36, 0x96, 0x6f, 0x5a, 0x41,
0x85, 0xcf, 0xe0, 0x9a, 0xac, 0x28, 0x56, 0x0b, 0x9b, 0x59, 0x68, 0x94, 0x67, 0x02, 0xdf, 0x00, 0xd2, 0x1f, 0x6f, 0x5a, 0xdf, 0x35, 0xee, 0xd5, 0xa1, 0x25, 0xdf, 0x28, 0x05, 0x0d, 0xdf, 0xb7,
0x17, 0x28, 0x0b, 0x22, 0x62, 0x27, 0x11, 0x57, 0xf5, 0x0d, 0xf6, 0xba, 0x95, 0x0b, 0xcd, 0x9c, 0xc0, 0x1c, 0x8b, 0x76, 0xa9, 0x5e, 0xc5, 0xe4, 0xeb, 0x57, 0xba, 0xf6, 0x9d, 0xb1, 0x72, 0x69,
0x06, 0xf5, 0x59, 0x56, 0x7f, 0x6b, 0x80, 0xca, 0x13, 0x4e, 0x94, 0xd7, 0x42, 0x7e, 0x3f, 0x55, 0xa6, 0x00, 0x1a, 0x8b, 0xfd, 0x5e, 0x65, 0x2e, 0x2d, 0x41, 0x19, 0x02, 0xf0, 0xe7, 0x16, 0x28,
0xa5, 0xd1, 0xb5, 0x90, 0x83, 0x23, 0xa1, 0xe1, 0x35, 0x5b, 0x6c, 0xd7, 0x16, 0x51, 0x99, 0xc9, 0xea, 0x13, 0x66, 0xf6, 0x8c, 0xbc, 0xf0, 0x6f, 0x4f, 0xe8, 0x60, 0x75, 0x46, 0x25, 0xb7, 0x40,
0x74, 0x1c, 0x42, 0x8a, 0x94, 0x96, 0xd7, 0x23, 0x8e, 0xcf, 0x5f, 0xc9, 0xa2, 0x30, 0xd4, 0xf5, 0x0b, 0x18, 0x32, 0x0c, 0xe0, 0x3f, 0x2d, 0x60, 0xe3, 0xb6, 0x2a, 0xf0, 0xd8, 0xdd, 0xa1, 0x8e,
0xa8, 0x29, 0xc5, 0x28, 0xd1, 0x57, 0xff, 0x67, 0xf4, 0xa7, 0x4a, 0x26, 0xcd, 0x9b, 0x16, 0x76, 0xcf, 0x09, 0x55, 0x0d, 0x11, 0xb3, 0x8b, 0x92, 0xde, 0x78, 0xdf, 0xc2, 0xc1, 0x66, 0xab, 0xb1,
0x09, 0xdc, 0x06, 0x4b, 0xbc, 0x9f, 0x42, 0x24, 0x74, 0x1d, 0x0b, 0xd3, 0x03, 0xcc, 0x8e, 0x14, 0xaa, 0xd9, 0xd9, 0xeb, 0x23, 0x68, 0xa0, 0x91, 0x04, 0xab, 0xef, 0xe7, 0x07, 0x7b, 0xb9, 0xc1,
0x47, 0x53, 0xb9, 0x5d, 0x6a, 0xf6, 0xe9, 0xd1, 0xc0, 0x0a, 0xf8, 0x26, 0x80, 0xb2, 0xc7, 0xc8, 0xa7, 0x16, 0x3e, 0xb4, 0x00, 0x68, 0xc5, 0x4f, 0x18, 0xb3, 0x2d, 0xb9, 0xa5, 0x77, 0x27, 0x14,
0xf9, 0x91, 0xe5, 0x52, 0x77, 0x0b, 0xcd, 0x01, 0x0b, 0x74, 0xce, 0x2a, 0xb8, 0x05, 0x96, 0x5d, 0x71, 0xf3, 0x56, 0x26, 0xed, 0x8e, 0x11, 0x89, 0x6a, 0x62, 0x7e, 0xc3, 0xdf, 0x59, 0x60, 0x1e,
0x7c, 0x48, 0xdc, 0x26, 0x71, 0x89, 0xc5, 0x82, 0x48, 0xb8, 0x2a, 0x0a, 0x57, 0x2b, 0xbd, 0x6e, 0xb7, 0x5a, 0x24, 0xe4, 0xa4, 0xad, 0x2a, 0x60, 0xee, 0x33, 0xb8, 0xe4, 0xcb, 0x9a, 0xd5, 0xfc,
0x65, 0x79, 0xb7, 0x5f, 0x89, 0x06, 0xed, 0xab, 0xeb, 0xfd, 0x27, 0x92, 0xdd, 0xb8, 0xec, 0xdc, 0x7a, 0x1a, 0x1a, 0x65, 0x99, 0xc0, 0xd7, 0xc0, 0x69, 0xc6, 0x03, 0x4a, 0xda, 0x71, 0xbe, 0xe8,
0xfe, 0x50, 0x00, 0xab, 0xc3, 0xab, 0x02, 0xfc, 0x71, 0xda, 0x60, 0xca, 0xfe, 0xe1, 0xdd, 0x71, 0xea, 0x0c, 0xfb, 0xbd, 0xca, 0xe9, 0x66, 0x46, 0x83, 0x06, 0x2c, 0xab, 0xbf, 0xb5, 0x40, 0xe5,
0x55, 0x20, 0xd5, 0x61, 0x82, 0xc1, 0xee, 0x12, 0xfe, 0x80, 0x17, 0x73, 0xec, 0x12, 0x75, 0x51, 0x09, 0xf9, 0xf8, 0x14, 0xed, 0xf5, 0xf3, 0x60, 0x5a, 0x6e, 0xb7, 0x2d, 0xa3, 0x52, 0x4c, 0xf5,
0xde, 0x19, 0x1b, 0x05, 0x0e, 0xd2, 0x98, 0x95, 0xef, 0x04, 0x76, 0xc5, 0xb3, 0x80, 0x5d, 0x52, 0x4b, 0x52, 0x8a, 0xb4, 0x56, 0x54, 0x53, 0x81, 0x2f, 0xde, 0xf8, 0xbc, 0x34, 0x34, 0xd5, 0xb4,
0xfd, 0xb3, 0xd1, 0x3f, 0x63, 0xa4, 0x55, 0x1b, 0xfe, 0xc2, 0x00, 0x8b, 0x41, 0x48, 0xfc, 0xcd, 0xa9, 0xc4, 0x28, 0xd6, 0x57, 0xff, 0x67, 0x0d, 0xa6, 0x4a, 0xea, 0x92, 0x36, 0x5b, 0xd8, 0x25,
0x83, 0x9b, 0x77, 0x5f, 0x6e, 0x8a, 0xc9, 0x46, 0x85, 0xea, 0xd6, 0xa7, 0xe4, 0xf9, 0x66, 0x73, 0x70, 0x13, 0x2c, 0x8a, 0x6e, 0x10, 0x91, 0xd0, 0x75, 0x5a, 0x98, 0xc9, 0x6e, 0x59, 0x71, 0xb4,
0xff, 0x96, 0x74, 0x78, 0x10, 0x05, 0x21, 0x6d, 0x5c, 0xec, 0x75, 0x2b, 0x8b, 0xfb, 0x79, 0x28, 0xb5, 0xdb, 0xc5, 0xe6, 0x80, 0x1e, 0x0d, 0xad, 0x80, 0xaf, 0x03, 0xa8, 0x3a, 0xa4, 0x8c, 0x1f,
0xd4, 0x8f, 0x5d, 0xf5, 0xc0, 0xca, 0xce, 0x09, 0x23, 0x91, 0x8f, 0xdd, 0xed, 0xc0, 0x8a, 0x3d, 0x55, 0xec, 0x4d, 0xaf, 0xd3, 0x1c, 0xb2, 0x40, 0x27, 0xac, 0x82, 0x1b, 0x60, 0xc9, 0xc5, 0xbb,
0xe2, 0x33, 0x49, 0xf4, 0x55, 0x30, 0x67, 0x13, 0x6a, 0x45, 0x4e, 0x28, 0x1e, 0x37, 0x99, 0xde, 0xc4, 0x6d, 0x12, 0x97, 0xb4, 0x78, 0x40, 0xa5, 0x2b, 0x35, 0x4f, 0x2c, 0xf7, 0x7b, 0x95, 0xa5,
0x17, 0x55, 0x5a, 0xce, 0x6d, 0xa7, 0x2a, 0x94, 0xb5, 0x83, 0xd7, 0x40, 0x31, 0x8e, 0x5c, 0x95, 0x9b, 0x83, 0x4a, 0x34, 0x6c, 0x5f, 0xbd, 0x34, 0x78, 0x22, 0xe9, 0x8d, 0xab, 0xbe, 0xf3, 0x0f,
0xc5, 0x73, 0xca, 0xbc, 0x78, 0x07, 0xed, 0x22, 0x2e, 0xaf, 0xae, 0x83, 0x49, 0xce, 0x13, 0x5e, 0x39, 0xb0, 0x32, 0xba, 0xa6, 0xc1, 0x1f, 0x27, 0xed, 0xb1, 0xea, 0x7e, 0xde, 0x9e, 0x54, 0xfd,
0x01, 0xc5, 0x08, 0x3f, 0x10, 0x5e, 0xe7, 0x1b, 0xd3, 0xdc, 0x04, 0xe1, 0x07, 0x88, 0xcb, 0xaa, 0xd4, 0xfd, 0x31, 0x18, 0xee, 0x8d, 0xe1, 0x0f, 0xc4, 0x53, 0x84, 0x5d, 0xa2, 0x2f, 0xca, 0x5b,
0x7f, 0xb9, 0x0a, 0x16, 0xfb, 0xf6, 0x02, 0x57, 0x41, 0xc1, 0xb1, 0x15, 0x07, 0xa0, 0x9c, 0x16, 0x13, 0xa3, 0x20, 0x40, 0x1a, 0xb3, 0xea, 0x95, 0xc3, 0xae, 0x7c, 0xd4, 0xb0, 0x4b, 0xaa, 0x7f,
0x6e, 0x6e, 0xa3, 0x82, 0x63, 0xc3, 0xd7, 0xc0, 0x94, 0x9c, 0x10, 0x15, 0x68, 0x45, 0x97, 0x00, 0xb6, 0x06, 0x27, 0xa4, 0xe4, 0xcd, 0x81, 0xbf, 0xb0, 0xc0, 0x42, 0x10, 0x12, 0x7f, 0x7d, 0xe7,
0x21, 0xe5, 0xaf, 0x77, 0xea, 0x8e, 0x13, 0x51, 0xe6, 0x82, 0x03, 0x69, 0xa9, 0x5b, 0x22, 0x39, 0xc6, 0xdd, 0x17, 0x9b, 0x72, 0x5a, 0xd5, 0xa1, 0xba, 0xf5, 0x29, 0x79, 0x8a, 0xb9, 0x4d, 0x39,
0x90, 0x16, 0xe2, 0xb2, 0xfe, 0xcd, 0x4f, 0x3e, 0xe5, 0xe6, 0xd7, 0xd4, 0xc4, 0x52, 0xca, 0xd7, 0xdc, 0xa1, 0x41, 0xc8, 0x1a, 0x67, 0xfa, 0xbd, 0xca, 0xc2, 0x76, 0x16, 0x0a, 0x0d, 0x62, 0x57,
0xab, 0xcc, 0x20, 0xf2, 0x02, 0x98, 0x6a, 0x05, 0x91, 0x87, 0x99, 0x78, 0xa1, 0x33, 0x3d, 0xe6, 0x3d, 0xb0, 0x7c, 0xfd, 0x90, 0x13, 0xea, 0x63, 0x77, 0x33, 0x68, 0x45, 0x1e, 0xf1, 0xb9, 0x22,
0x37, 0x84, 0x14, 0x29, 0x2d, 0x6f, 0xb2, 0x98, 0xc3, 0x5c, 0x62, 0x4e, 0xe7, 0x9b, 0xac, 0xdb, 0x3a, 0x30, 0x6e, 0x5a, 0x4f, 0x39, 0x6e, 0x5e, 0x04, 0xf9, 0x88, 0xba, 0x3a, 0x8b, 0x4b, 0xda,
0x5c, 0x88, 0xa4, 0x0e, 0xde, 0x03, 0xd3, 0x36, 0x69, 0xe1, 0xd8, 0x65, 0xe6, 0x8c, 0x48, 0xa1, 0x3c, 0x7f, 0x07, 0xdd, 0x44, 0x42, 0x5e, 0xbd, 0x04, 0xa6, 0x04, 0x4f, 0x78, 0x1e, 0xe4, 0x29,
0xad, 0x11, 0xa4, 0x50, 0x63, 0x8e, 0x57, 0xc5, 0x6d, 0xe9, 0x17, 0x25, 0x00, 0xf0, 0x79, 0x30, 0x7e, 0x20, 0xbd, 0xce, 0x35, 0x66, 0x84, 0x09, 0xc2, 0x0f, 0x90, 0x90, 0x55, 0xff, 0x72, 0x01,
0xed, 0xe1, 0x13, 0xc7, 0x8b, 0x3d, 0x73, 0x76, 0xcd, 0xd8, 0x30, 0xa4, 0xd9, 0x9e, 0x14, 0xa1, 0x2c, 0x0c, 0xec, 0x05, 0xae, 0x80, 0x9c, 0xd3, 0xd6, 0x1c, 0x80, 0x76, 0x9a, 0xbb, 0xb1, 0x89,
0x44, 0xc7, 0x2b, 0x23, 0x39, 0xb1, 0xdc, 0x98, 0x3a, 0x1d, 0xa2, 0x94, 0x26, 0x10, 0x05, 0x57, 0x72, 0x4e, 0x1b, 0xbe, 0x02, 0xa6, 0xd5, 0xd4, 0xaf, 0x41, 0x2b, 0xa6, 0x04, 0x48, 0xa9, 0xe8,
0x57, 0xc6, 0x9d, 0x3e, 0x3d, 0x1a, 0x58, 0x21, 0xc0, 0x1c, 0x5f, 0x2c, 0x9e, 0xcb, 0x80, 0x49, 0x3d, 0x12, 0x77, 0x82, 0x88, 0x36, 0x97, 0x1c, 0xc8, 0x9e, 0xbe, 0x25, 0x8a, 0x03, 0xd9, 0x43,
0x11, 0x4a, 0x74, 0x79, 0x30, 0x65, 0x3f, 0x3f, 0x0c, 0x4c, 0x2d, 0x1e, 0x58, 0x01, 0xbf, 0x0c, 0x42, 0xf6, 0x49, 0x67, 0xed, 0x78, 0xd8, 0x2f, 0x3c, 0xc5, 0xb0, 0x3f, 0xfd, 0xb1, 0xc3, 0xfe,
0x66, 0x3d, 0x7c, 0xb2, 0x4b, 0xfc, 0x36, 0x3b, 0x32, 0x17, 0xd6, 0x8c, 0x8d, 0x62, 0x63, 0xa1, 0x65, 0x50, 0xe0, 0x0e, 0x77, 0x89, 0x3d, 0x93, 0x6d, 0x11, 0x6f, 0x0b, 0x21, 0x52, 0x3a, 0x78,
0xd7, 0xad, 0xcc, 0xee, 0x25, 0x42, 0x94, 0xea, 0x85, 0xb1, 0xe3, 0x2b, 0xe3, 0x0b, 0x19, 0xe3, 0x0f, 0xcc, 0xb4, 0xc9, 0x1e, 0x8e, 0x5c, 0x6e, 0x17, 0x65, 0x0a, 0x6d, 0x8c, 0x21, 0x85, 0x1a,
0x44, 0x88, 0x52, 0x3d, 0x7f, 0x74, 0x42, 0xcc, 0xf8, 0xe5, 0x32, 0x17, 0xf3, 0x4d, 0xf0, 0x81, 0x25, 0x51, 0x15, 0x37, 0x95, 0x5f, 0x14, 0x03, 0xc0, 0xe7, 0xc0, 0x8c, 0x87, 0x0f, 0x1d, 0x2f,
0x14, 0xa3, 0x44, 0x0f, 0x37, 0xc0, 0x8c, 0x87, 0x4f, 0xc4, 0xc0, 0x62, 0x2e, 0x09, 0xb7, 0xf3, 0xf2, 0xec, 0xd9, 0x55, 0x6b, 0xcd, 0x52, 0x66, 0x5b, 0x4a, 0x84, 0x62, 0x9d, 0xa8, 0x8c, 0xe4,
0xbc, 0x93, 0xd9, 0x53, 0x32, 0xa4, 0xb5, 0xc2, 0xd2, 0xf1, 0xa5, 0xe5, 0x72, 0xc6, 0x52, 0xc9, 0xb0, 0xe5, 0x46, 0xcc, 0xe9, 0x12, 0xad, 0xb4, 0x81, 0x2c, 0xb8, 0xa6, 0x32, 0x5e, 0x1f, 0xd0,
0x90, 0xd6, 0xf2, 0x24, 0x8e, 0x7d, 0xe7, 0x7e, 0x4c, 0xa4, 0x31, 0x14, 0x91, 0xd1, 0x49, 0x7c, 0xa3, 0xa1, 0x15, 0x12, 0xcc, 0xf1, 0xe5, 0xe2, 0x52, 0x0a, 0x4c, 0x89, 0x50, 0xac, 0xcb, 0x82,
0x27, 0x55, 0xa1, 0xac, 0x1d, 0x1f, 0x18, 0xbc, 0xd8, 0x65, 0x4e, 0xe8, 0x92, 0xfd, 0x96, 0x79, 0x69, 0xfb, 0xb9, 0x51, 0x60, 0x7a, 0xf1, 0xd0, 0x0a, 0xf8, 0x65, 0x30, 0xeb, 0xe1, 0xc3, 0x9b,
0x51, 0xc4, 0x5f, 0xf4, 0x9e, 0x7b, 0x5a, 0x8a, 0x32, 0x16, 0x90, 0x80, 0x49, 0xe2, 0xc7, 0x9e, 0xc4, 0xef, 0xf0, 0x7d, 0x7b, 0x7e, 0xd5, 0x5a, 0xcb, 0x37, 0xe6, 0xfb, 0xbd, 0xca, 0xec, 0x56,
0x79, 0x49, 0x34, 0x4c, 0x23, 0x49, 0x41, 0x7d, 0x73, 0x76, 0xfc, 0xd8, 0x43, 0xc2, 0x3d, 0x7c, 0x2c, 0x44, 0x89, 0x5e, 0x1a, 0x3b, 0xbe, 0x36, 0x3e, 0x9d, 0x32, 0x8e, 0x85, 0x28, 0xd1, 0x8b,
0x0d, 0x2c, 0x78, 0xf8, 0x84, 0x97, 0x03, 0x12, 0x31, 0x3e, 0xca, 0xac, 0x88, 0xcd, 0x2f, 0xf3, 0x47, 0x27, 0xc4, 0x5c, 0x5c, 0x2e, 0x7b, 0x21, 0xdb, 0xc2, 0xef, 0x28, 0x31, 0x8a, 0xf5, 0x70,
0x26, 0x65, 0x2f, 0xab, 0x40, 0x79, 0x3b, 0xb1, 0xd0, 0xf1, 0x33, 0x0b, 0x2f, 0x67, 0x16, 0x66, 0x0d, 0x14, 0x3d, 0x7c, 0x28, 0xc7, 0x2d, 0x7b, 0x51, 0xba, 0x9d, 0x13, 0x7d, 0xd8, 0x96, 0x96,
0x15, 0x28, 0x6f, 0xc7, 0x23, 0x1d, 0x91, 0xfb, 0xb1, 0x13, 0x11, 0xdb, 0xfc, 0x9c, 0xe8, 0x6b, 0x21, 0xa3, 0x95, 0x96, 0x8e, 0xaf, 0x2c, 0x97, 0x52, 0x96, 0x5a, 0x86, 0x8c, 0x56, 0x24, 0x71,
0x44, 0xa4, 0x91, 0x92, 0x21, 0xad, 0x85, 0x9d, 0x64, 0xb2, 0x35, 0xc5, 0x35, 0xbc, 0x33, 0xda, 0xe4, 0x3b, 0xf7, 0x23, 0xa2, 0x8c, 0xa1, 0x8c, 0x8c, 0x49, 0xe2, 0x3b, 0x89, 0x0a, 0xa5, 0xed,
0x4a, 0xbe, 0x1f, 0x6d, 0x46, 0x11, 0x3e, 0x95, 0x2f, 0x4d, 0x76, 0xa6, 0x85, 0x14, 0x94, 0xb0, 0xc4, 0xb8, 0xe3, 0x45, 0x2e, 0x77, 0x42, 0x97, 0x6c, 0xef, 0xd9, 0x67, 0x64, 0xfc, 0x65, 0xe7,
0xeb, 0xee, 0xb7, 0xcc, 0x2b, 0x22, 0xf6, 0xa3, 0x7e, 0x41, 0x74, 0xd5, 0xd9, 0xe4, 0x20, 0x48, 0xbc, 0x65, 0xa4, 0x28, 0x65, 0x01, 0x09, 0x98, 0x22, 0x7e, 0xe4, 0xd9, 0x67, 0x65, 0xc3, 0x34,
0x62, 0x71, 0xd0, 0xc0, 0xe7, 0xa9, 0xb1, 0x3a, 0x5e, 0xd0, 0x7d, 0x0e, 0x82, 0x24, 0x96, 0xd8, 0x96, 0x14, 0x34, 0x37, 0xe7, 0xba, 0x1f, 0x79, 0x48, 0xba, 0x87, 0xaf, 0x80, 0x79, 0x0f, 0x1f,
0xa9, 0x7f, 0xba, 0xdf, 0x32, 0x3f, 0x3f, 0xe6, 0x9d, 0x72, 0x10, 0x24, 0xb1, 0xa0, 0x03, 0x8a, 0x8a, 0x72, 0x40, 0x28, 0x17, 0x83, 0xd8, 0xb2, 0xdc, 0xfc, 0x92, 0x68, 0x52, 0xb6, 0xd2, 0x0a,
0x7e, 0xc0, 0xcc, 0xab, 0x63, 0x79, 0x9e, 0xc5, 0x83, 0x73, 0x2b, 0x60, 0x88, 0x63, 0xc0, 0x5f, 0x94, 0xb5, 0x93, 0x0b, 0x1d, 0x3f, 0xb5, 0xf0, 0x5c, 0x6a, 0x61, 0x5a, 0x81, 0xb2, 0x76, 0x22,
0x1b, 0x00, 0x84, 0x69, 0x8a, 0x5e, 0x1b, 0xc9, 0xc0, 0xd4, 0x07, 0x59, 0x4b, 0x73, 0x7b, 0xc7, 0xd2, 0x94, 0xdc, 0x8f, 0x1c, 0x4a, 0xda, 0xf6, 0xe7, 0x64, 0x5f, 0x23, 0x23, 0x8d, 0xb4, 0x0c,
0x67, 0xd1, 0x69, 0x3a, 0x7a, 0x64, 0xee, 0x40, 0x86, 0x05, 0xfc, 0xa3, 0x01, 0x2e, 0x61, 0x5b, 0x19, 0x2d, 0xec, 0xc6, 0x73, 0xb9, 0x2d, 0xaf, 0xe1, 0x9d, 0xf1, 0x56, 0xf2, 0x6d, 0xba, 0x4e,
0x0e, 0x22, 0xd8, 0xcd, 0xdc, 0xa0, 0xb2, 0x88, 0xc8, 0xed, 0x51, 0xa7, 0x79, 0x23, 0x08, 0xdc, 0x29, 0x3e, 0x52, 0x2f, 0x4d, 0x7a, 0x22, 0x87, 0x0c, 0x14, 0xb0, 0xeb, 0x6e, 0xef, 0xd9, 0xe7,
0x86, 0xd9, 0xeb, 0x56, 0x2e, 0x6d, 0x9e, 0x83, 0x8a, 0xce, 0xe5, 0x02, 0xff, 0x6a, 0x80, 0x65, 0x65, 0xec, 0xc7, 0xfd, 0x82, 0x98, 0xaa, 0xb3, 0x2e, 0x40, 0x90, 0xc2, 0x12, 0xa0, 0x81, 0x2f,
0x55, 0x45, 0x33, 0x0c, 0x2b, 0x22, 0x80, 0x64, 0xd4, 0x01, 0xec, 0xc7, 0x91, 0x71, 0xbc, 0xa2, 0x52, 0x63, 0x65, 0xb2, 0xa0, 0xdb, 0x02, 0x04, 0x29, 0x2c, 0xb9, 0x53, 0xff, 0x68, 0x7b, 0xcf,
0xe2, 0xb8, 0x3c, 0xa0, 0x47, 0x83, 0xd4, 0xe0, 0x3f, 0x0c, 0x30, 0x6f, 0x93, 0x90, 0xf8, 0x36, 0xfe, 0xfc, 0x84, 0x77, 0x2a, 0x40, 0x90, 0xc2, 0x82, 0x0e, 0xc8, 0xfb, 0x01, 0xb7, 0x2f, 0x4c,
0xf1, 0x2d, 0xce, 0x75, 0x6d, 0x24, 0x93, 0x66, 0x3f, 0xd7, 0xed, 0x0c, 0x84, 0xa4, 0x59, 0x53, 0xe4, 0x79, 0x96, 0x0f, 0xce, 0xad, 0x80, 0x23, 0x81, 0x01, 0x7f, 0x63, 0x01, 0x10, 0x26, 0x29,
0x34, 0xe7, 0xb3, 0xaa, 0xb3, 0x6e, 0xe5, 0x72, 0xba, 0x34, 0xab, 0x41, 0x39, 0x96, 0xf0, 0x37, 0x7a, 0x71, 0x2c, 0xe3, 0xde, 0x00, 0x64, 0x2d, 0xc9, 0xed, 0xeb, 0x3e, 0xa7, 0x47, 0xc9, 0xe8,
0x06, 0x58, 0x4c, 0x0f, 0x40, 0x3e, 0x29, 0xeb, 0x63, 0xcc, 0x03, 0xd1, 0xbe, 0x6e, 0xe6, 0x01, 0x91, 0xba, 0x03, 0x29, 0x16, 0xf0, 0x8f, 0x16, 0x38, 0x9b, 0x9e, 0xa8, 0x0c, 0xbd, 0xb2, 0x8c,
0x51, 0x3f, 0x03, 0xf8, 0x37, 0x83, 0x77, 0x6a, 0xc9, 0xdc, 0x48, 0xcd, 0xaa, 0x88, 0xe5, 0x7b, 0xc8, 0xed, 0x71, 0xa7, 0x79, 0x23, 0x08, 0xdc, 0x86, 0xdd, 0xef, 0x55, 0xce, 0xae, 0x9f, 0x80,
0x23, 0x8f, 0xa5, 0x46, 0x90, 0xa1, 0x7c, 0x31, 0x6d, 0x05, 0xb5, 0xe6, 0xac, 0x5b, 0x59, 0xc9, 0x8a, 0x4e, 0xe4, 0x02, 0xff, 0x6a, 0x81, 0x25, 0x5d, 0x45, 0x53, 0x0c, 0x2b, 0x32, 0x80, 0x64,
0x46, 0x52, 0x2b, 0x50, 0x96, 0x21, 0xfc, 0x99, 0x01, 0xe6, 0x49, 0xda, 0x71, 0x53, 0xf3, 0xb9, 0xdc, 0x01, 0x1c, 0xc4, 0x51, 0x71, 0x3c, 0xaf, 0xe3, 0xb8, 0x34, 0xa4, 0x47, 0xc3, 0xd4, 0xe0,
0x91, 0x04, 0xf1, 0xdc, 0x26, 0x5e, 0xfe, 0x4a, 0x93, 0x51, 0x51, 0x94, 0xc3, 0xe6, 0x1d, 0x24, 0x3f, 0x2c, 0x30, 0xd7, 0x26, 0x21, 0xf1, 0xdb, 0xc4, 0x6f, 0x09, 0xae, 0xab, 0x63, 0x99, 0x34,
0x39, 0xc1, 0x5e, 0xe8, 0x12, 0xf3, 0x0b, 0x23, 0xee, 0x20, 0x77, 0xa4, 0x5f, 0x94, 0x00, 0xac, 0x07, 0xb9, 0x6e, 0xa6, 0x20, 0x14, 0xcd, 0x9a, 0xa6, 0x39, 0x97, 0x56, 0x1d, 0xf7, 0x2a, 0xe7,
0xf2, 0xc9, 0xa7, 0xef, 0xe6, 0xc0, 0x25, 0x50, 0x3c, 0x26, 0xa7, 0xb2, 0xb1, 0x47, 0xfc, 0x4f, 0x92, 0xa5, 0x69, 0x0d, 0xca, 0xb0, 0x84, 0x1f, 0x58, 0x60, 0x21, 0x39, 0x00, 0xf5, 0xa4, 0x5c,
0x68, 0x83, 0x52, 0x07, 0xbb, 0x71, 0x32, 0xbc, 0x8d, 0xb8, 0xea, 0x22, 0xe9, 0xfc, 0x8d, 0xc2, 0x9a, 0x60, 0x1e, 0xc8, 0xf6, 0x75, 0x3d, 0x0b, 0x88, 0x06, 0x19, 0xc0, 0xbf, 0x59, 0xa2, 0x53,
0xeb, 0xc6, 0xea, 0x43, 0x03, 0x5c, 0x3e, 0xff, 0x42, 0x3f, 0x53, 0x5a, 0xbf, 0x37, 0xc0, 0xf2, 0x8b, 0xe7, 0x46, 0x66, 0x57, 0x65, 0x2c, 0xdf, 0x19, 0x7b, 0x2c, 0x0d, 0x82, 0x0a, 0xe5, 0x0b,
0xc0, 0xdd, 0x3d, 0x87, 0xd1, 0xfd, 0x3c, 0xa3, 0xb7, 0x46, 0x7d, 0x09, 0x9b, 0x2c, 0x72, 0xfc, 0x49, 0x2b, 0x68, 0x34, 0xc7, 0xbd, 0xca, 0x72, 0x3a, 0x92, 0x46, 0x81, 0xd2, 0x0c, 0xe1, 0xcf,
0xb6, 0xe8, 0x3c, 0xb2, 0xf4, 0x7e, 0x69, 0x80, 0xa5, 0xfe, 0xeb, 0xf0, 0x2c, 0xe3, 0x55, 0x7d, 0x2c, 0x30, 0x47, 0x92, 0x8e, 0x9b, 0xd9, 0x97, 0xc7, 0x12, 0xc4, 0x13, 0x9b, 0x78, 0xf5, 0x37,
0x58, 0x00, 0x97, 0xcf, 0x6f, 0x98, 0x60, 0xa4, 0x27, 0xc3, 0xf1, 0x4c, 0xd8, 0x20, 0x9d, 0x32, 0xa6, 0x94, 0x8a, 0xa1, 0x0c, 0xb6, 0xe8, 0x20, 0xc9, 0x21, 0xf6, 0x42, 0x97, 0xd8, 0x5f, 0x18,
0xf5, 0x50, 0xf9, 0x81, 0x01, 0xe6, 0xee, 0x69, 0xbb, 0xe4, 0x7f, 0x1d, 0x23, 0x9f, 0xed, 0x93, 0x73, 0x07, 0x79, 0x5d, 0xf9, 0x45, 0x31, 0xc0, 0x8a, 0x98, 0x7c, 0x06, 0x6e, 0x0e, 0x5c, 0x04,
0xfa, 0x93, 0x2a, 0x28, 0xca, 0xe2, 0x56, 0xff, 0x6e, 0x80, 0x95, 0x73, 0x0b, 0x2b, 0x1f, 0x41, 0xf9, 0x03, 0x72, 0xa4, 0x1a, 0x7b, 0x24, 0x7e, 0xc2, 0x36, 0x28, 0x74, 0xb1, 0x1b, 0xc5, 0xc3,
0xb1, 0xeb, 0x06, 0x0f, 0xe4, 0x4f, 0x34, 0x99, 0x9f, 0xcc, 0x36, 0x85, 0x14, 0x29, 0x6d, 0x26, 0xdb, 0x98, 0xab, 0x2e, 0x52, 0xce, 0x5f, 0xcb, 0xbd, 0x6a, 0xad, 0x3c, 0xb4, 0xc0, 0xb9, 0x93,
0x7a, 0x85, 0xcf, 0x2a, 0x7a, 0xd5, 0x7f, 0x1a, 0xe0, 0xea, 0x27, 0x65, 0xe2, 0x33, 0x39, 0xd2, 0x2f, 0xf4, 0x33, 0xa5, 0xf5, 0x7b, 0x0b, 0x2c, 0x0d, 0xdd, 0xdd, 0x13, 0x18, 0xdd, 0xcf, 0x32,
0x0d, 0x30, 0xa3, 0x9a, 0xa2, 0x53, 0x71, 0x9c, 0x6a, 0x0e, 0x50, 0x45, 0xe3, 0x14, 0x69, 0x6d, 0x7a, 0x63, 0xdc, 0x97, 0xb0, 0xc9, 0xa9, 0xe3, 0x77, 0x64, 0xe7, 0x91, 0xa6, 0xf7, 0x4b, 0x0b,
0xe3, 0xfa, 0xa3, 0xc7, 0xe5, 0x89, 0x8f, 0x1e, 0x97, 0x27, 0x3e, 0x7e, 0x5c, 0x9e, 0xf8, 0x61, 0x2c, 0x0e, 0x5e, 0x87, 0x67, 0x19, 0xaf, 0xea, 0xc3, 0x1c, 0x38, 0x77, 0x72, 0xc3, 0x04, 0xa9,
0xaf, 0x6c, 0x3c, 0xea, 0x95, 0x8d, 0x8f, 0x7a, 0x65, 0xe3, 0xe3, 0x5e, 0xd9, 0xf8, 0x77, 0xaf, 0x99, 0x0c, 0x27, 0x33, 0x61, 0x83, 0x64, 0xca, 0x34, 0x43, 0xe5, 0x7b, 0x16, 0x28, 0xdd, 0x33,
0x6c, 0xfc, 0xea, 0x3f, 0xe5, 0x89, 0xef, 0x4e, 0x2b, 0xf0, 0xff, 0x07, 0x00, 0x00, 0xff, 0xff, 0x76, 0xf1, 0x7f, 0x6a, 0xc6, 0x3e, 0xdb, 0xc7, 0xf5, 0x27, 0x51, 0x30, 0x94, 0xc6, 0xad, 0xfe,
0x8c, 0x3a, 0x89, 0x32, 0x37, 0x20, 0x00, 0x00, 0xdd, 0x02, 0xcb, 0x27, 0x16, 0x56, 0x31, 0x82, 0x62, 0xd7, 0x0d, 0x1e, 0xa8, 0x3f, 0xd1, 0xa4,
0xfe, 0x64, 0xb6, 0x2e, 0xa5, 0x48, 0x6b, 0x53, 0xd1, 0xcb, 0x7d, 0x56, 0xd1, 0xab, 0xfe, 0xcb,
0x02, 0x17, 0x3e, 0x2e, 0x13, 0x9f, 0xc9, 0x91, 0xae, 0x81, 0xa2, 0x6e, 0x8a, 0x8e, 0xe4, 0x71,
0xea, 0x39, 0x40, 0x17, 0x0d, 0xf9, 0xdf, 0x73, 0xf5, 0xab, 0x71, 0xe5, 0xd1, 0xe3, 0xf2, 0xa9,
0x0f, 0x1f, 0x97, 0x4f, 0x7d, 0xf4, 0xb8, 0x7c, 0xea, 0x87, 0xfd, 0xb2, 0xf5, 0xa8, 0x5f, 0xb6,
0x3e, 0xec, 0x97, 0xad, 0x8f, 0xfa, 0x65, 0xeb, 0xdf, 0xfd, 0xb2, 0xf5, 0xab, 0xff, 0x94, 0x4f,
0x7d, 0x77, 0x46, 0x83, 0xff, 0x3f, 0x00, 0x00, 0xff, 0xff, 0x9e, 0x11, 0xe8, 0x41, 0x0b, 0x22,
0x00, 0x00,
} }

View File

@ -29,6 +29,32 @@ import "k8s.io/apimachinery/pkg/util/intstr/generated.proto";
// Package-wide variables from generator "generated". // Package-wide variables from generator "generated".
option go_package = "v1beta1"; option go_package = "v1beta1";
// CustomResourceColumnDefinition specifies a column for server side printing.
message CustomResourceColumnDefinition {
// name is a human readable name for the column.
optional string name = 1;
// type is an OpenAPI type definition for this column.
// See https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md#data-types for more.
optional string type = 2;
// format is an optional OpenAPI type definition for this column. The 'name' format is applied
// to the primary identifier column to assist in clients identifying column is the resource name.
// See https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md#data-types for more.
optional string format = 3;
// description is a human readable description of this column.
optional string description = 4;
// priority is an integer defining the relative importance of this column compared to others. Lower
// numbers are considered higher priority. Columns that may be omitted in limited space scenarios
// should be given a higher priority.
optional int32 priority = 5;
// JSONPath is a simple JSON path, i.e. with array notation.
optional string JSONPath = 6;
}
// CustomResourceDefinition represents a resource that should be exposed on the API server. Its name MUST be in the format // CustomResourceDefinition represents a resource that should be exposed on the API server. Its name MUST be in the format
// <.spec.name>.<.spec.group>. // <.spec.name>.<.spec.group>.
message CustomResourceDefinition { message CustomResourceDefinition {
@ -132,6 +158,9 @@ message CustomResourceDefinitionSpec {
// major version, then minor version. An example sorted list of versions: // major version, then minor version. An example sorted list of versions:
// v10, v2, v1, v11beta2, v10beta3, v3beta1, v12alpha1, v11alpha2, foo1, foo10. // v10, v2, v1, v11beta2, v10beta3, v3beta1, v12alpha1, v11alpha2, foo1, foo10.
repeated CustomResourceDefinitionVersion versions = 7; repeated CustomResourceDefinitionVersion versions = 7;
// AdditionalPrinterColumns are additional columns shown e.g. in kubectl next to the name. Defaults to a created-at column.
repeated CustomResourceColumnDefinition additionalPrinterColumns = 8;
} }
// CustomResourceDefinitionStatus indicates the state of the CustomResourceDefinition // CustomResourceDefinitionStatus indicates the state of the CustomResourceDefinition

View File

@ -52,6 +52,8 @@ type CustomResourceDefinitionSpec struct {
// major version, then minor version. An example sorted list of versions: // major version, then minor version. An example sorted list of versions:
// v10, v2, v1, v11beta2, v10beta3, v3beta1, v12alpha1, v11alpha2, foo1, foo10. // v10, v2, v1, v11beta2, v10beta3, v3beta1, v12alpha1, v11alpha2, foo1, foo10.
Versions []CustomResourceDefinitionVersion `json:"versions,omitempty" protobuf:"bytes,7,rep,name=versions"` Versions []CustomResourceDefinitionVersion `json:"versions,omitempty" protobuf:"bytes,7,rep,name=versions"`
// AdditionalPrinterColumns are additional columns shown e.g. in kubectl next to the name. Defaults to a created-at column.
AdditionalPrinterColumns []CustomResourceColumnDefinition `json:"additionalPrinterColumns,omitempty" protobuf:"bytes,8,rep,name=additionalPrinterColumns"`
} }
type CustomResourceDefinitionVersion struct { type CustomResourceDefinitionVersion struct {
@ -64,6 +66,28 @@ type CustomResourceDefinitionVersion struct {
Storage bool `json:"storage" protobuf:"varint,3,opt,name=storage"` Storage bool `json:"storage" protobuf:"varint,3,opt,name=storage"`
} }
// CustomResourceColumnDefinition specifies a column for server side printing.
type CustomResourceColumnDefinition struct {
// name is a human readable name for the column.
Name string `json:"name" protobuf:"bytes,1,opt,name=name"`
// type is an OpenAPI type definition for this column.
// See https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md#data-types for more.
Type string `json:"type" protobuf:"bytes,2,opt,name=type"`
// format is an optional OpenAPI type definition for this column. The 'name' format is applied
// to the primary identifier column to assist in clients identifying column is the resource name.
// See https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md#data-types for more.
Format string `json:"format,omitempty" protobuf:"bytes,3,opt,name=format"`
// description is a human readable description of this column.
Description string `json:"description,omitempty" protobuf:"bytes,4,opt,name=description"`
// priority is an integer defining the relative importance of this column compared to others. Lower
// numbers are considered higher priority. Columns that may be omitted in limited space scenarios
// should be given a higher priority.
Priority int32 `json:"priority,omitempty" protobuf:"bytes,5,opt,name=priority"`
// JSONPath is a simple JSON path, i.e. with array notation.
JSONPath string `json:"JSONPath" protobuf:"bytes,6,opt,name=JSONPath"`
}
// CustomResourceDefinitionNames indicates the names to serve this CustomResourceDefinition // CustomResourceDefinitionNames indicates the names to serve this CustomResourceDefinition
type CustomResourceDefinitionNames struct { type CustomResourceDefinitionNames struct {
// Plural is the plural name of the resource to serve. It must match the name of the CustomResourceDefinition-registration // Plural is the plural name of the resource to serve. It must match the name of the CustomResourceDefinition-registration

View File

@ -36,6 +36,8 @@ func init() {
// Public to allow building arbitrary schemes. // Public to allow building arbitrary schemes.
func RegisterConversions(scheme *runtime.Scheme) error { func RegisterConversions(scheme *runtime.Scheme) error {
return scheme.AddGeneratedConversionFuncs( return scheme.AddGeneratedConversionFuncs(
Convert_v1beta1_CustomResourceColumnDefinition_To_apiextensions_CustomResourceColumnDefinition,
Convert_apiextensions_CustomResourceColumnDefinition_To_v1beta1_CustomResourceColumnDefinition,
Convert_v1beta1_CustomResourceDefinition_To_apiextensions_CustomResourceDefinition, Convert_v1beta1_CustomResourceDefinition_To_apiextensions_CustomResourceDefinition,
Convert_apiextensions_CustomResourceDefinition_To_v1beta1_CustomResourceDefinition, Convert_apiextensions_CustomResourceDefinition_To_v1beta1_CustomResourceDefinition,
Convert_v1beta1_CustomResourceDefinitionCondition_To_apiextensions_CustomResourceDefinitionCondition, Convert_v1beta1_CustomResourceDefinitionCondition_To_apiextensions_CustomResourceDefinitionCondition,
@ -73,6 +75,36 @@ func RegisterConversions(scheme *runtime.Scheme) error {
) )
} }
func autoConvert_v1beta1_CustomResourceColumnDefinition_To_apiextensions_CustomResourceColumnDefinition(in *CustomResourceColumnDefinition, out *apiextensions.CustomResourceColumnDefinition, s conversion.Scope) error {
out.Name = in.Name
out.Type = in.Type
out.Format = in.Format
out.Description = in.Description
out.Priority = in.Priority
out.JSONPath = in.JSONPath
return nil
}
// Convert_v1beta1_CustomResourceColumnDefinition_To_apiextensions_CustomResourceColumnDefinition is an autogenerated conversion function.
func Convert_v1beta1_CustomResourceColumnDefinition_To_apiextensions_CustomResourceColumnDefinition(in *CustomResourceColumnDefinition, out *apiextensions.CustomResourceColumnDefinition, s conversion.Scope) error {
return autoConvert_v1beta1_CustomResourceColumnDefinition_To_apiextensions_CustomResourceColumnDefinition(in, out, s)
}
func autoConvert_apiextensions_CustomResourceColumnDefinition_To_v1beta1_CustomResourceColumnDefinition(in *apiextensions.CustomResourceColumnDefinition, out *CustomResourceColumnDefinition, s conversion.Scope) error {
out.Name = in.Name
out.Type = in.Type
out.Format = in.Format
out.Description = in.Description
out.Priority = in.Priority
out.JSONPath = in.JSONPath
return nil
}
// Convert_apiextensions_CustomResourceColumnDefinition_To_v1beta1_CustomResourceColumnDefinition is an autogenerated conversion function.
func Convert_apiextensions_CustomResourceColumnDefinition_To_v1beta1_CustomResourceColumnDefinition(in *apiextensions.CustomResourceColumnDefinition, out *CustomResourceColumnDefinition, s conversion.Scope) error {
return autoConvert_apiextensions_CustomResourceColumnDefinition_To_v1beta1_CustomResourceColumnDefinition(in, out, s)
}
func autoConvert_v1beta1_CustomResourceDefinition_To_apiextensions_CustomResourceDefinition(in *CustomResourceDefinition, out *apiextensions.CustomResourceDefinition, s conversion.Scope) error { func autoConvert_v1beta1_CustomResourceDefinition_To_apiextensions_CustomResourceDefinition(in *CustomResourceDefinition, out *apiextensions.CustomResourceDefinition, s conversion.Scope) error {
out.ObjectMeta = in.ObjectMeta out.ObjectMeta = in.ObjectMeta
if err := Convert_v1beta1_CustomResourceDefinitionSpec_To_apiextensions_CustomResourceDefinitionSpec(&in.Spec, &out.Spec, s); err != nil { if err := Convert_v1beta1_CustomResourceDefinitionSpec_To_apiextensions_CustomResourceDefinitionSpec(&in.Spec, &out.Spec, s); err != nil {
@ -223,6 +255,7 @@ func autoConvert_v1beta1_CustomResourceDefinitionSpec_To_apiextensions_CustomRes
} }
out.Subresources = (*apiextensions.CustomResourceSubresources)(unsafe.Pointer(in.Subresources)) out.Subresources = (*apiextensions.CustomResourceSubresources)(unsafe.Pointer(in.Subresources))
out.Versions = *(*[]apiextensions.CustomResourceDefinitionVersion)(unsafe.Pointer(&in.Versions)) out.Versions = *(*[]apiextensions.CustomResourceDefinitionVersion)(unsafe.Pointer(&in.Versions))
out.AdditionalPrinterColumns = *(*[]apiextensions.CustomResourceColumnDefinition)(unsafe.Pointer(&in.AdditionalPrinterColumns))
return nil return nil
} }
@ -249,6 +282,7 @@ func autoConvert_apiextensions_CustomResourceDefinitionSpec_To_v1beta1_CustomRes
} }
out.Subresources = (*CustomResourceSubresources)(unsafe.Pointer(in.Subresources)) out.Subresources = (*CustomResourceSubresources)(unsafe.Pointer(in.Subresources))
out.Versions = *(*[]CustomResourceDefinitionVersion)(unsafe.Pointer(&in.Versions)) out.Versions = *(*[]CustomResourceDefinitionVersion)(unsafe.Pointer(&in.Versions))
out.AdditionalPrinterColumns = *(*[]CustomResourceColumnDefinition)(unsafe.Pointer(&in.AdditionalPrinterColumns))
return nil return nil
} }

View File

@ -24,6 +24,22 @@ import (
runtime "k8s.io/apimachinery/pkg/runtime" runtime "k8s.io/apimachinery/pkg/runtime"
) )
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *CustomResourceColumnDefinition) DeepCopyInto(out *CustomResourceColumnDefinition) {
*out = *in
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CustomResourceColumnDefinition.
func (in *CustomResourceColumnDefinition) DeepCopy() *CustomResourceColumnDefinition {
if in == nil {
return nil
}
out := new(CustomResourceColumnDefinition)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *CustomResourceDefinition) DeepCopyInto(out *CustomResourceDefinition) { func (in *CustomResourceDefinition) DeepCopyInto(out *CustomResourceDefinition) {
*out = *in *out = *in
@ -155,6 +171,11 @@ func (in *CustomResourceDefinitionSpec) DeepCopyInto(out *CustomResourceDefiniti
*out = make([]CustomResourceDefinitionVersion, len(*in)) *out = make([]CustomResourceDefinitionVersion, len(*in))
copy(*out, *in) copy(*out, *in)
} }
if in.AdditionalPrinterColumns != nil {
in, out := &in.AdditionalPrinterColumns, &out.AdditionalPrinterColumns
*out = make([]CustomResourceColumnDefinition, len(*in))
copy(*out, *in)
}
return return
} }

View File

@ -15,6 +15,7 @@ go_library(
"//vendor/k8s.io/apiextensions-apiserver/pkg/apiserver/validation:go_default_library", "//vendor/k8s.io/apiextensions-apiserver/pkg/apiserver/validation:go_default_library",
"//vendor/k8s.io/apiextensions-apiserver/pkg/features:go_default_library", "//vendor/k8s.io/apiextensions-apiserver/pkg/features:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/api/validation:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/validation:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/validation:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/validation:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/validation/field:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/validation/field:go_default_library",
"//vendor/k8s.io/apiserver/pkg/util/feature:go_default_library", "//vendor/k8s.io/apiserver/pkg/util/feature:go_default_library",

View File

@ -22,6 +22,7 @@ import (
"strings" "strings"
genericvalidation "k8s.io/apimachinery/pkg/api/validation" genericvalidation "k8s.io/apimachinery/pkg/api/validation"
"k8s.io/apimachinery/pkg/util/sets"
validationutil "k8s.io/apimachinery/pkg/util/validation" validationutil "k8s.io/apimachinery/pkg/util/validation"
"k8s.io/apimachinery/pkg/util/validation/field" "k8s.io/apimachinery/pkg/util/validation/field"
utilfeature "k8s.io/apiserver/pkg/util/feature" utilfeature "k8s.io/apiserver/pkg/util/feature"
@ -31,6 +32,11 @@ import (
apiextensionsfeatures "k8s.io/apiextensions-apiserver/pkg/features" apiextensionsfeatures "k8s.io/apiextensions-apiserver/pkg/features"
) )
var (
printerColumnDatatypes = sets.NewString("integer", "number", "string", "boolean", "date")
customResourceColumnDefinitionFormats = sets.NewString("int32", "int64", "float", "double", "byte", "date", "date-time", "password")
)
// ValidateCustomResourceDefinition statically validates // ValidateCustomResourceDefinition statically validates
func ValidateCustomResourceDefinition(obj *apiextensions.CustomResourceDefinition) field.ErrorList { func ValidateCustomResourceDefinition(obj *apiextensions.CustomResourceDefinition) field.ErrorList {
nameValidationFn := func(name string, prefix bool) []string { nameValidationFn := func(name string, prefix bool) []string {
@ -175,6 +181,12 @@ func ValidateCustomResourceDefinitionSpec(spec *apiextensions.CustomResourceDefi
allErrs = append(allErrs, field.Forbidden(fldPath.Child("subresources"), "disabled by feature-gate CustomResourceSubresources")) allErrs = append(allErrs, field.Forbidden(fldPath.Child("subresources"), "disabled by feature-gate CustomResourceSubresources"))
} }
for i := range spec.AdditionalPrinterColumns {
if errs := ValidateCustomResourceColumnDefinition(&spec.AdditionalPrinterColumns[i], fldPath.Child("columns").Index(i)); len(errs) > 0 {
allErrs = append(allErrs, errs...)
}
}
return allErrs return allErrs
} }
@ -238,6 +250,33 @@ func ValidateCustomResourceDefinitionNames(names *apiextensions.CustomResourceDe
return allErrs return allErrs
} }
// ValidateCustomResourceColumnDefinition statically validates a printer column.
func ValidateCustomResourceColumnDefinition(col *apiextensions.CustomResourceColumnDefinition, fldPath *field.Path) field.ErrorList {
allErrs := field.ErrorList{}
if len(col.Name) == 0 {
allErrs = append(allErrs, field.Required(fldPath.Child("header"), ""))
}
if len(col.Type) == 0 {
allErrs = append(allErrs, field.Required(fldPath.Child("type"), fmt.Sprintf("must be one of %s", strings.Join(printerColumnDatatypes.List(), ","))))
} else if !printerColumnDatatypes.Has(col.Type) {
allErrs = append(allErrs, field.Invalid(fldPath.Child("type"), col.Type, fmt.Sprintf("must be one of %s", strings.Join(printerColumnDatatypes.List(), ","))))
}
if len(col.Format) > 0 && !customResourceColumnDefinitionFormats.Has(col.Format) {
allErrs = append(allErrs, field.Invalid(fldPath.Child("format"), col.Format, fmt.Sprintf("must be one of %s", strings.Join(customResourceColumnDefinitionFormats.List(), ","))))
}
if len(col.JSONPath) == 0 {
allErrs = append(allErrs, field.Required(fldPath.Child("path"), ""))
} else if errs := validateSimpleJSONPath(col.JSONPath, fldPath.Child("path")); len(errs) > 0 {
allErrs = append(allErrs, errs...)
}
return allErrs
}
// specStandardValidator applies validations for different OpenAPI specification versions. // specStandardValidator applies validations for different OpenAPI specification versions.
type specStandardValidator interface { type specStandardValidator interface {
validate(spec *apiextensions.JSONSchemaProps, fldPath *field.Path) field.ErrorList validate(spec *apiextensions.JSONSchemaProps, fldPath *field.Path) field.ErrorList

View File

@ -24,6 +24,22 @@ import (
runtime "k8s.io/apimachinery/pkg/runtime" runtime "k8s.io/apimachinery/pkg/runtime"
) )
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *CustomResourceColumnDefinition) DeepCopyInto(out *CustomResourceColumnDefinition) {
*out = *in
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CustomResourceColumnDefinition.
func (in *CustomResourceColumnDefinition) DeepCopy() *CustomResourceColumnDefinition {
if in == nil {
return nil
}
out := new(CustomResourceColumnDefinition)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *CustomResourceDefinition) DeepCopyInto(out *CustomResourceDefinition) { func (in *CustomResourceDefinition) DeepCopyInto(out *CustomResourceDefinition) {
*out = *in *out = *in
@ -155,6 +171,11 @@ func (in *CustomResourceDefinitionSpec) DeepCopyInto(out *CustomResourceDefiniti
*out = make([]CustomResourceDefinitionVersion, len(*in)) *out = make([]CustomResourceDefinitionVersion, len(*in))
copy(*out, *in) copy(*out, *in)
} }
if in.AdditionalPrinterColumns != nil {
in, out := &in.AdditionalPrinterColumns, &out.AdditionalPrinterColumns
*out = make([]CustomResourceColumnDefinition, len(*in))
copy(*out, *in)
}
return return
} }

View File

@ -370,6 +370,8 @@ func (r *crdHandler) GetCustomResourceListerCollectionDeleter(crd *apiextensions
return info.storages[info.storageVersion].CustomResource, nil return info.storages[info.storageVersion].CustomResource, nil
} }
var swaggerMetadataDescriptions = metav1.ObjectMeta{}.SwaggerDoc()
func (r *crdHandler) getOrCreateServingInfoFor(crd *apiextensions.CustomResourceDefinition) (*crdInfo, error) { func (r *crdHandler) getOrCreateServingInfoFor(crd *apiextensions.CustomResourceDefinition) (*crdInfo, error) {
storageMap := r.customStorage.Load().(crdStorageMap) storageMap := r.customStorage.Load().(crdStorageMap)
if ret, ok := storageMap[crd.UID]; ok { if ret, ok := storageMap[crd.UID]; ok {
@ -439,8 +441,7 @@ func (r *crdHandler) getOrCreateServingInfoFor(crd *apiextensions.CustomResource
scaleSpec = crd.Spec.Subresources.Scale scaleSpec = crd.Spec.Subresources.Scale
} }
// TODO: identify how to pass printer specification from the CRD table, err := tableconvertor.New(crd.Spec.AdditionalPrinterColumns)
table, err := tableconvertor.New(nil)
if err != nil { if err != nil {
glog.V(2).Infof("The CRD for %v has an invalid printer specification, falling back to default printing: %v", kind, err) glog.V(2).Infof("The CRD for %v has an invalid printer specification, falling back to default printing: %v", kind, err)
} }

View File

@ -71,8 +71,10 @@ go_test(
"//vendor/k8s.io/apiextensions-apiserver/pkg/registry/customresource/tableconvertor:go_default_library", "//vendor/k8s.io/apiextensions-apiserver/pkg/registry/customresource/tableconvertor:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/api/equality:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/equality:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/meta/internalversion:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1beta1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/diff:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/diff:go_default_library",

View File

@ -21,12 +21,15 @@ import (
"reflect" "reflect"
"strings" "strings"
"testing" "testing"
"time"
autoscalingv1 "k8s.io/api/autoscaling/v1" autoscalingv1 "k8s.io/api/autoscaling/v1"
apiequality "k8s.io/apimachinery/pkg/api/equality" apiequality "k8s.io/apimachinery/pkg/api/equality"
"k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/api/errors"
metainternal "k8s.io/apimachinery/pkg/apis/meta/internalversion"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
metav1beta1 "k8s.io/apimachinery/pkg/apis/meta/v1beta1"
"k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/util/diff" "k8s.io/apimachinery/pkg/util/diff"
@ -72,8 +75,19 @@ func newStorage(t *testing.T) (customresource.CustomResourceStorage, *etcdtestin
status := &apiextensions.CustomResourceSubresourceStatus{} status := &apiextensions.CustomResourceSubresourceStatus{}
// TODO: identify how to pass printer specification from the CRD headers := []apiextensions.CustomResourceColumnDefinition{
table, _ := tableconvertor.New(nil) {Name: "Age", Type: "date", JSONPath: ".metadata.creationTimestamp"},
{Name: "Replicas", Type: "integer", JSONPath: ".spec.replicas"},
{Name: "Missing", Type: "string", JSONPath: ".spec.missing"},
{Name: "Invalid", Type: "integer", JSONPath: ".spec.string"},
{Name: "String", Type: "string", JSONPath: ".spec.string"},
{Name: "StringFloat64", Type: "string", JSONPath: ".spec.float64"},
{Name: "StringInt64", Type: "string", JSONPath: ".spec.replicas"},
{Name: "StringBool", Type: "string", JSONPath: ".spec.bool"},
{Name: "Float64", Type: "number", JSONPath: ".spec.float64"},
{Name: "Bool", Type: "boolean", JSONPath: ".spec.bool"},
}
table, _ := tableconvertor.New(headers)
storage := customresource.NewStorage( storage := customresource.NewStorage(
schema.GroupResource{Group: "mygroup.example.com", Resource: "noxus"}, schema.GroupResource{Group: "mygroup.example.com", Resource: "noxus"},
@ -112,11 +126,18 @@ func validNewCustomResource() *unstructured.Unstructured {
"apiVersion": "mygroup.example.com/v1beta1", "apiVersion": "mygroup.example.com/v1beta1",
"kind": "Noxu", "kind": "Noxu",
"metadata": map[string]interface{}{ "metadata": map[string]interface{}{
"namespace": "default", "namespace": "default",
"name": "foo", "name": "foo",
"creationTimestamp": time.Now().Add(-time.Hour*12 - 30*time.Minute).UTC().Format(time.RFC3339),
}, },
"spec": map[string]interface{}{ "spec": map[string]interface{}{
"replicas": int64(7), "replicas": int64(7),
"string": "string",
"float64": float64(3.1415926),
"bool": true,
"stringList": []interface{}{"foo", "bar"},
"mixedList": []interface{}{"foo", int64(42)},
"nonPrimitiveList": []interface{}{"foo", []interface{}{int64(1), int64(2)}},
}, },
}, },
} }
@ -225,6 +246,77 @@ func TestCategories(t *testing.T) {
} }
} }
func TestColumns(t *testing.T) {
storage, server := newStorage(t)
defer server.Terminate(t)
defer storage.CustomResource.Store.DestroyFunc()
ctx := genericapirequest.WithNamespace(genericapirequest.NewContext(), metav1.NamespaceDefault)
key := "/noxus/" + metav1.NamespaceDefault + "/foo"
validCustomResource := validNewCustomResource()
if err := storage.CustomResource.Storage.Create(ctx, key, validCustomResource, nil, 0); err != nil {
t.Fatalf("unexpected error: %v", err)
}
gottenList, err := storage.CustomResource.List(ctx, &metainternal.ListOptions{})
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
tbl, err := storage.CustomResource.ConvertToTable(ctx, gottenList, &metav1beta1.TableOptions{})
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
expectedColumns := []struct {
Name, Type string
}{
{"Name", "string"},
{"Age", "date"},
{"Replicas", "integer"},
{"Missing", "string"},
{"Invalid", "integer"},
{"String", "string"},
{"StringFloat64", "string"},
{"StringInt64", "string"},
{"StringBool", "string"},
{"Float64", "number"},
{"Bool", "boolean"},
}
if len(tbl.ColumnDefinitions) != len(expectedColumns) {
t.Fatalf("got %d columns, expected %d. Got: %+v", len(tbl.ColumnDefinitions), len(expectedColumns), tbl.ColumnDefinitions)
}
for i, d := range tbl.ColumnDefinitions {
if d.Name != expectedColumns[i].Name {
t.Errorf("got column %d name %q, expected %q", i, d.Name, expectedColumns[i].Name)
}
if d.Type != expectedColumns[i].Type {
t.Errorf("got column %d type %q, expected %q", i, d.Type, expectedColumns[i].Type)
}
}
expectedRows := [][]interface{}{
{
"foo",
"12h",
int64(7),
nil,
nil,
"string",
"3.1415926",
"7",
"true",
float64(3.1415926),
true,
},
}
for i, r := range tbl.Rows {
if !reflect.DeepEqual(r.Cells, expectedRows[i]) {
t.Errorf("got row %d with cells %#v, expected %#v", i, r.Cells, expectedRows[i])
}
}
}
func TestStatusUpdate(t *testing.T) { func TestStatusUpdate(t *testing.T) {
storage, server := newStorage(t) storage, server := newStorage(t)
defer server.Terminate(t) defer server.Terminate(t)

View File

@ -1,4 +1,4 @@
load("@io_bazel_rules_go//go:def.bzl", "go_library") load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test")
go_library( go_library(
name = "go_default_library", name = "go_default_library",
@ -6,7 +6,7 @@ go_library(
importpath = "k8s.io/apiextensions-apiserver/pkg/registry/customresource/tableconvertor", importpath = "k8s.io/apiextensions-apiserver/pkg/registry/customresource/tableconvertor",
visibility = ["//visibility:public"], visibility = ["//visibility:public"],
deps = [ deps = [
"//vendor/github.com/go-openapi/spec:go_default_library", "//vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/api/meta:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/meta:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/api/meta/table:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/meta/table:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
@ -30,3 +30,9 @@ filegroup(
tags = ["automanaged"], tags = ["automanaged"],
visibility = ["//visibility:public"], visibility = ["//visibility:public"],
) )
go_test(
name = "go_default_test",
srcs = ["tableconvertor_test.go"],
embed = [":go_default_library"],
)

View File

@ -19,11 +19,11 @@ package tableconvertor
import ( import (
"bytes" "bytes"
"context" "context"
"encoding/json"
"fmt" "fmt"
"strings" "reflect"
"github.com/go-openapi/spec"
"k8s.io/apiextensions-apiserver/pkg/apis/apiextensions"
"k8s.io/apimachinery/pkg/api/meta" "k8s.io/apimachinery/pkg/api/meta"
metatable "k8s.io/apimachinery/pkg/api/meta/table" metatable "k8s.io/apimachinery/pkg/api/meta/table"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@ -33,56 +33,46 @@ import (
"k8s.io/client-go/util/jsonpath" "k8s.io/client-go/util/jsonpath"
) )
const printColumnsKey = "x-kubernetes-print-columns"
var swaggerMetadataDescriptions = metav1.ObjectMeta{}.SwaggerDoc() var swaggerMetadataDescriptions = metav1.ObjectMeta{}.SwaggerDoc()
// New creates a new table convertor for the provided OpenAPI schema. If the printer definition cannot be parsed, // New creates a new table convertor for the provided CRD column definition. If the printer definition cannot be parsed,
// error will be returned along with a default table convertor. // error will be returned along with a default table convertor.
func New(extensions spec.Extensions) (rest.TableConvertor, error) { func New(crdColumns []apiextensions.CustomResourceColumnDefinition) (rest.TableConvertor, error) {
headers := []metav1beta1.TableColumnDefinition{ headers := []metav1beta1.TableColumnDefinition{
{Name: "Name", Type: "string", Format: "name", Description: swaggerMetadataDescriptions["name"]}, {Name: "Name", Type: "string", Format: "name", Description: swaggerMetadataDescriptions["name"]},
{Name: "Age", Type: "date", Description: swaggerMetadataDescriptions["creationTimestamp"]},
} }
c := &convertor{ c := &convertor{
headers: headers, headers: headers,
} }
format, ok := extensions.GetString(printColumnsKey)
if !ok { for _, col := range crdColumns {
return c, nil path := jsonpath.New(col.Name)
} if err := path.Parse(fmt.Sprintf("{%s}", col.JSONPath)); err != nil {
// "x-kubernetes-print-columns": "custom-columns=NAME:.metadata.name,RSRC:.metadata.resourceVersion" return c, fmt.Errorf("unrecognized column definition %q", col.JSONPath)
parts := strings.SplitN(format, "=", 2)
if len(parts) != 2 || parts[0] != "custom-columns" {
return c, fmt.Errorf("unrecognized column definition in 'x-kubernetes-print-columns', only support 'custom-columns=NAME=JSONPATH[,NAME=JSONPATH]'")
}
columnSpecs := strings.Split(parts[1], ",")
var columns []*jsonpath.JSONPath
for _, spec := range columnSpecs {
parts := strings.SplitN(spec, ":", 2)
if len(parts) != 2 || len(parts[0]) == 0 || len(parts[1]) == 0 {
return c, fmt.Errorf("unrecognized column definition in 'x-kubernetes-print-columns', must specify NAME=JSONPATH: %s", spec)
}
path := jsonpath.New(parts[0])
if err := path.Parse(parts[1]); err != nil {
return c, fmt.Errorf("unrecognized column definition in 'x-kubernetes-print-columns': %v", spec)
} }
path.AllowMissingKeys(true) path.AllowMissingKeys(true)
columns = append(columns, path)
headers = append(headers, metav1beta1.TableColumnDefinition{ desc := fmt.Sprintf("Custom resource definition column (in JSONPath format): %s", col.JSONPath)
Name: parts[0], if len(col.Description) > 0 {
Type: "string", desc = col.Description
Description: fmt.Sprintf("Custom resource definition column from OpenAPI (in JSONPath format): %s", parts[1]), }
c.additionalColumns = append(c.additionalColumns, path)
c.headers = append(c.headers, metav1beta1.TableColumnDefinition{
Name: col.Name,
Type: col.Type,
Format: col.Format,
Description: desc,
Priority: col.Priority,
}) })
} }
c.columns = columns
c.headers = headers
return c, nil return c, nil
} }
type convertor struct { type convertor struct {
headers []metav1beta1.TableColumnDefinition headers []metav1beta1.TableColumnDefinition
columns []*jsonpath.JSONPath additionalColumns []*jsonpath.JSONPath
} }
func (c *convertor) ConvertToTable(ctx context.Context, obj runtime.Object, tableOptions runtime.Object) (*metav1beta1.Table, error) { func (c *convertor) ConvertToTable(ctx context.Context, obj runtime.Object, tableOptions runtime.Object) (*metav1beta1.Table, error) {
@ -103,18 +93,80 @@ func (c *convertor) ConvertToTable(ctx context.Context, obj runtime.Object, tabl
var err error var err error
buf := &bytes.Buffer{} buf := &bytes.Buffer{}
table.Rows, err = metatable.MetaToTableRow(obj, func(obj runtime.Object, m metav1.Object, name, age string) ([]interface{}, error) { table.Rows, err = metatable.MetaToTableRow(obj, func(obj runtime.Object, m metav1.Object, name, age string) ([]interface{}, error) {
cells := make([]interface{}, 2, 2+len(c.columns)) cells := make([]interface{}, 1, 1+len(c.additionalColumns))
cells[0] = name cells[0] = name
cells[1] = age customHeaders := c.headers[1:]
for _, column := range c.columns { for i, column := range c.additionalColumns {
if err := column.Execute(buf, obj); err != nil { results, err := column.FindResults(obj.(runtime.Unstructured).UnstructuredContent())
if err != nil || len(results) == 0 || len(results[0]) == 0 {
cells = append(cells, nil) cells = append(cells, nil)
continue continue
} }
cells = append(cells, buf.String())
buf.Reset() // as we only support simple JSON path, we can assume to have only one result (or none, filtered out above)
value := results[0][0].Interface()
if customHeaders[i].Type == "string" {
if err := column.PrintResults(buf, []reflect.Value{reflect.ValueOf(value)}); err == nil {
cells = append(cells, buf.String())
buf.Reset()
} else {
cells = append(cells, nil)
}
} else {
cells = append(cells, cellForJSONValue(customHeaders[i].Type, value))
}
} }
return cells, nil return cells, nil
}) })
return table, err return table, err
} }
func cellForJSONValue(headerType string, value interface{}) interface{} {
if value == nil {
return nil
}
switch headerType {
case "integer":
switch typed := value.(type) {
case int64:
return typed
case float64:
return int64(typed)
case json.Number:
if i64, err := typed.Int64(); err == nil {
return i64
}
}
case "number":
switch typed := value.(type) {
case int64:
return float64(typed)
case float64:
return typed
case json.Number:
if f, err := typed.Float64(); err == nil {
return f
}
}
case "boolean":
if b, ok := value.(bool); ok {
return b
}
case "string":
if s, ok := value.(string); ok {
return s
}
case "date":
if typed, ok := value.(string); ok {
var timestamp metav1.Time
err := timestamp.UnmarshalQueryParameter(typed)
if err != nil {
return "<invalid>"
}
return metatable.ConvertToHumanReadableDateType(timestamp)
}
}
return nil
}

View File

@ -0,0 +1,68 @@
/*
Copyright 2018 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package tableconvertor
import (
"fmt"
"reflect"
"testing"
"time"
)
func Test_cellForJSONValue(t *testing.T) {
tests := []struct {
headerType string
value interface{}
want interface{}
}{
{"integer", int64(42), int64(42)},
{"integer", float64(3.14), int64(3)},
{"integer", true, nil},
{"integer", "foo", nil},
{"number", int64(42), float64(42)},
{"number", float64(3.14), float64(3.14)},
{"number", true, nil},
{"number", "foo", nil},
{"boolean", int64(42), nil},
{"boolean", float64(3.14), nil},
{"boolean", true, true},
{"boolean", "foo", nil},
{"string", int64(42), nil},
{"string", float64(3.14), nil},
{"string", true, nil},
{"string", "foo", "foo"},
{"date", int64(42), nil},
{"date", float64(3.14), nil},
{"date", true, nil},
{"date", time.Now().Add(-time.Hour*12 - 30*time.Minute).UTC().Format(time.RFC3339), "12h"},
{"date", time.Now().Add(+time.Hour*12 + 30*time.Minute).UTC().Format(time.RFC3339), "<invalid>"},
{"date", "", "<unknown>"},
{"unknown", "foo", nil},
}
for _, tt := range tests {
t.Run(fmt.Sprintf("%#v of type %s", tt.value, tt.headerType), func(t *testing.T) {
if got := cellForJSONValue(tt.headerType, tt.value); !reflect.DeepEqual(got, tt.want) {
t.Errorf("cellForJSONValue() = %#v, want %#v", got, tt.want)
}
})
}
}

View File

@ -13,6 +13,7 @@ go_test(
"finalization_test.go", "finalization_test.go",
"registration_test.go", "registration_test.go",
"subresources_test.go", "subresources_test.go",
"table_test.go",
"validation_test.go", "validation_test.go",
"versioning_test.go", "versioning_test.go",
"yaml_test.go", "yaml_test.go",
@ -32,12 +33,15 @@ go_test(
"//vendor/k8s.io/apimachinery/pkg/api/meta:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/meta:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1beta1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime/serializer:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/types:go_default_library", "//vendor/k8s.io/apimachinery/pkg/types:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/wait:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/wait:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/watch:go_default_library", "//vendor/k8s.io/apimachinery/pkg/watch:go_default_library",
"//vendor/k8s.io/client-go/dynamic:go_default_library", "//vendor/k8s.io/client-go/dynamic:go_default_library",
"//vendor/k8s.io/client-go/rest:go_default_library",
], ],
) )

View File

@ -0,0 +1,185 @@
/*
Copyright 2017 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package integration
import (
"fmt"
"testing"
"k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
metav1beta1 "k8s.io/apimachinery/pkg/apis/meta/v1beta1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/runtime/serializer"
"k8s.io/client-go/dynamic"
"k8s.io/client-go/rest"
apiextensionsv1beta1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1"
"k8s.io/apiextensions-apiserver/test/integration/testserver"
)
func newTableCRD() *apiextensionsv1beta1.CustomResourceDefinition {
return &apiextensionsv1beta1.CustomResourceDefinition{
ObjectMeta: metav1.ObjectMeta{Name: "tables.mygroup.example.com"},
Spec: apiextensionsv1beta1.CustomResourceDefinitionSpec{
Group: "mygroup.example.com",
Version: "v1beta1",
Names: apiextensionsv1beta1.CustomResourceDefinitionNames{
Plural: "tables",
Singular: "table",
Kind: "Table",
ListKind: "TablemList",
},
Scope: apiextensionsv1beta1.ClusterScoped,
AdditionalPrinterColumns: []apiextensionsv1beta1.CustomResourceColumnDefinition{
{Name: "Age", Type: "date", JSONPath: ".metadata.creationTimestamp"},
{Name: "Alpha", Type: "string", JSONPath: ".spec.alpha"},
{Name: "Beta", Type: "integer", Description: "the beta field", Format: "int64", Priority: 42, JSONPath: ".spec.beta"},
{Name: "Gamma", Type: "integer", Description: "a column with wrongly typed values", JSONPath: ".spec.gamma"},
},
},
}
}
func newTableInstance(name string) *unstructured.Unstructured {
return &unstructured.Unstructured{
Object: map[string]interface{}{
"apiVersion": "mygroup.example.com/v1beta1",
"kind": "Table",
"metadata": map[string]interface{}{
"name": name,
},
"spec": map[string]interface{}{
"alpha": "foo_123",
"beta": 10,
"gamma": "bar",
"delta": "hello",
},
},
}
}
func TestTableGet(t *testing.T) {
stopCh, config, err := testserver.StartDefaultServer()
if err != nil {
t.Fatal(err)
}
defer close(stopCh)
apiExtensionClient, err := clientset.NewForConfig(config)
if err != nil {
t.Fatal(err)
}
dynamicClient, err := dynamic.NewForConfig(config)
if err != nil {
t.Fatal(err)
}
crd := newTableCRD()
crd, err = testserver.CreateNewCustomResourceDefinition(crd, apiExtensionClient, dynamicClient)
if err != nil {
t.Fatal(err)
}
crd, err = apiExtensionClient.ApiextensionsV1beta1().CustomResourceDefinitions().Get(crd.Name, metav1.GetOptions{})
if err != nil {
t.Fatal(err)
}
t.Logf("table crd created: %#v", crd)
crClient := newNamespacedCustomResourceClient("", dynamicClient, crd)
foo, err := crClient.Create(newTableInstance("foo"))
if err != nil {
t.Fatalf("unable to create noxu instance: %v", err)
}
t.Logf("foo created: %#v", foo.UnstructuredContent())
gv := schema.GroupVersion{Group: crd.Spec.Group, Version: crd.Spec.Version}
gvk := gv.WithKind(crd.Spec.Names.Kind)
scheme := runtime.NewScheme()
codecs := serializer.NewCodecFactory(scheme)
parameterCodec := runtime.NewParameterCodec(scheme)
metav1.AddToGroupVersion(scheme, gv)
scheme.AddKnownTypes(gv, &metav1beta1.Table{}, &metav1beta1.TableOptions{})
scheme.AddKnownTypes(metav1beta1.SchemeGroupVersion, &metav1beta1.Table{}, &metav1beta1.TableOptions{})
crConfig := *config
crConfig.GroupVersion = &gv
crConfig.APIPath = "/apis"
crConfig.NegotiatedSerializer = serializer.DirectCodecFactory{CodecFactory: codecs}
crRestClient, err := rest.RESTClientFor(&crConfig)
if err != nil {
t.Fatal(err)
}
ret, err := crRestClient.Get().
Resource(crd.Spec.Names.Plural).
SetHeader("Accept", fmt.Sprintf("application/json;as=Table;v=%s;g=%s, application/json", metav1beta1.SchemeGroupVersion.Version, metav1beta1.GroupName)).
VersionedParams(&metav1beta1.TableOptions{}, parameterCodec).
Do().
Get()
if err != nil {
t.Fatalf("failed to list %v resources: %v", gvk, err)
}
tbl, ok := ret.(*metav1beta1.Table)
if !ok {
t.Fatalf("expected metav1beta1.Table, got %T", ret)
}
t.Logf("%v table list: %#v", gvk, tbl)
if got, expected := len(tbl.ColumnDefinitions), 5; got != expected {
t.Errorf("expected %d headers, got %d", expected, got)
} else {
alpha := metav1beta1.TableColumnDefinition{Name: "Alpha", Type: "string", Format: "", Description: "Custom resource definition column (in JSONPath format): .spec.alpha", Priority: 0}
if got, expected := tbl.ColumnDefinitions[2], alpha; got != expected {
t.Errorf("expected column definition %#v, got %#v", expected, got)
}
beta := metav1beta1.TableColumnDefinition{Name: "Beta", Type: "integer", Format: "int64", Description: "the beta field", Priority: 42}
if got, expected := tbl.ColumnDefinitions[3], beta; got != expected {
t.Errorf("expected column definition %#v, got %#v", expected, got)
}
gamma := metav1beta1.TableColumnDefinition{Name: "Gamma", Type: "integer", Description: "a column with wrongly typed values"}
if got, expected := tbl.ColumnDefinitions[4], gamma; got != expected {
t.Errorf("expected column definition %#v, got %#v", expected, got)
}
}
if got, expected := len(tbl.Rows), 1; got != expected {
t.Errorf("expected %d rows, got %d", expected, got)
} else if got, expected := len(tbl.Rows[0].Cells), 5; got != expected {
t.Errorf("expected %d cells, got %d", expected, got)
} else {
if got, expected := tbl.Rows[0].Cells[0], "foo"; got != expected {
t.Errorf("expected cell[0] to equal %q, got %q", expected, got)
}
if got, expected := tbl.Rows[0].Cells[2], "foo_123"; got != expected {
t.Errorf("expected cell[2] to equal %q, got %q", expected, got)
}
if got, expected := tbl.Rows[0].Cells[3], int64(10); got != expected {
t.Errorf("expected cell[3] to equal %#v, got %#v", expected, got)
}
if got, expected := tbl.Rows[0].Cells[4], interface{}(nil); got != expected {
t.Errorf("expected cell[3] to equal %#v although the type does not match the column, got %#v", expected, got)
}
}
}

View File

@ -53,7 +53,7 @@ func MetaToTableRow(obj runtime.Object, rowFn func(obj runtime.Object, m metav1.
row := metav1beta1.TableRow{ row := metav1beta1.TableRow{
Object: runtime.RawExtension{Object: obj}, Object: runtime.RawExtension{Object: obj},
} }
row.Cells, err = rowFn(obj, m, m.GetName(), translateTimestamp(m.GetCreationTimestamp())) row.Cells, err = rowFn(obj, m, m.GetName(), ConvertToHumanReadableDateType(m.GetCreationTimestamp()))
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -61,9 +61,9 @@ func MetaToTableRow(obj runtime.Object, rowFn func(obj runtime.Object, m metav1.
return rows, nil return rows, nil
} }
// translateTimestamp returns the elapsed time since timestamp in // ConvertToHumanReadableDateType returns the elapsed time since timestamp in
// human-readable approximation. // human-readable approximation.
func translateTimestamp(timestamp metav1.Time) string { func ConvertToHumanReadableDateType(timestamp metav1.Time) string {
if timestamp.IsZero() { if timestamp.IsZero() {
return "<unknown>" return "<unknown>"
} }

View File

@ -1320,7 +1320,7 @@ func (t *Tester) testListTableConversion(obj runtime.Object, assignFn AssignFunc
t.Errorf("column %d has no name", j) t.Errorf("column %d has no name", j)
} }
switch column.Type { switch column.Type {
case "string", "date", "integer": case "string", "date", "integer", "number", "boolean":
default: default:
t.Errorf("column %d has unexpected type: %q", j, column.Type) t.Errorf("column %d has unexpected type: %q", j, column.Type)
} }
@ -1342,13 +1342,14 @@ func (t *Tester) testListTableConversion(obj runtime.Object, assignFn AssignFunc
} }
for i, row := range table.Rows { for i, row := range table.Rows {
if len(row.Cells) != len(table.ColumnDefinitions) { if len(row.Cells) != len(table.ColumnDefinitions) {
t.Errorf("row %d did not have the correct number of cells: %d in %v", i, len(table.ColumnDefinitions), row.Cells) t.Errorf("row %d did not have the correct number of cells: %d in %v, expected %d", i, len(row.Cells), row.Cells, len(table.ColumnDefinitions))
} }
for j, cell := range row.Cells { for j, cell := range row.Cells {
// do not add to this test without discussion - may break clients // do not add to this test without discussion - may break clients
switch cell.(type) { switch cell.(type) {
case float64, int64, int32, int, string, bool: case float64, int64, int32, int, string, bool:
case []interface{}: case []interface{}:
case nil:
default: default:
t.Errorf("row %d, cell %d has an unrecognized type, only JSON serialization safe types are allowed: %T ", i, j, cell) t.Errorf("row %d, cell %d has an unrecognized type, only JSON serialization safe types are allowed: %T ", i, j, cell)
} }