Add generated file
This PR adds generated files under pkg/client and vendor folder.
This commit is contained in:
262
vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/deepcopy.go
generated
vendored
Normal file
262
vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/deepcopy.go
generated
vendored
Normal file
@@ -0,0 +1,262 @@
|
||||
/*
|
||||
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 apiextensions
|
||||
|
||||
import "k8s.io/apimachinery/pkg/runtime"
|
||||
|
||||
// TODO: Update this after a tag is created for interface fields in DeepCopy
|
||||
func (in *JSONSchemaProps) DeepCopy() *JSONSchemaProps {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(JSONSchemaProps)
|
||||
|
||||
*out = *in
|
||||
|
||||
if in.Default != nil {
|
||||
defaultJSON := JSON(runtime.DeepCopyJSONValue(*(in.Default)))
|
||||
out.Default = &(defaultJSON)
|
||||
} else {
|
||||
out.Default = nil
|
||||
}
|
||||
|
||||
if in.Example != nil {
|
||||
exampleJSON := JSON(runtime.DeepCopyJSONValue(*(in.Example)))
|
||||
out.Example = &(exampleJSON)
|
||||
} else {
|
||||
out.Example = nil
|
||||
}
|
||||
|
||||
if in.Ref != nil {
|
||||
in, out := &in.Ref, &out.Ref
|
||||
if *in == nil {
|
||||
*out = nil
|
||||
} else {
|
||||
*out = new(string)
|
||||
**out = **in
|
||||
}
|
||||
}
|
||||
|
||||
if in.Maximum != nil {
|
||||
in, out := &in.Maximum, &out.Maximum
|
||||
if *in == nil {
|
||||
*out = nil
|
||||
} else {
|
||||
*out = new(float64)
|
||||
**out = **in
|
||||
}
|
||||
}
|
||||
|
||||
if in.Minimum != nil {
|
||||
in, out := &in.Minimum, &out.Minimum
|
||||
if *in == nil {
|
||||
*out = nil
|
||||
} else {
|
||||
*out = new(float64)
|
||||
**out = **in
|
||||
}
|
||||
}
|
||||
|
||||
if in.MaxLength != nil {
|
||||
in, out := &in.MaxLength, &out.MaxLength
|
||||
if *in == nil {
|
||||
*out = nil
|
||||
} else {
|
||||
*out = new(int64)
|
||||
**out = **in
|
||||
}
|
||||
}
|
||||
|
||||
if in.MinLength != nil {
|
||||
in, out := &in.MinLength, &out.MinLength
|
||||
if *in == nil {
|
||||
*out = nil
|
||||
} else {
|
||||
*out = new(int64)
|
||||
**out = **in
|
||||
}
|
||||
}
|
||||
if in.MaxItems != nil {
|
||||
in, out := &in.MaxItems, &out.MaxItems
|
||||
if *in == nil {
|
||||
*out = nil
|
||||
} else {
|
||||
*out = new(int64)
|
||||
**out = **in
|
||||
}
|
||||
}
|
||||
|
||||
if in.MinItems != nil {
|
||||
in, out := &in.MinItems, &out.MinItems
|
||||
if *in == nil {
|
||||
*out = nil
|
||||
} else {
|
||||
*out = new(int64)
|
||||
**out = **in
|
||||
}
|
||||
}
|
||||
|
||||
if in.MultipleOf != nil {
|
||||
in, out := &in.MultipleOf, &out.MultipleOf
|
||||
if *in == nil {
|
||||
*out = nil
|
||||
} else {
|
||||
*out = new(float64)
|
||||
**out = **in
|
||||
}
|
||||
}
|
||||
|
||||
if in.Enum != nil {
|
||||
out.Enum = make([]JSON, len(in.Enum))
|
||||
for i := range in.Enum {
|
||||
out.Enum[i] = runtime.DeepCopyJSONValue(in.Enum[i])
|
||||
}
|
||||
}
|
||||
|
||||
if in.MaxProperties != nil {
|
||||
in, out := &in.MaxProperties, &out.MaxProperties
|
||||
if *in == nil {
|
||||
*out = nil
|
||||
} else {
|
||||
*out = new(int64)
|
||||
**out = **in
|
||||
}
|
||||
}
|
||||
|
||||
if in.MinProperties != nil {
|
||||
in, out := &in.MinProperties, &out.MinProperties
|
||||
if *in == nil {
|
||||
*out = nil
|
||||
} else {
|
||||
*out = new(int64)
|
||||
**out = **in
|
||||
}
|
||||
}
|
||||
|
||||
if in.Required != nil {
|
||||
in, out := &in.Required, &out.Required
|
||||
*out = make([]string, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
|
||||
if in.Items != nil {
|
||||
in, out := &in.Items, &out.Items
|
||||
if *in == nil {
|
||||
*out = nil
|
||||
} else {
|
||||
*out = new(JSONSchemaPropsOrArray)
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
}
|
||||
|
||||
if in.AllOf != nil {
|
||||
in, out := &in.AllOf, &out.AllOf
|
||||
*out = make([]JSONSchemaProps, len(*in))
|
||||
for i := range *in {
|
||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||
}
|
||||
}
|
||||
|
||||
if in.OneOf != nil {
|
||||
in, out := &in.OneOf, &out.OneOf
|
||||
*out = make([]JSONSchemaProps, len(*in))
|
||||
for i := range *in {
|
||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||
}
|
||||
}
|
||||
if in.AnyOf != nil {
|
||||
in, out := &in.AnyOf, &out.AnyOf
|
||||
*out = make([]JSONSchemaProps, len(*in))
|
||||
for i := range *in {
|
||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||
}
|
||||
}
|
||||
|
||||
if in.Not != nil {
|
||||
in, out := &in.Not, &out.Not
|
||||
if *in == nil {
|
||||
*out = nil
|
||||
} else {
|
||||
*out = new(JSONSchemaProps)
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
}
|
||||
|
||||
if in.Properties != nil {
|
||||
in, out := &in.Properties, &out.Properties
|
||||
*out = make(map[string]JSONSchemaProps, len(*in))
|
||||
for key, val := range *in {
|
||||
(*out)[key] = *val.DeepCopy()
|
||||
}
|
||||
}
|
||||
|
||||
if in.AdditionalProperties != nil {
|
||||
in, out := &in.AdditionalProperties, &out.AdditionalProperties
|
||||
if *in == nil {
|
||||
*out = nil
|
||||
} else {
|
||||
*out = new(JSONSchemaPropsOrBool)
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
}
|
||||
|
||||
if in.PatternProperties != nil {
|
||||
in, out := &in.PatternProperties, &out.PatternProperties
|
||||
*out = make(map[string]JSONSchemaProps, len(*in))
|
||||
for key, val := range *in {
|
||||
(*out)[key] = *val.DeepCopy()
|
||||
}
|
||||
}
|
||||
|
||||
if in.Dependencies != nil {
|
||||
in, out := &in.Dependencies, &out.Dependencies
|
||||
*out = make(JSONSchemaDependencies, len(*in))
|
||||
for key, val := range *in {
|
||||
(*out)[key] = *val.DeepCopy()
|
||||
}
|
||||
}
|
||||
|
||||
if in.AdditionalItems != nil {
|
||||
in, out := &in.AdditionalItems, &out.AdditionalItems
|
||||
if *in == nil {
|
||||
*out = nil
|
||||
} else {
|
||||
*out = new(JSONSchemaPropsOrBool)
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
}
|
||||
|
||||
if in.Definitions != nil {
|
||||
in, out := &in.Definitions, &out.Definitions
|
||||
*out = make(JSONSchemaDefinitions, len(*in))
|
||||
for key, val := range *in {
|
||||
(*out)[key] = *val.DeepCopy()
|
||||
}
|
||||
}
|
||||
|
||||
if in.ExternalDocs != nil {
|
||||
in, out := &in.ExternalDocs, &out.ExternalDocs
|
||||
if *in == nil {
|
||||
*out = nil
|
||||
} else {
|
||||
*out = new(ExternalDocumentation)
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
}
|
||||
|
||||
return out
|
||||
}
|
||||
21
vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/doc.go
generated
vendored
Normal file
21
vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/doc.go
generated
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
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.
|
||||
*/
|
||||
|
||||
// +k8s:deepcopy-gen=package
|
||||
|
||||
// Package apiextensions is the internal version of the API.
|
||||
// +groupName=apiextensions.k8s.io
|
||||
package apiextensions // import "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions"
|
||||
142
vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/fuzzer/fuzzer.go
generated
vendored
Normal file
142
vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/fuzzer/fuzzer.go
generated
vendored
Normal file
@@ -0,0 +1,142 @@
|
||||
/*
|
||||
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 fuzzer
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"strings"
|
||||
|
||||
"github.com/google/gofuzz"
|
||||
|
||||
"k8s.io/apiextensions-apiserver/pkg/apis/apiextensions"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
runtimeserializer "k8s.io/apimachinery/pkg/runtime/serializer"
|
||||
)
|
||||
|
||||
var swaggerMetadataDescriptions = metav1.ObjectMeta{}.SwaggerDoc()
|
||||
|
||||
// Funcs returns the fuzzer functions for the apiextensions apis.
|
||||
func Funcs(codecs runtimeserializer.CodecFactory) []interface{} {
|
||||
return []interface{}{
|
||||
func(obj *apiextensions.CustomResourceDefinitionSpec, c fuzz.Continue) {
|
||||
c.FuzzNoCustom(obj)
|
||||
|
||||
// match our defaulter
|
||||
if len(obj.Scope) == 0 {
|
||||
obj.Scope = apiextensions.NamespaceScoped
|
||||
}
|
||||
if len(obj.Names.Singular) == 0 {
|
||||
obj.Names.Singular = strings.ToLower(obj.Names.Kind)
|
||||
}
|
||||
if len(obj.Names.ListKind) == 0 && len(obj.Names.Kind) > 0 {
|
||||
obj.Names.ListKind = obj.Names.Kind + "List"
|
||||
}
|
||||
if len(obj.Versions) == 0 && len(obj.Version) != 0 {
|
||||
obj.Versions = []apiextensions.CustomResourceDefinitionVersion{
|
||||
{
|
||||
Name: obj.Version,
|
||||
Served: true,
|
||||
Storage: true,
|
||||
},
|
||||
}
|
||||
} else if len(obj.Versions) != 0 {
|
||||
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) {
|
||||
c.FuzzNoCustom(obj)
|
||||
|
||||
if len(obj.Status.StoredVersions) == 0 {
|
||||
for _, v := range obj.Spec.Versions {
|
||||
if v.Storage && !apiextensions.IsStoredVersion(obj, v.Name) {
|
||||
obj.Status.StoredVersions = append(obj.Status.StoredVersions, v.Name)
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
func(obj *apiextensions.JSONSchemaProps, c fuzz.Continue) {
|
||||
// we cannot use c.FuzzNoCustom because of the interface{} fields. So let's loop with reflection.
|
||||
vobj := reflect.ValueOf(obj).Elem()
|
||||
tobj := reflect.TypeOf(obj).Elem()
|
||||
for i := 0; i < tobj.NumField(); i++ {
|
||||
field := tobj.Field(i)
|
||||
switch field.Name {
|
||||
case "Default", "Enum", "Example", "Ref":
|
||||
continue
|
||||
default:
|
||||
isValue := true
|
||||
switch field.Type.Kind() {
|
||||
case reflect.Interface, reflect.Map, reflect.Slice, reflect.Ptr:
|
||||
isValue = false
|
||||
}
|
||||
if isValue || c.Intn(10) == 0 {
|
||||
c.Fuzz(vobj.Field(i).Addr().Interface())
|
||||
}
|
||||
}
|
||||
}
|
||||
if c.RandBool() {
|
||||
validJSON := apiextensions.JSON(`{"some": {"json": "test"}, "string": 42}`)
|
||||
obj.Default = &validJSON
|
||||
}
|
||||
if c.RandBool() {
|
||||
obj.Enum = []apiextensions.JSON{c.Float64(), c.RandString(), c.RandBool()}
|
||||
}
|
||||
if c.RandBool() {
|
||||
validJSON := apiextensions.JSON(`"foobarbaz"`)
|
||||
obj.Example = &validJSON
|
||||
}
|
||||
if c.RandBool() {
|
||||
validRef := "validRef"
|
||||
obj.Ref = &validRef
|
||||
}
|
||||
},
|
||||
func(obj *apiextensions.JSONSchemaPropsOrBool, c fuzz.Continue) {
|
||||
if c.RandBool() {
|
||||
obj.Allows = true
|
||||
obj.Schema = &apiextensions.JSONSchemaProps{}
|
||||
c.Fuzz(obj.Schema)
|
||||
} else {
|
||||
obj.Allows = c.RandBool()
|
||||
}
|
||||
},
|
||||
func(obj *apiextensions.JSONSchemaPropsOrArray, c fuzz.Continue) {
|
||||
// disallow both Schema and JSONSchemas to be nil.
|
||||
if c.RandBool() {
|
||||
obj.Schema = &apiextensions.JSONSchemaProps{}
|
||||
c.Fuzz(obj.Schema)
|
||||
} else {
|
||||
obj.JSONSchemas = make([]apiextensions.JSONSchemaProps, c.Intn(3)+1)
|
||||
for i := range obj.JSONSchemas {
|
||||
c.Fuzz(&obj.JSONSchemas[i])
|
||||
}
|
||||
}
|
||||
},
|
||||
func(obj *apiextensions.JSONSchemaPropsOrStringArray, c fuzz.Continue) {
|
||||
if c.RandBool() {
|
||||
obj.Schema = &apiextensions.JSONSchemaProps{}
|
||||
c.Fuzz(obj.Schema)
|
||||
} else {
|
||||
c.Fuzz(&obj.Property)
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
149
vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/helpers.go
generated
vendored
Normal file
149
vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/helpers.go
generated
vendored
Normal file
@@ -0,0 +1,149 @@
|
||||
/*
|
||||
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 apiextensions
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
)
|
||||
|
||||
// SetCRDCondition sets the status condition. It either overwrites the existing one or
|
||||
// creates a new one
|
||||
func SetCRDCondition(crd *CustomResourceDefinition, newCondition CustomResourceDefinitionCondition) {
|
||||
existingCondition := FindCRDCondition(crd, newCondition.Type)
|
||||
if existingCondition == nil {
|
||||
newCondition.LastTransitionTime = metav1.NewTime(time.Now())
|
||||
crd.Status.Conditions = append(crd.Status.Conditions, newCondition)
|
||||
return
|
||||
}
|
||||
|
||||
if existingCondition.Status != newCondition.Status {
|
||||
existingCondition.Status = newCondition.Status
|
||||
existingCondition.LastTransitionTime = newCondition.LastTransitionTime
|
||||
}
|
||||
|
||||
existingCondition.Reason = newCondition.Reason
|
||||
existingCondition.Message = newCondition.Message
|
||||
}
|
||||
|
||||
// RemoveCRDCondition removes the status condition.
|
||||
func RemoveCRDCondition(crd *CustomResourceDefinition, conditionType CustomResourceDefinitionConditionType) {
|
||||
newConditions := []CustomResourceDefinitionCondition{}
|
||||
for _, condition := range crd.Status.Conditions {
|
||||
if condition.Type != conditionType {
|
||||
newConditions = append(newConditions, condition)
|
||||
}
|
||||
}
|
||||
crd.Status.Conditions = newConditions
|
||||
}
|
||||
|
||||
// FindCRDCondition returns the condition you're looking for or nil
|
||||
func FindCRDCondition(crd *CustomResourceDefinition, conditionType CustomResourceDefinitionConditionType) *CustomResourceDefinitionCondition {
|
||||
for i := range crd.Status.Conditions {
|
||||
if crd.Status.Conditions[i].Type == conditionType {
|
||||
return &crd.Status.Conditions[i]
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// IsCRDConditionTrue indicates if the condition is present and strictly true
|
||||
func IsCRDConditionTrue(crd *CustomResourceDefinition, conditionType CustomResourceDefinitionConditionType) bool {
|
||||
return IsCRDConditionPresentAndEqual(crd, conditionType, ConditionTrue)
|
||||
}
|
||||
|
||||
// IsCRDConditionFalse indicates if the condition is present and false true
|
||||
func IsCRDConditionFalse(crd *CustomResourceDefinition, conditionType CustomResourceDefinitionConditionType) bool {
|
||||
return IsCRDConditionPresentAndEqual(crd, conditionType, ConditionFalse)
|
||||
}
|
||||
|
||||
// IsCRDConditionPresentAndEqual indicates if the condition is present and equal to the arg
|
||||
func IsCRDConditionPresentAndEqual(crd *CustomResourceDefinition, conditionType CustomResourceDefinitionConditionType, status ConditionStatus) bool {
|
||||
for _, condition := range crd.Status.Conditions {
|
||||
if condition.Type == conditionType {
|
||||
return condition.Status == status
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// IsCRDConditionEquivalent returns true if the lhs and rhs are equivalent except for times
|
||||
func IsCRDConditionEquivalent(lhs, rhs *CustomResourceDefinitionCondition) bool {
|
||||
if lhs == nil && rhs == nil {
|
||||
return true
|
||||
}
|
||||
if lhs == nil || rhs == nil {
|
||||
return false
|
||||
}
|
||||
|
||||
return lhs.Message == rhs.Message && lhs.Reason == rhs.Reason && lhs.Status == rhs.Status && lhs.Type == rhs.Type
|
||||
}
|
||||
|
||||
// CRDHasFinalizer returns true if the finalizer is in the list
|
||||
func CRDHasFinalizer(crd *CustomResourceDefinition, needle string) bool {
|
||||
for _, finalizer := range crd.Finalizers {
|
||||
if finalizer == needle {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
// CRDRemoveFinalizer removes the finalizer if present
|
||||
func CRDRemoveFinalizer(crd *CustomResourceDefinition, needle string) {
|
||||
newFinalizers := []string{}
|
||||
for _, finalizer := range crd.Finalizers {
|
||||
if finalizer != needle {
|
||||
newFinalizers = append(newFinalizers, finalizer)
|
||||
}
|
||||
}
|
||||
crd.Finalizers = newFinalizers
|
||||
}
|
||||
|
||||
// HasServedCRDVersion returns true if `version` is in the list of CRD's versions and the Served flag is set.
|
||||
func HasServedCRDVersion(crd *CustomResourceDefinition, version string) bool {
|
||||
for _, v := range crd.Spec.Versions {
|
||||
if v.Name == version {
|
||||
return v.Served
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// GetCRDStorageVersion returns the storage version for given CRD.
|
||||
func GetCRDStorageVersion(crd *CustomResourceDefinition) (string, error) {
|
||||
for _, v := range crd.Spec.Versions {
|
||||
if v.Storage {
|
||||
return v.Name, nil
|
||||
}
|
||||
}
|
||||
// This should not happened if crd is valid
|
||||
return "", fmt.Errorf("invalid CustomResourceDefinition, no storage version")
|
||||
}
|
||||
|
||||
func IsStoredVersion(crd *CustomResourceDefinition, version string) bool {
|
||||
for _, v := range crd.Status.StoredVersions {
|
||||
if version == v {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
421
vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/helpers_test.go
generated
vendored
Normal file
421
vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/helpers_test.go
generated
vendored
Normal file
@@ -0,0 +1,421 @@
|
||||
/*
|
||||
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 apiextensions
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
)
|
||||
|
||||
func TestCRDHasFinalizer(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
crd *CustomResourceDefinition
|
||||
finalizerToCheck string
|
||||
|
||||
expected bool
|
||||
}{
|
||||
{
|
||||
name: "missing",
|
||||
crd: &CustomResourceDefinition{
|
||||
ObjectMeta: metav1.ObjectMeta{Finalizers: []string{"not-it"}},
|
||||
},
|
||||
finalizerToCheck: "it",
|
||||
expected: false,
|
||||
},
|
||||
{
|
||||
name: "present",
|
||||
crd: &CustomResourceDefinition{
|
||||
ObjectMeta: metav1.ObjectMeta{Finalizers: []string{"not-it", "it"}},
|
||||
},
|
||||
finalizerToCheck: "it",
|
||||
expected: true,
|
||||
},
|
||||
}
|
||||
for _, tc := range tests {
|
||||
actual := CRDHasFinalizer(tc.crd, tc.finalizerToCheck)
|
||||
if tc.expected != actual {
|
||||
t.Errorf("%v expected %v, got %v", tc.name, tc.expected, actual)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestCRDRemoveFinalizer(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
crd *CustomResourceDefinition
|
||||
finalizerToCheck string
|
||||
|
||||
expected []string
|
||||
}{
|
||||
{
|
||||
name: "missing",
|
||||
crd: &CustomResourceDefinition{
|
||||
ObjectMeta: metav1.ObjectMeta{Finalizers: []string{"not-it"}},
|
||||
},
|
||||
finalizerToCheck: "it",
|
||||
expected: []string{"not-it"},
|
||||
},
|
||||
{
|
||||
name: "present",
|
||||
crd: &CustomResourceDefinition{
|
||||
ObjectMeta: metav1.ObjectMeta{Finalizers: []string{"not-it", "it"}},
|
||||
},
|
||||
finalizerToCheck: "it",
|
||||
expected: []string{"not-it"},
|
||||
},
|
||||
}
|
||||
for _, tc := range tests {
|
||||
CRDRemoveFinalizer(tc.crd, tc.finalizerToCheck)
|
||||
if !reflect.DeepEqual(tc.expected, tc.crd.Finalizers) {
|
||||
t.Errorf("%v expected %v, got %v", tc.name, tc.expected, tc.crd.Finalizers)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestSetCRDCondition(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
crdCondition []CustomResourceDefinitionCondition
|
||||
newCondition CustomResourceDefinitionCondition
|
||||
expectedcrdCondition []CustomResourceDefinitionCondition
|
||||
}{
|
||||
{
|
||||
name: "test setCRDcondition when one condition",
|
||||
crdCondition: []CustomResourceDefinitionCondition{
|
||||
{
|
||||
Type: Established,
|
||||
Status: ConditionTrue,
|
||||
Reason: "Accepted",
|
||||
Message: "the initial names have been accepted",
|
||||
LastTransitionTime: metav1.Date(2018, 1, 1, 0, 0, 0, 0, time.UTC),
|
||||
},
|
||||
},
|
||||
newCondition: CustomResourceDefinitionCondition{
|
||||
Type: Established,
|
||||
Status: ConditionFalse,
|
||||
Reason: "NotAccepted",
|
||||
Message: "Not accepted",
|
||||
LastTransitionTime: metav1.Date(2018, 1, 2, 0, 0, 0, 0, time.UTC),
|
||||
},
|
||||
expectedcrdCondition: []CustomResourceDefinitionCondition{
|
||||
{
|
||||
Type: Established,
|
||||
Status: ConditionFalse,
|
||||
Reason: "NotAccepted",
|
||||
Message: "Not accepted",
|
||||
LastTransitionTime: metav1.Date(2018, 1, 2, 0, 0, 0, 0, time.UTC),
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "test setCRDcondition when two condition",
|
||||
crdCondition: []CustomResourceDefinitionCondition{
|
||||
{
|
||||
Type: Established,
|
||||
Status: ConditionTrue,
|
||||
Reason: "Accepted",
|
||||
Message: "the initial names have been accepted",
|
||||
LastTransitionTime: metav1.Date(2018, 1, 1, 0, 0, 0, 0, time.UTC),
|
||||
},
|
||||
{
|
||||
Type: NamesAccepted,
|
||||
Status: ConditionTrue,
|
||||
Reason: "NoConflicts",
|
||||
Message: "no conflicts found",
|
||||
LastTransitionTime: metav1.Date(2018, 1, 1, 0, 0, 0, 0, time.UTC),
|
||||
},
|
||||
},
|
||||
newCondition: CustomResourceDefinitionCondition{
|
||||
Type: NamesAccepted,
|
||||
Status: ConditionFalse,
|
||||
Reason: "Conflicts",
|
||||
Message: "conflicts found",
|
||||
LastTransitionTime: metav1.Date(2018, 1, 2, 0, 0, 0, 0, time.UTC),
|
||||
},
|
||||
expectedcrdCondition: []CustomResourceDefinitionCondition{
|
||||
{
|
||||
Type: Established,
|
||||
Status: ConditionTrue,
|
||||
Reason: "Accepted",
|
||||
Message: "the initial names have been accepted",
|
||||
LastTransitionTime: metav1.Date(2018, 1, 1, 0, 0, 0, 0, time.UTC),
|
||||
},
|
||||
{
|
||||
Type: NamesAccepted,
|
||||
Status: ConditionFalse,
|
||||
Reason: "Conflicts",
|
||||
Message: "conflicts found",
|
||||
LastTransitionTime: metav1.Date(2018, 1, 2, 0, 0, 0, 0, time.UTC),
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "test setCRDcondition when condition needs to be appended",
|
||||
crdCondition: []CustomResourceDefinitionCondition{
|
||||
{
|
||||
Type: Established,
|
||||
Status: ConditionTrue,
|
||||
Reason: "Accepted",
|
||||
Message: "the initial names have been accepted",
|
||||
LastTransitionTime: metav1.Date(2018, 1, 1, 0, 0, 0, 0, time.UTC),
|
||||
},
|
||||
},
|
||||
newCondition: CustomResourceDefinitionCondition{
|
||||
Type: Terminating,
|
||||
Status: ConditionFalse,
|
||||
Reason: "NeverEstablished",
|
||||
Message: "resource was never established",
|
||||
LastTransitionTime: metav1.Date(2018, 2, 1, 0, 0, 0, 0, time.UTC),
|
||||
},
|
||||
expectedcrdCondition: []CustomResourceDefinitionCondition{
|
||||
{
|
||||
Type: Established,
|
||||
Status: ConditionTrue,
|
||||
Reason: "Accepted",
|
||||
Message: "the initial names have been accepted",
|
||||
LastTransitionTime: metav1.Date(2018, 1, 1, 0, 0, 0, 0, time.UTC),
|
||||
},
|
||||
{
|
||||
Type: Terminating,
|
||||
Status: ConditionFalse,
|
||||
Reason: "NeverEstablished",
|
||||
Message: "resource was never established",
|
||||
LastTransitionTime: metav1.Date(2018, 2, 1, 0, 0, 0, 0, time.UTC),
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tc := range tests {
|
||||
crd := generateCRDwithCondition(tc.crdCondition)
|
||||
SetCRDCondition(crd, tc.newCondition)
|
||||
if len(tc.expectedcrdCondition) != len(crd.Status.Conditions) {
|
||||
t.Errorf("%v expected %v, got %v", tc.name, tc.expectedcrdCondition, crd.Status.Conditions)
|
||||
}
|
||||
for i := range tc.expectedcrdCondition {
|
||||
if !IsCRDConditionEquivalent(&tc.expectedcrdCondition[i], &crd.Status.Conditions[i]) {
|
||||
t.Errorf("%v expected %v, got %v", tc.name, tc.expectedcrdCondition, crd.Status.Conditions)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestRemoveCRDCondition(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
crdCondition []CustomResourceDefinitionCondition
|
||||
conditionType CustomResourceDefinitionConditionType
|
||||
expectedcrdCondition []CustomResourceDefinitionCondition
|
||||
}{
|
||||
{
|
||||
name: "test remove CRDCondition when the conditionType meets",
|
||||
crdCondition: []CustomResourceDefinitionCondition{
|
||||
{
|
||||
Type: Established,
|
||||
Status: ConditionTrue,
|
||||
Reason: "Accepted",
|
||||
Message: "the initial names have been accepted",
|
||||
LastTransitionTime: metav1.Date(2018, 1, 1, 0, 0, 0, 0, time.UTC),
|
||||
},
|
||||
{
|
||||
Type: NamesAccepted,
|
||||
Status: ConditionTrue,
|
||||
Reason: "NoConflicts",
|
||||
Message: "no conflicts found",
|
||||
LastTransitionTime: metav1.Date(2018, 1, 1, 0, 0, 0, 0, time.UTC),
|
||||
},
|
||||
},
|
||||
conditionType: NamesAccepted,
|
||||
expectedcrdCondition: []CustomResourceDefinitionCondition{
|
||||
{
|
||||
Type: Established,
|
||||
Status: ConditionTrue,
|
||||
Reason: "Accepted",
|
||||
Message: "the initial names have been accepted",
|
||||
LastTransitionTime: metav1.Date(2011, 1, 2, 0, 0, 0, 0, time.UTC),
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "test remove CRDCondition when the conditionType not meets",
|
||||
crdCondition: []CustomResourceDefinitionCondition{
|
||||
{
|
||||
Type: Established,
|
||||
Status: ConditionTrue,
|
||||
Reason: "Accepted",
|
||||
Message: "the initial names have been accepted",
|
||||
LastTransitionTime: metav1.Date(2018, 1, 1, 0, 0, 0, 0, time.UTC),
|
||||
},
|
||||
{
|
||||
Type: NamesAccepted,
|
||||
Status: ConditionTrue,
|
||||
Reason: "NoConflicts",
|
||||
Message: "no conflicts found",
|
||||
LastTransitionTime: metav1.Date(2018, 1, 1, 0, 0, 0, 0, time.UTC),
|
||||
},
|
||||
},
|
||||
conditionType: Terminating,
|
||||
expectedcrdCondition: []CustomResourceDefinitionCondition{
|
||||
{
|
||||
Type: Established,
|
||||
Status: ConditionTrue,
|
||||
Reason: "Accepted",
|
||||
Message: "the initial names have been accepted",
|
||||
LastTransitionTime: metav1.Date(2018, 1, 1, 0, 0, 0, 0, time.UTC),
|
||||
},
|
||||
{
|
||||
Type: NamesAccepted,
|
||||
Status: ConditionTrue,
|
||||
Reason: "NoConflicts",
|
||||
Message: "no conflicts found",
|
||||
LastTransitionTime: metav1.Date(2018, 1, 1, 0, 0, 0, 0, time.UTC),
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tc := range tests {
|
||||
crd := generateCRDwithCondition(tc.crdCondition)
|
||||
RemoveCRDCondition(crd, tc.conditionType)
|
||||
if len(tc.expectedcrdCondition) != len(crd.Status.Conditions) {
|
||||
t.Errorf("%v expected %v, got %v", tc.name, tc.expectedcrdCondition, crd.Status.Conditions)
|
||||
}
|
||||
for i := range tc.expectedcrdCondition {
|
||||
if !IsCRDConditionEquivalent(&tc.expectedcrdCondition[i], &crd.Status.Conditions[i]) {
|
||||
t.Errorf("%v expected %v, got %v", tc.name, tc.expectedcrdCondition, crd.Status.Conditions)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestIsCRDConditionPresentAndEqual(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
crdCondition []CustomResourceDefinitionCondition
|
||||
conditionType CustomResourceDefinitionConditionType
|
||||
status ConditionStatus
|
||||
expectresult bool
|
||||
}{
|
||||
{
|
||||
name: "test CRDCondition is not Present",
|
||||
crdCondition: []CustomResourceDefinitionCondition{
|
||||
{
|
||||
Type: Established,
|
||||
Status: ConditionTrue,
|
||||
Reason: "Accepted",
|
||||
Message: "the initial names have been accepted",
|
||||
LastTransitionTime: metav1.Date(2018, 1, 1, 0, 0, 0, 0, time.UTC),
|
||||
},
|
||||
{
|
||||
Type: NamesAccepted,
|
||||
Status: ConditionTrue,
|
||||
Reason: "NoConflicts",
|
||||
Message: "no conflicts found",
|
||||
LastTransitionTime: metav1.Date(2018, 1, 1, 0, 0, 0, 0, time.UTC),
|
||||
},
|
||||
},
|
||||
conditionType: Terminating,
|
||||
status: ConditionTrue,
|
||||
expectresult: false,
|
||||
},
|
||||
{
|
||||
name: "test CRDCondition is Present but not Equal",
|
||||
crdCondition: []CustomResourceDefinitionCondition{
|
||||
{
|
||||
Type: Established,
|
||||
Status: ConditionTrue,
|
||||
Reason: "Accepted",
|
||||
Message: "the initial names have been accepted",
|
||||
LastTransitionTime: metav1.Date(2018, 1, 1, 0, 0, 0, 0, time.UTC),
|
||||
},
|
||||
{
|
||||
Type: NamesAccepted,
|
||||
Status: ConditionTrue,
|
||||
Reason: "NoConflicts",
|
||||
Message: "no conflicts found",
|
||||
LastTransitionTime: metav1.Date(2018, 1, 1, 0, 0, 0, 0, time.UTC),
|
||||
},
|
||||
},
|
||||
conditionType: Established,
|
||||
status: ConditionFalse,
|
||||
expectresult: false,
|
||||
},
|
||||
{
|
||||
name: "test CRDCondition is Present and Equal",
|
||||
crdCondition: []CustomResourceDefinitionCondition{
|
||||
{
|
||||
Type: Established,
|
||||
Status: ConditionTrue,
|
||||
Reason: "Accepted",
|
||||
Message: "the initial names have been accepted",
|
||||
LastTransitionTime: metav1.Date(2018, 1, 1, 0, 0, 0, 0, time.UTC),
|
||||
},
|
||||
{
|
||||
Type: NamesAccepted,
|
||||
Status: ConditionTrue,
|
||||
Reason: "NoConflicts",
|
||||
Message: "no conflicts found",
|
||||
LastTransitionTime: metav1.Date(2018, 1, 1, 0, 0, 0, 0, time.UTC),
|
||||
},
|
||||
},
|
||||
conditionType: NamesAccepted,
|
||||
status: ConditionTrue,
|
||||
expectresult: true,
|
||||
},
|
||||
}
|
||||
for _, tc := range tests {
|
||||
crd := generateCRDwithCondition(tc.crdCondition)
|
||||
res := IsCRDConditionPresentAndEqual(crd, tc.conditionType, tc.status)
|
||||
if res != tc.expectresult {
|
||||
t.Errorf("%v expected %t, got %t", tc.name, tc.expectresult, res)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func generateCRDwithCondition(conditions []CustomResourceDefinitionCondition) *CustomResourceDefinition {
|
||||
testCRDObjectMeta := metav1.ObjectMeta{
|
||||
Name: "plural.group.com",
|
||||
ResourceVersion: "12",
|
||||
}
|
||||
testCRDSpec := CustomResourceDefinitionSpec{
|
||||
Group: "group.com",
|
||||
Version: "version",
|
||||
Scope: ResourceScope("Cluster"),
|
||||
Names: CustomResourceDefinitionNames{
|
||||
Plural: "plural",
|
||||
Singular: "singular",
|
||||
Kind: "kind",
|
||||
ListKind: "listkind",
|
||||
},
|
||||
}
|
||||
testCRDAcceptedNames := CustomResourceDefinitionNames{
|
||||
Plural: "plural",
|
||||
Singular: "singular",
|
||||
Kind: "kind",
|
||||
ListKind: "listkind",
|
||||
}
|
||||
return &CustomResourceDefinition{
|
||||
ObjectMeta: testCRDObjectMeta,
|
||||
Spec: testCRDSpec,
|
||||
Status: CustomResourceDefinitionStatus{
|
||||
AcceptedNames: testCRDAcceptedNames,
|
||||
Conditions: conditions,
|
||||
},
|
||||
}
|
||||
}
|
||||
31
vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/install/install.go
generated
vendored
Normal file
31
vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/install/install.go
generated
vendored
Normal file
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
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 install
|
||||
|
||||
import (
|
||||
"k8s.io/apiextensions-apiserver/pkg/apis/apiextensions"
|
||||
"k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
|
||||
)
|
||||
|
||||
// Install registers the API group and adds types to a scheme
|
||||
func Install(scheme *runtime.Scheme) {
|
||||
utilruntime.Must(apiextensions.AddToScheme(scheme))
|
||||
utilruntime.Must(v1beta1.AddToScheme(scheme))
|
||||
utilruntime.Must(scheme.SetVersionPriority(v1beta1.SchemeGroupVersion))
|
||||
}
|
||||
28
vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/install/roundtrip_test.go
generated
vendored
Normal file
28
vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/install/roundtrip_test.go
generated
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
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 install
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
apiextensionsfuzzer "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/fuzzer"
|
||||
"k8s.io/apimachinery/pkg/api/testing/roundtrip"
|
||||
)
|
||||
|
||||
func TestRoundTrip(t *testing.T) {
|
||||
roundtrip.RoundTripTestForAPIGroup(t, Install, apiextensionsfuzzer.Funcs)
|
||||
}
|
||||
51
vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/register.go
generated
vendored
Normal file
51
vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/register.go
generated
vendored
Normal file
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
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 apiextensions
|
||||
|
||||
import (
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
)
|
||||
|
||||
const GroupName = "apiextensions.k8s.io"
|
||||
|
||||
// SchemeGroupVersion is group version used to register these objects
|
||||
var SchemeGroupVersion = schema.GroupVersion{Group: GroupName, Version: runtime.APIVersionInternal}
|
||||
|
||||
// Kind takes an unqualified kind and returns back a Group qualified GroupKind
|
||||
func Kind(kind string) schema.GroupKind {
|
||||
return SchemeGroupVersion.WithKind(kind).GroupKind()
|
||||
}
|
||||
|
||||
// Resource takes an unqualified resource and returns back a Group qualified GroupResource
|
||||
func Resource(resource string) schema.GroupResource {
|
||||
return SchemeGroupVersion.WithResource(resource).GroupResource()
|
||||
}
|
||||
|
||||
var (
|
||||
SchemeBuilder = runtime.NewSchemeBuilder(addKnownTypes)
|
||||
AddToScheme = SchemeBuilder.AddToScheme
|
||||
)
|
||||
|
||||
// Adds the list of known types to the given scheme.
|
||||
func addKnownTypes(scheme *runtime.Scheme) error {
|
||||
scheme.AddKnownTypes(SchemeGroupVersion,
|
||||
&CustomResourceDefinition{},
|
||||
&CustomResourceDefinitionList{},
|
||||
)
|
||||
return nil
|
||||
}
|
||||
250
vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/types.go
generated
vendored
Normal file
250
vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/types.go
generated
vendored
Normal file
@@ -0,0 +1,250 @@
|
||||
/*
|
||||
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 apiextensions
|
||||
|
||||
import (
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
)
|
||||
|
||||
// CustomResourceDefinitionSpec describes how a user wants their resource to appear
|
||||
type CustomResourceDefinitionSpec struct {
|
||||
// Group is the group this resource belongs in
|
||||
Group string
|
||||
// Version is the version this resource belongs in
|
||||
// Should be always first item in Versions field if provided.
|
||||
// Optional, but at least one of Version or Versions must be set.
|
||||
// Deprecated: Please use `Versions`.
|
||||
Version string
|
||||
// Names are the names used to describe this custom resource
|
||||
Names CustomResourceDefinitionNames
|
||||
// Scope indicates whether this resource is cluster or namespace scoped. Default is namespaced
|
||||
Scope ResourceScope
|
||||
// Validation describes the validation methods for CustomResources
|
||||
Validation *CustomResourceValidation
|
||||
// Subresources describes the subresources for CustomResources
|
||||
Subresources *CustomResourceSubresources
|
||||
// Versions is the list of all supported versions for this resource.
|
||||
// If Version field is provided, this field is optional.
|
||||
// Validation: All versions must use the same validation schema for now. i.e., top
|
||||
// level Validation field is applied to all of these versions.
|
||||
// Order: The version name will be used to compute the order.
|
||||
// If the version string is "kube-like", it will sort above non "kube-like" version strings, which are ordered
|
||||
// lexicographically. "Kube-like" versions start with a "v", then are followed by a number (the major version),
|
||||
// then optionally the string "alpha" or "beta" and another number (the minor version). These are sorted first
|
||||
// by GA > beta > alpha (where GA is a version with no suffix such as beta or alpha), and then by comparing
|
||||
// major version, then minor version. An example sorted list of versions:
|
||||
// v10, v2, v1, v11beta2, v10beta3, v3beta1, v12alpha1, v11alpha2, foo1, foo10.
|
||||
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 {
|
||||
// Name is the version name, e.g. “v1”, “v2beta1”, etc.
|
||||
Name string
|
||||
// Served is a flag enabling/disabling this version from being served via REST APIs
|
||||
Served bool
|
||||
// Storage flags the version as storage version. There must be exactly one flagged
|
||||
// as storage version.
|
||||
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
|
||||
type CustomResourceDefinitionNames struct {
|
||||
// Plural is the plural name of the resource to serve. It must match the name of the CustomResourceDefinition-registration
|
||||
// too: plural.group and it must be all lowercase.
|
||||
Plural string
|
||||
// Singular is the singular name of the resource. It must be all lowercase Defaults to lowercased <kind>
|
||||
Singular string
|
||||
// ShortNames are short names for the resource. It must be all lowercase.
|
||||
ShortNames []string
|
||||
// Kind is the serialized kind of the resource. It is normally CamelCase and singular.
|
||||
Kind string
|
||||
// ListKind is the serialized kind of the list for this resource. Defaults to <kind>List.
|
||||
ListKind string
|
||||
// Categories is a list of grouped resources custom resources belong to (e.g. 'all')
|
||||
// +optional
|
||||
Categories []string
|
||||
}
|
||||
|
||||
// ResourceScope is an enum defining the different scopes available to a custom resource
|
||||
type ResourceScope string
|
||||
|
||||
const (
|
||||
ClusterScoped ResourceScope = "Cluster"
|
||||
NamespaceScoped ResourceScope = "Namespaced"
|
||||
)
|
||||
|
||||
type ConditionStatus string
|
||||
|
||||
// These are valid condition statuses. "ConditionTrue" means a resource is in the condition.
|
||||
// "ConditionFalse" means a resource is not in the condition. "ConditionUnknown" means kubernetes
|
||||
// can't decide if a resource is in the condition or not. In the future, we could add other
|
||||
// intermediate conditions, e.g. ConditionDegraded.
|
||||
const (
|
||||
ConditionTrue ConditionStatus = "True"
|
||||
ConditionFalse ConditionStatus = "False"
|
||||
ConditionUnknown ConditionStatus = "Unknown"
|
||||
)
|
||||
|
||||
// CustomResourceDefinitionConditionType is a valid value for CustomResourceDefinitionCondition.Type
|
||||
type CustomResourceDefinitionConditionType string
|
||||
|
||||
const (
|
||||
// Established means that the resource has become active. A resource is established when all names are
|
||||
// accepted without a conflict for the first time. A resource stays established until deleted, even during
|
||||
// a later NamesAccepted due to changed names. Note that not all names can be changed.
|
||||
Established CustomResourceDefinitionConditionType = "Established"
|
||||
// NamesAccepted means the names chosen for this CustomResourceDefinition do not conflict with others in
|
||||
// the group and are therefore accepted.
|
||||
NamesAccepted CustomResourceDefinitionConditionType = "NamesAccepted"
|
||||
// Terminating means that the CustomResourceDefinition has been deleted and is cleaning up.
|
||||
Terminating CustomResourceDefinitionConditionType = "Terminating"
|
||||
)
|
||||
|
||||
// CustomResourceDefinitionCondition contains details for the current condition of this pod.
|
||||
type CustomResourceDefinitionCondition struct {
|
||||
// Type is the type of the condition.
|
||||
Type CustomResourceDefinitionConditionType
|
||||
// Status is the status of the condition.
|
||||
// Can be True, False, Unknown.
|
||||
Status ConditionStatus
|
||||
// Last time the condition transitioned from one status to another.
|
||||
// +optional
|
||||
LastTransitionTime metav1.Time
|
||||
// Unique, one-word, CamelCase reason for the condition's last transition.
|
||||
// +optional
|
||||
Reason string
|
||||
// Human-readable message indicating details about last transition.
|
||||
// +optional
|
||||
Message string
|
||||
}
|
||||
|
||||
// CustomResourceDefinitionStatus indicates the state of the CustomResourceDefinition
|
||||
type CustomResourceDefinitionStatus struct {
|
||||
// Conditions indicate state for particular aspects of a CustomResourceDefinition
|
||||
Conditions []CustomResourceDefinitionCondition
|
||||
|
||||
// AcceptedNames are the names that are actually being used to serve discovery
|
||||
// They may be different than the names in spec.
|
||||
AcceptedNames CustomResourceDefinitionNames
|
||||
|
||||
// StoredVersions are all versions of CustomResources that were ever persisted. Tracking these
|
||||
// versions allows a migration path for stored versions in etcd. The field is mutable
|
||||
// so the migration controller can first finish a migration to another version (i.e.
|
||||
// that no old objects are left in the storage), and then remove the rest of the
|
||||
// versions from this list.
|
||||
// None of the versions in this list can be removed from the spec.Versions field.
|
||||
StoredVersions []string
|
||||
}
|
||||
|
||||
// CustomResourceCleanupFinalizer is the name of the finalizer which will delete instances of
|
||||
// a CustomResourceDefinition
|
||||
const CustomResourceCleanupFinalizer = "customresourcecleanup.apiextensions.k8s.io"
|
||||
|
||||
// +genclient
|
||||
// +genclient:nonNamespaced
|
||||
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
|
||||
|
||||
// CustomResourceDefinition represents a resource that should be exposed on the API server. Its name MUST be in the format
|
||||
// <.spec.name>.<.spec.group>.
|
||||
type CustomResourceDefinition struct {
|
||||
metav1.TypeMeta
|
||||
metav1.ObjectMeta
|
||||
|
||||
// Spec describes how the user wants the resources to appear
|
||||
Spec CustomResourceDefinitionSpec
|
||||
// Status indicates the actual state of the CustomResourceDefinition
|
||||
Status CustomResourceDefinitionStatus
|
||||
}
|
||||
|
||||
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
|
||||
|
||||
// CustomResourceDefinitionList is a list of CustomResourceDefinition objects.
|
||||
type CustomResourceDefinitionList struct {
|
||||
metav1.TypeMeta
|
||||
metav1.ListMeta
|
||||
|
||||
// Items individual CustomResourceDefinitions
|
||||
Items []CustomResourceDefinition
|
||||
}
|
||||
|
||||
// CustomResourceValidation is a list of validation methods for CustomResources.
|
||||
type CustomResourceValidation struct {
|
||||
// OpenAPIV3Schema is the OpenAPI v3 schema to be validated against.
|
||||
OpenAPIV3Schema *JSONSchemaProps
|
||||
}
|
||||
|
||||
// CustomResourceSubresources defines the status and scale subresources for CustomResources.
|
||||
type CustomResourceSubresources struct {
|
||||
// Status denotes the status subresource for CustomResources
|
||||
Status *CustomResourceSubresourceStatus
|
||||
// Scale denotes the scale subresource for CustomResources
|
||||
Scale *CustomResourceSubresourceScale
|
||||
}
|
||||
|
||||
// CustomResourceSubresourceStatus defines how to serve the status subresource for CustomResources.
|
||||
// Status is represented by the `.status` JSON path inside of a CustomResource. When set,
|
||||
// * exposes a /status subresource for the custom resource
|
||||
// * PUT requests to the /status subresource take a custom resource object, and ignore changes to anything except the status stanza
|
||||
// * PUT/POST/PATCH requests to the custom resource ignore changes to the status stanza
|
||||
type CustomResourceSubresourceStatus struct{}
|
||||
|
||||
// CustomResourceSubresourceScale defines how to serve the scale subresource for CustomResources.
|
||||
type CustomResourceSubresourceScale struct {
|
||||
// SpecReplicasPath defines the JSON path inside of a CustomResource that corresponds to Scale.Spec.Replicas.
|
||||
// Only JSON paths without the array notation are allowed.
|
||||
// Must be a JSON Path under .spec.
|
||||
// If there is no value under the given path in the CustomResource, the /scale subresource will return an error on GET.
|
||||
SpecReplicasPath string
|
||||
// StatusReplicasPath defines the JSON path inside of a CustomResource that corresponds to Scale.Status.Replicas.
|
||||
// Only JSON paths without the array notation are allowed.
|
||||
// Must be a JSON Path under .status.
|
||||
// If there is no value under the given path in the CustomResource, the status replica value in the /scale subresource
|
||||
// will default to 0.
|
||||
StatusReplicasPath string
|
||||
// LabelSelectorPath defines the JSON path inside of a CustomResource that corresponds to Scale.Status.Selector.
|
||||
// Only JSON paths without the array notation are allowed.
|
||||
// Must be a JSON Path under .status.
|
||||
// Must be set to work with HPA.
|
||||
// If there is no value under the given path in the CustomResource, the status label selector value in the /scale
|
||||
// subresource will default to the empty string.
|
||||
// +optional
|
||||
LabelSelectorPath *string
|
||||
}
|
||||
96
vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/types_jsonschema.go
generated
vendored
Normal file
96
vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/types_jsonschema.go
generated
vendored
Normal file
@@ -0,0 +1,96 @@
|
||||
/*
|
||||
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 apiextensions
|
||||
|
||||
// JSONSchemaProps is a JSON-Schema following Specification Draft 4 (http://json-schema.org/).
|
||||
type JSONSchemaProps struct {
|
||||
ID string
|
||||
Schema JSONSchemaURL
|
||||
Ref *string
|
||||
Description string
|
||||
Type string
|
||||
Format string
|
||||
Title string
|
||||
Default *JSON
|
||||
Maximum *float64
|
||||
ExclusiveMaximum bool
|
||||
Minimum *float64
|
||||
ExclusiveMinimum bool
|
||||
MaxLength *int64
|
||||
MinLength *int64
|
||||
Pattern string
|
||||
MaxItems *int64
|
||||
MinItems *int64
|
||||
UniqueItems bool
|
||||
MultipleOf *float64
|
||||
Enum []JSON
|
||||
MaxProperties *int64
|
||||
MinProperties *int64
|
||||
Required []string
|
||||
Items *JSONSchemaPropsOrArray
|
||||
AllOf []JSONSchemaProps
|
||||
OneOf []JSONSchemaProps
|
||||
AnyOf []JSONSchemaProps
|
||||
Not *JSONSchemaProps
|
||||
Properties map[string]JSONSchemaProps
|
||||
AdditionalProperties *JSONSchemaPropsOrBool
|
||||
PatternProperties map[string]JSONSchemaProps
|
||||
Dependencies JSONSchemaDependencies
|
||||
AdditionalItems *JSONSchemaPropsOrBool
|
||||
Definitions JSONSchemaDefinitions
|
||||
ExternalDocs *ExternalDocumentation
|
||||
Example *JSON
|
||||
}
|
||||
|
||||
// JSON represents any valid JSON value.
|
||||
// These types are supported: bool, int64, float64, string, []interface{}, map[string]interface{} and nil.
|
||||
type JSON interface{}
|
||||
|
||||
// JSONSchemaURL represents a schema url.
|
||||
type JSONSchemaURL string
|
||||
|
||||
// JSONSchemaPropsOrArray represents a value that can either be a JSONSchemaProps
|
||||
// or an array of JSONSchemaProps. Mainly here for serialization purposes.
|
||||
type JSONSchemaPropsOrArray struct {
|
||||
Schema *JSONSchemaProps
|
||||
JSONSchemas []JSONSchemaProps
|
||||
}
|
||||
|
||||
// JSONSchemaPropsOrBool represents JSONSchemaProps or a boolean value.
|
||||
// Defaults to true for the boolean property.
|
||||
type JSONSchemaPropsOrBool struct {
|
||||
Allows bool
|
||||
Schema *JSONSchemaProps
|
||||
}
|
||||
|
||||
// JSONSchemaDependencies represent a dependencies property.
|
||||
type JSONSchemaDependencies map[string]JSONSchemaPropsOrStringArray
|
||||
|
||||
// JSONSchemaPropsOrStringArray represents a JSONSchemaProps or a string array.
|
||||
type JSONSchemaPropsOrStringArray struct {
|
||||
Schema *JSONSchemaProps
|
||||
Property []string
|
||||
}
|
||||
|
||||
// JSONSchemaDefinitions contains the models explicitly defined in this spec.
|
||||
type JSONSchemaDefinitions map[string]JSONSchemaProps
|
||||
|
||||
// ExternalDocumentation allows referencing an external resource for extended documentation.
|
||||
type ExternalDocumentation struct {
|
||||
Description string
|
||||
URL string
|
||||
}
|
||||
73
vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1/conversion.go
generated
vendored
Normal file
73
vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1/conversion.go
generated
vendored
Normal file
@@ -0,0 +1,73 @@
|
||||
/*
|
||||
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 v1beta1
|
||||
|
||||
import (
|
||||
"k8s.io/apimachinery/pkg/conversion"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/util/json"
|
||||
|
||||
"k8s.io/apiextensions-apiserver/pkg/apis/apiextensions"
|
||||
)
|
||||
|
||||
func addConversionFuncs(scheme *runtime.Scheme) error {
|
||||
// Add non-generated conversion functions
|
||||
err := scheme.AddConversionFuncs(
|
||||
Convert_apiextensions_JSONSchemaProps_To_v1beta1_JSONSchemaProps,
|
||||
Convert_apiextensions_JSON_To_v1beta1_JSON,
|
||||
Convert_v1beta1_JSON_To_apiextensions_JSON,
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func Convert_apiextensions_JSONSchemaProps_To_v1beta1_JSONSchemaProps(in *apiextensions.JSONSchemaProps, out *JSONSchemaProps, s conversion.Scope) error {
|
||||
if err := autoConvert_apiextensions_JSONSchemaProps_To_v1beta1_JSONSchemaProps(in, out, s); err != nil {
|
||||
return err
|
||||
}
|
||||
if in.Default != nil && *(in.Default) == nil {
|
||||
out.Default = nil
|
||||
}
|
||||
if in.Example != nil && *(in.Example) == nil {
|
||||
out.Example = nil
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func Convert_apiextensions_JSON_To_v1beta1_JSON(in *apiextensions.JSON, out *JSON, s conversion.Scope) error {
|
||||
raw, err := json.Marshal(*in)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
out.Raw = raw
|
||||
return nil
|
||||
}
|
||||
|
||||
func Convert_v1beta1_JSON_To_apiextensions_JSON(in *JSON, out *apiextensions.JSON, s conversion.Scope) error {
|
||||
if in != nil {
|
||||
var i interface{}
|
||||
if err := json.Unmarshal(in.Raw, &i); err != nil {
|
||||
return err
|
||||
}
|
||||
*out = i
|
||||
} else {
|
||||
out = nil
|
||||
}
|
||||
return nil
|
||||
}
|
||||
113
vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1/conversion_test.go
generated
vendored
Normal file
113
vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1/conversion_test.go
generated
vendored
Normal file
@@ -0,0 +1,113 @@
|
||||
/*
|
||||
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 v1beta1
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
|
||||
"k8s.io/apiextensions-apiserver/pkg/apis/apiextensions"
|
||||
)
|
||||
|
||||
func TestJSONConversion(t *testing.T) {
|
||||
nilJSON := apiextensions.JSON(nil)
|
||||
nullJSON := apiextensions.JSON("null")
|
||||
stringJSON := apiextensions.JSON("foo")
|
||||
boolJSON := apiextensions.JSON(true)
|
||||
sliceJSON := apiextensions.JSON([]string{"foo", "bar", "baz"})
|
||||
|
||||
testCases := map[string]struct {
|
||||
input *apiextensions.JSONSchemaProps
|
||||
expected *JSONSchemaProps
|
||||
}{
|
||||
"nil": {
|
||||
input: &apiextensions.JSONSchemaProps{
|
||||
Default: nil,
|
||||
},
|
||||
expected: &JSONSchemaProps{},
|
||||
},
|
||||
"aliased nil": {
|
||||
input: &apiextensions.JSONSchemaProps{
|
||||
Default: &nilJSON,
|
||||
},
|
||||
expected: &JSONSchemaProps{},
|
||||
},
|
||||
"null": {
|
||||
input: &apiextensions.JSONSchemaProps{
|
||||
Default: &nullJSON,
|
||||
},
|
||||
expected: &JSONSchemaProps{
|
||||
Default: &JSON{
|
||||
Raw: []byte(`"null"`),
|
||||
},
|
||||
},
|
||||
},
|
||||
"string": {
|
||||
input: &apiextensions.JSONSchemaProps{
|
||||
Default: &stringJSON,
|
||||
},
|
||||
expected: &JSONSchemaProps{
|
||||
Default: &JSON{
|
||||
Raw: []byte(`"foo"`),
|
||||
},
|
||||
},
|
||||
},
|
||||
"bool": {
|
||||
input: &apiextensions.JSONSchemaProps{
|
||||
Default: &boolJSON,
|
||||
},
|
||||
expected: &JSONSchemaProps{
|
||||
Default: &JSON{
|
||||
Raw: []byte(`true`),
|
||||
},
|
||||
},
|
||||
},
|
||||
"slice": {
|
||||
input: &apiextensions.JSONSchemaProps{
|
||||
Default: &sliceJSON,
|
||||
},
|
||||
expected: &JSONSchemaProps{
|
||||
Default: &JSON{
|
||||
Raw: []byte(`["foo","bar","baz"]`),
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
scheme := runtime.NewScheme()
|
||||
|
||||
// add internal and external types
|
||||
if err := apiextensions.AddToScheme(scheme); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := AddToScheme(scheme); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
for k, tc := range testCases {
|
||||
external := &JSONSchemaProps{}
|
||||
if err := scheme.Convert(tc.input, external, nil); err != nil {
|
||||
t.Errorf("%s: unexpected error: %v", k, err)
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(external, tc.expected) {
|
||||
t.Errorf("%s: expected\n\t%#v, got \n\t%#v", k, tc.expected, external)
|
||||
}
|
||||
}
|
||||
}
|
||||
238
vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1/deepcopy.go
generated
vendored
Normal file
238
vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1/deepcopy.go
generated
vendored
Normal file
@@ -0,0 +1,238 @@
|
||||
/*
|
||||
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 v1beta1
|
||||
|
||||
// TODO: Update this after a tag is created for interface fields in DeepCopy
|
||||
func (in *JSONSchemaProps) DeepCopy() *JSONSchemaProps {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(JSONSchemaProps)
|
||||
*out = *in
|
||||
|
||||
if in.Ref != nil {
|
||||
in, out := &in.Ref, &out.Ref
|
||||
if *in == nil {
|
||||
*out = nil
|
||||
} else {
|
||||
*out = new(string)
|
||||
**out = **in
|
||||
}
|
||||
}
|
||||
|
||||
if in.Maximum != nil {
|
||||
in, out := &in.Maximum, &out.Maximum
|
||||
if *in == nil {
|
||||
*out = nil
|
||||
} else {
|
||||
*out = new(float64)
|
||||
**out = **in
|
||||
}
|
||||
}
|
||||
|
||||
if in.Minimum != nil {
|
||||
in, out := &in.Minimum, &out.Minimum
|
||||
if *in == nil {
|
||||
*out = nil
|
||||
} else {
|
||||
*out = new(float64)
|
||||
**out = **in
|
||||
}
|
||||
}
|
||||
|
||||
if in.MaxLength != nil {
|
||||
in, out := &in.MaxLength, &out.MaxLength
|
||||
if *in == nil {
|
||||
*out = nil
|
||||
} else {
|
||||
*out = new(int64)
|
||||
**out = **in
|
||||
}
|
||||
}
|
||||
|
||||
if in.MinLength != nil {
|
||||
in, out := &in.MinLength, &out.MinLength
|
||||
if *in == nil {
|
||||
*out = nil
|
||||
} else {
|
||||
*out = new(int64)
|
||||
**out = **in
|
||||
}
|
||||
}
|
||||
if in.MaxItems != nil {
|
||||
in, out := &in.MaxItems, &out.MaxItems
|
||||
if *in == nil {
|
||||
*out = nil
|
||||
} else {
|
||||
*out = new(int64)
|
||||
**out = **in
|
||||
}
|
||||
}
|
||||
|
||||
if in.MinItems != nil {
|
||||
in, out := &in.MinItems, &out.MinItems
|
||||
if *in == nil {
|
||||
*out = nil
|
||||
} else {
|
||||
*out = new(int64)
|
||||
**out = **in
|
||||
}
|
||||
}
|
||||
|
||||
if in.MultipleOf != nil {
|
||||
in, out := &in.MultipleOf, &out.MultipleOf
|
||||
if *in == nil {
|
||||
*out = nil
|
||||
} else {
|
||||
*out = new(float64)
|
||||
**out = **in
|
||||
}
|
||||
}
|
||||
|
||||
if in.MaxProperties != nil {
|
||||
in, out := &in.MaxProperties, &out.MaxProperties
|
||||
if *in == nil {
|
||||
*out = nil
|
||||
} else {
|
||||
*out = new(int64)
|
||||
**out = **in
|
||||
}
|
||||
}
|
||||
|
||||
if in.MinProperties != nil {
|
||||
in, out := &in.MinProperties, &out.MinProperties
|
||||
if *in == nil {
|
||||
*out = nil
|
||||
} else {
|
||||
*out = new(int64)
|
||||
**out = **in
|
||||
}
|
||||
}
|
||||
|
||||
if in.Required != nil {
|
||||
in, out := &in.Required, &out.Required
|
||||
*out = make([]string, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
|
||||
if in.Items != nil {
|
||||
in, out := &in.Items, &out.Items
|
||||
if *in == nil {
|
||||
*out = nil
|
||||
} else {
|
||||
*out = new(JSONSchemaPropsOrArray)
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
}
|
||||
|
||||
if in.AllOf != nil {
|
||||
in, out := &in.AllOf, &out.AllOf
|
||||
*out = make([]JSONSchemaProps, len(*in))
|
||||
for i := range *in {
|
||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||
}
|
||||
}
|
||||
|
||||
if in.OneOf != nil {
|
||||
in, out := &in.OneOf, &out.OneOf
|
||||
*out = make([]JSONSchemaProps, len(*in))
|
||||
for i := range *in {
|
||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||
}
|
||||
}
|
||||
if in.AnyOf != nil {
|
||||
in, out := &in.AnyOf, &out.AnyOf
|
||||
*out = make([]JSONSchemaProps, len(*in))
|
||||
for i := range *in {
|
||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||
}
|
||||
}
|
||||
|
||||
if in.Not != nil {
|
||||
in, out := &in.Not, &out.Not
|
||||
if *in == nil {
|
||||
*out = nil
|
||||
} else {
|
||||
*out = new(JSONSchemaProps)
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
}
|
||||
|
||||
if in.Properties != nil {
|
||||
in, out := &in.Properties, &out.Properties
|
||||
*out = make(map[string]JSONSchemaProps, len(*in))
|
||||
for key, val := range *in {
|
||||
(*out)[key] = *val.DeepCopy()
|
||||
}
|
||||
}
|
||||
|
||||
if in.AdditionalProperties != nil {
|
||||
in, out := &in.AdditionalProperties, &out.AdditionalProperties
|
||||
if *in == nil {
|
||||
*out = nil
|
||||
} else {
|
||||
*out = new(JSONSchemaPropsOrBool)
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
}
|
||||
|
||||
if in.PatternProperties != nil {
|
||||
in, out := &in.PatternProperties, &out.PatternProperties
|
||||
*out = make(map[string]JSONSchemaProps, len(*in))
|
||||
for key, val := range *in {
|
||||
(*out)[key] = *val.DeepCopy()
|
||||
}
|
||||
}
|
||||
|
||||
if in.Dependencies != nil {
|
||||
in, out := &in.Dependencies, &out.Dependencies
|
||||
*out = make(JSONSchemaDependencies, len(*in))
|
||||
for key, val := range *in {
|
||||
(*out)[key] = *val.DeepCopy()
|
||||
}
|
||||
}
|
||||
|
||||
if in.AdditionalItems != nil {
|
||||
in, out := &in.AdditionalItems, &out.AdditionalItems
|
||||
if *in == nil {
|
||||
*out = nil
|
||||
} else {
|
||||
*out = new(JSONSchemaPropsOrBool)
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
}
|
||||
|
||||
if in.Definitions != nil {
|
||||
in, out := &in.Definitions, &out.Definitions
|
||||
*out = make(JSONSchemaDefinitions, len(*in))
|
||||
for key, val := range *in {
|
||||
(*out)[key] = *val.DeepCopy()
|
||||
}
|
||||
}
|
||||
|
||||
if in.ExternalDocs != nil {
|
||||
in, out := &in.ExternalDocs, &out.ExternalDocs
|
||||
if *in == nil {
|
||||
*out = nil
|
||||
} else {
|
||||
*out = new(ExternalDocumentation)
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
}
|
||||
|
||||
return out
|
||||
}
|
||||
74
vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1/defaults.go
generated
vendored
Normal file
74
vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1/defaults.go
generated
vendored
Normal file
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
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 v1beta1
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
)
|
||||
|
||||
var swaggerMetadataDescriptions = metav1.ObjectMeta{}.SwaggerDoc()
|
||||
|
||||
func addDefaultingFuncs(scheme *runtime.Scheme) error {
|
||||
scheme.AddTypeDefaultingFunc(&CustomResourceDefinition{}, func(obj interface{}) { SetDefaults_CustomResourceDefinition(obj.(*CustomResourceDefinition)) })
|
||||
// TODO figure out why I can't seem to get my defaulter generated
|
||||
// return RegisterDefaults(scheme)
|
||||
return nil
|
||||
}
|
||||
|
||||
func SetDefaults_CustomResourceDefinition(obj *CustomResourceDefinition) {
|
||||
SetDefaults_CustomResourceDefinitionSpec(&obj.Spec)
|
||||
if len(obj.Status.StoredVersions) == 0 {
|
||||
for _, v := range obj.Spec.Versions {
|
||||
if v.Storage {
|
||||
obj.Status.StoredVersions = append(obj.Status.StoredVersions, v.Name)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func SetDefaults_CustomResourceDefinitionSpec(obj *CustomResourceDefinitionSpec) {
|
||||
if len(obj.Scope) == 0 {
|
||||
obj.Scope = NamespaceScoped
|
||||
}
|
||||
if len(obj.Names.Singular) == 0 {
|
||||
obj.Names.Singular = strings.ToLower(obj.Names.Kind)
|
||||
}
|
||||
if len(obj.Names.ListKind) == 0 && len(obj.Names.Kind) > 0 {
|
||||
obj.Names.ListKind = obj.Names.Kind + "List"
|
||||
}
|
||||
// If there is no list of versions, create on using deprecated Version field.
|
||||
if len(obj.Versions) == 0 && len(obj.Version) != 0 {
|
||||
obj.Versions = []CustomResourceDefinitionVersion{{
|
||||
Name: obj.Version,
|
||||
Storage: true,
|
||||
Served: true,
|
||||
}}
|
||||
}
|
||||
// For backward compatibility set the version field to the first item in versions list.
|
||||
if len(obj.Version) == 0 && len(obj.Versions) != 0 {
|
||||
obj.Version = obj.Versions[0].Name
|
||||
}
|
||||
if len(obj.AdditionalPrinterColumns) == 0 {
|
||||
obj.AdditionalPrinterColumns = []CustomResourceColumnDefinition{
|
||||
{Name: "Age", Type: "date", Description: swaggerMetadataDescriptions["creationTimestamp"], JSONPath: ".metadata.creationTimestamp"},
|
||||
}
|
||||
}
|
||||
}
|
||||
24
vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1/doc.go
generated
vendored
Normal file
24
vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1/doc.go
generated
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
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.
|
||||
*/
|
||||
|
||||
// +k8s:deepcopy-gen=package
|
||||
// +k8s:conversion-gen=k8s.io/apiextensions-apiserver/pkg/apis/apiextensions
|
||||
// +k8s:defaulter-gen=TypeMeta
|
||||
|
||||
// Package v1beta1 is the v1beta1 version of the API.
|
||||
// +groupName=apiextensions.k8s.io
|
||||
// +k8s:openapi-gen=true
|
||||
package v1beta1 // import "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1"
|
||||
6023
vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1/generated.pb.go
generated
vendored
Normal file
6023
vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1/generated.pb.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
354
vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1/generated.proto
generated
vendored
Normal file
354
vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1/generated.proto
generated
vendored
Normal file
@@ -0,0 +1,354 @@
|
||||
/*
|
||||
Copyright 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.
|
||||
*/
|
||||
|
||||
|
||||
// This file was autogenerated by go-to-protobuf. Do not edit it manually!
|
||||
|
||||
syntax = 'proto2';
|
||||
|
||||
package k8s.io.apiextensions_apiserver.pkg.apis.apiextensions.v1beta1;
|
||||
|
||||
import "k8s.io/apimachinery/pkg/apis/meta/v1/generated.proto";
|
||||
import "k8s.io/apimachinery/pkg/runtime/generated.proto";
|
||||
import "k8s.io/apimachinery/pkg/runtime/schema/generated.proto";
|
||||
import "k8s.io/apimachinery/pkg/util/intstr/generated.proto";
|
||||
|
||||
// Package-wide variables from generator "generated".
|
||||
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
|
||||
// <.spec.name>.<.spec.group>.
|
||||
message CustomResourceDefinition {
|
||||
optional k8s.io.apimachinery.pkg.apis.meta.v1.ObjectMeta metadata = 1;
|
||||
|
||||
// Spec describes how the user wants the resources to appear
|
||||
optional CustomResourceDefinitionSpec spec = 2;
|
||||
|
||||
// Status indicates the actual state of the CustomResourceDefinition
|
||||
optional CustomResourceDefinitionStatus status = 3;
|
||||
}
|
||||
|
||||
// CustomResourceDefinitionCondition contains details for the current condition of this pod.
|
||||
message CustomResourceDefinitionCondition {
|
||||
// Type is the type of the condition.
|
||||
optional string type = 1;
|
||||
|
||||
// Status is the status of the condition.
|
||||
// Can be True, False, Unknown.
|
||||
optional string status = 2;
|
||||
|
||||
// Last time the condition transitioned from one status to another.
|
||||
// +optional
|
||||
optional k8s.io.apimachinery.pkg.apis.meta.v1.Time lastTransitionTime = 3;
|
||||
|
||||
// Unique, one-word, CamelCase reason for the condition's last transition.
|
||||
// +optional
|
||||
optional string reason = 4;
|
||||
|
||||
// Human-readable message indicating details about last transition.
|
||||
// +optional
|
||||
optional string message = 5;
|
||||
}
|
||||
|
||||
// CustomResourceDefinitionList is a list of CustomResourceDefinition objects.
|
||||
message CustomResourceDefinitionList {
|
||||
optional k8s.io.apimachinery.pkg.apis.meta.v1.ListMeta metadata = 1;
|
||||
|
||||
// Items individual CustomResourceDefinitions
|
||||
repeated CustomResourceDefinition items = 2;
|
||||
}
|
||||
|
||||
// CustomResourceDefinitionNames indicates the names to serve this CustomResourceDefinition
|
||||
message CustomResourceDefinitionNames {
|
||||
// Plural is the plural name of the resource to serve. It must match the name of the CustomResourceDefinition-registration
|
||||
// too: plural.group and it must be all lowercase.
|
||||
optional string plural = 1;
|
||||
|
||||
// Singular is the singular name of the resource. It must be all lowercase Defaults to lowercased <kind>
|
||||
optional string singular = 2;
|
||||
|
||||
// ShortNames are short names for the resource. It must be all lowercase.
|
||||
repeated string shortNames = 3;
|
||||
|
||||
// Kind is the serialized kind of the resource. It is normally CamelCase and singular.
|
||||
optional string kind = 4;
|
||||
|
||||
// ListKind is the serialized kind of the list for this resource. Defaults to <kind>List.
|
||||
optional string listKind = 5;
|
||||
|
||||
// Categories is a list of grouped resources custom resources belong to (e.g. 'all')
|
||||
// +optional
|
||||
repeated string categories = 6;
|
||||
}
|
||||
|
||||
// CustomResourceDefinitionSpec describes how a user wants their resource to appear
|
||||
message CustomResourceDefinitionSpec {
|
||||
// Group is the group this resource belongs in
|
||||
optional string group = 1;
|
||||
|
||||
// Version is the version this resource belongs in
|
||||
// Should be always first item in Versions field if provided.
|
||||
// Optional, but at least one of Version or Versions must be set.
|
||||
// Deprecated: Please use `Versions`.
|
||||
// +optional
|
||||
optional string version = 2;
|
||||
|
||||
// Names are the names used to describe this custom resource
|
||||
optional CustomResourceDefinitionNames names = 3;
|
||||
|
||||
// Scope indicates whether this resource is cluster or namespace scoped. Default is namespaced
|
||||
optional string scope = 4;
|
||||
|
||||
// Validation describes the validation methods for CustomResources
|
||||
// +optional
|
||||
optional CustomResourceValidation validation = 5;
|
||||
|
||||
// Subresources describes the subresources for CustomResources
|
||||
// +optional
|
||||
optional CustomResourceSubresources subresources = 6;
|
||||
|
||||
// Versions is the list of all supported versions for this resource.
|
||||
// If Version field is provided, this field is optional.
|
||||
// Validation: All versions must use the same validation schema for now. i.e., top
|
||||
// level Validation field is applied to all of these versions.
|
||||
// Order: The version name will be used to compute the order.
|
||||
// If the version string is "kube-like", it will sort above non "kube-like" version strings, which are ordered
|
||||
// lexicographically. "Kube-like" versions start with a "v", then are followed by a number (the major version),
|
||||
// then optionally the string "alpha" or "beta" and another number (the minor version). These are sorted first
|
||||
// by GA > beta > alpha (where GA is a version with no suffix such as beta or alpha), and then by comparing
|
||||
// major version, then minor version. An example sorted list of versions:
|
||||
// v10, v2, v1, v11beta2, v10beta3, v3beta1, v12alpha1, v11alpha2, foo1, foo10.
|
||||
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
|
||||
message CustomResourceDefinitionStatus {
|
||||
// Conditions indicate state for particular aspects of a CustomResourceDefinition
|
||||
repeated CustomResourceDefinitionCondition conditions = 1;
|
||||
|
||||
// AcceptedNames are the names that are actually being used to serve discovery
|
||||
// They may be different than the names in spec.
|
||||
optional CustomResourceDefinitionNames acceptedNames = 2;
|
||||
|
||||
// StoredVersions are all versions of CustomResources that were ever persisted. Tracking these
|
||||
// versions allows a migration path for stored versions in etcd. The field is mutable
|
||||
// so the migration controller can first finish a migration to another version (i.e.
|
||||
// that no old objects are left in the storage), and then remove the rest of the
|
||||
// versions from this list.
|
||||
// None of the versions in this list can be removed from the spec.Versions field.
|
||||
repeated string storedVersions = 3;
|
||||
}
|
||||
|
||||
message CustomResourceDefinitionVersion {
|
||||
// Name is the version name, e.g. “v1”, “v2beta1”, etc.
|
||||
optional string name = 1;
|
||||
|
||||
// Served is a flag enabling/disabling this version from being served via REST APIs
|
||||
optional bool served = 2;
|
||||
|
||||
// Storage flags the version as storage version. There must be exactly one
|
||||
// flagged as storage version.
|
||||
optional bool storage = 3;
|
||||
}
|
||||
|
||||
// CustomResourceSubresourceScale defines how to serve the scale subresource for CustomResources.
|
||||
message CustomResourceSubresourceScale {
|
||||
// SpecReplicasPath defines the JSON path inside of a CustomResource that corresponds to Scale.Spec.Replicas.
|
||||
// Only JSON paths without the array notation are allowed.
|
||||
// Must be a JSON Path under .spec.
|
||||
// If there is no value under the given path in the CustomResource, the /scale subresource will return an error on GET.
|
||||
optional string specReplicasPath = 1;
|
||||
|
||||
// StatusReplicasPath defines the JSON path inside of a CustomResource that corresponds to Scale.Status.Replicas.
|
||||
// Only JSON paths without the array notation are allowed.
|
||||
// Must be a JSON Path under .status.
|
||||
// If there is no value under the given path in the CustomResource, the status replica value in the /scale subresource
|
||||
// will default to 0.
|
||||
optional string statusReplicasPath = 2;
|
||||
|
||||
// LabelSelectorPath defines the JSON path inside of a CustomResource that corresponds to Scale.Status.Selector.
|
||||
// Only JSON paths without the array notation are allowed.
|
||||
// Must be a JSON Path under .status.
|
||||
// Must be set to work with HPA.
|
||||
// If there is no value under the given path in the CustomResource, the status label selector value in the /scale
|
||||
// subresource will default to the empty string.
|
||||
// +optional
|
||||
optional string labelSelectorPath = 3;
|
||||
}
|
||||
|
||||
// CustomResourceSubresourceStatus defines how to serve the status subresource for CustomResources.
|
||||
// Status is represented by the `.status` JSON path inside of a CustomResource. When set,
|
||||
// * exposes a /status subresource for the custom resource
|
||||
// * PUT requests to the /status subresource take a custom resource object, and ignore changes to anything except the status stanza
|
||||
// * PUT/POST/PATCH requests to the custom resource ignore changes to the status stanza
|
||||
message CustomResourceSubresourceStatus {
|
||||
}
|
||||
|
||||
// CustomResourceSubresources defines the status and scale subresources for CustomResources.
|
||||
message CustomResourceSubresources {
|
||||
// Status denotes the status subresource for CustomResources
|
||||
optional CustomResourceSubresourceStatus status = 1;
|
||||
|
||||
// Scale denotes the scale subresource for CustomResources
|
||||
optional CustomResourceSubresourceScale scale = 2;
|
||||
}
|
||||
|
||||
// CustomResourceValidation is a list of validation methods for CustomResources.
|
||||
message CustomResourceValidation {
|
||||
// OpenAPIV3Schema is the OpenAPI v3 schema to be validated against.
|
||||
optional JSONSchemaProps openAPIV3Schema = 1;
|
||||
}
|
||||
|
||||
// ExternalDocumentation allows referencing an external resource for extended documentation.
|
||||
message ExternalDocumentation {
|
||||
optional string description = 1;
|
||||
|
||||
optional string url = 2;
|
||||
}
|
||||
|
||||
// JSON represents any valid JSON value.
|
||||
// These types are supported: bool, int64, float64, string, []interface{}, map[string]interface{} and nil.
|
||||
message JSON {
|
||||
optional bytes raw = 1;
|
||||
}
|
||||
|
||||
// JSONSchemaProps is a JSON-Schema following Specification Draft 4 (http://json-schema.org/).
|
||||
message JSONSchemaProps {
|
||||
optional string id = 1;
|
||||
|
||||
optional string schema = 2;
|
||||
|
||||
optional string ref = 3;
|
||||
|
||||
optional string description = 4;
|
||||
|
||||
optional string type = 5;
|
||||
|
||||
optional string format = 6;
|
||||
|
||||
optional string title = 7;
|
||||
|
||||
optional JSON default = 8;
|
||||
|
||||
optional double maximum = 9;
|
||||
|
||||
optional bool exclusiveMaximum = 10;
|
||||
|
||||
optional double minimum = 11;
|
||||
|
||||
optional bool exclusiveMinimum = 12;
|
||||
|
||||
optional int64 maxLength = 13;
|
||||
|
||||
optional int64 minLength = 14;
|
||||
|
||||
optional string pattern = 15;
|
||||
|
||||
optional int64 maxItems = 16;
|
||||
|
||||
optional int64 minItems = 17;
|
||||
|
||||
optional bool uniqueItems = 18;
|
||||
|
||||
optional double multipleOf = 19;
|
||||
|
||||
repeated JSON enum = 20;
|
||||
|
||||
optional int64 maxProperties = 21;
|
||||
|
||||
optional int64 minProperties = 22;
|
||||
|
||||
repeated string required = 23;
|
||||
|
||||
optional JSONSchemaPropsOrArray items = 24;
|
||||
|
||||
repeated JSONSchemaProps allOf = 25;
|
||||
|
||||
repeated JSONSchemaProps oneOf = 26;
|
||||
|
||||
repeated JSONSchemaProps anyOf = 27;
|
||||
|
||||
optional JSONSchemaProps not = 28;
|
||||
|
||||
map<string, JSONSchemaProps> properties = 29;
|
||||
|
||||
optional JSONSchemaPropsOrBool additionalProperties = 30;
|
||||
|
||||
map<string, JSONSchemaProps> patternProperties = 31;
|
||||
|
||||
map<string, JSONSchemaPropsOrStringArray> dependencies = 32;
|
||||
|
||||
optional JSONSchemaPropsOrBool additionalItems = 33;
|
||||
|
||||
map<string, JSONSchemaProps> definitions = 34;
|
||||
|
||||
optional ExternalDocumentation externalDocs = 35;
|
||||
|
||||
optional JSON example = 36;
|
||||
}
|
||||
|
||||
// JSONSchemaPropsOrArray represents a value that can either be a JSONSchemaProps
|
||||
// or an array of JSONSchemaProps. Mainly here for serialization purposes.
|
||||
message JSONSchemaPropsOrArray {
|
||||
optional JSONSchemaProps schema = 1;
|
||||
|
||||
repeated JSONSchemaProps jSONSchemas = 2;
|
||||
}
|
||||
|
||||
// JSONSchemaPropsOrBool represents JSONSchemaProps or a boolean value.
|
||||
// Defaults to true for the boolean property.
|
||||
message JSONSchemaPropsOrBool {
|
||||
optional bool allows = 1;
|
||||
|
||||
optional JSONSchemaProps schema = 2;
|
||||
}
|
||||
|
||||
// JSONSchemaPropsOrStringArray represents a JSONSchemaProps or a string array.
|
||||
message JSONSchemaPropsOrStringArray {
|
||||
optional JSONSchemaProps schema = 1;
|
||||
|
||||
repeated string property = 2;
|
||||
}
|
||||
|
||||
135
vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1/marshal.go
generated
vendored
Normal file
135
vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1/marshal.go
generated
vendored
Normal file
@@ -0,0 +1,135 @@
|
||||
/*
|
||||
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 v1beta1
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"k8s.io/apimachinery/pkg/util/json"
|
||||
)
|
||||
|
||||
var jsTrue = []byte("true")
|
||||
var jsFalse = []byte("false")
|
||||
|
||||
func (s JSONSchemaPropsOrBool) MarshalJSON() ([]byte, error) {
|
||||
if s.Schema != nil {
|
||||
return json.Marshal(s.Schema)
|
||||
}
|
||||
|
||||
if s.Schema == nil && !s.Allows {
|
||||
return jsFalse, nil
|
||||
}
|
||||
return jsTrue, nil
|
||||
}
|
||||
|
||||
func (s *JSONSchemaPropsOrBool) UnmarshalJSON(data []byte) error {
|
||||
var nw JSONSchemaPropsOrBool
|
||||
switch {
|
||||
case len(data) == 0:
|
||||
case data[0] == '{':
|
||||
var sch JSONSchemaProps
|
||||
if err := json.Unmarshal(data, &sch); err != nil {
|
||||
return err
|
||||
}
|
||||
nw.Allows = true
|
||||
nw.Schema = &sch
|
||||
case len(data) == 4 && string(data) == "true":
|
||||
nw.Allows = true
|
||||
case len(data) == 5 && string(data) == "false":
|
||||
nw.Allows = false
|
||||
default:
|
||||
return errors.New("boolean or JSON schema expected")
|
||||
}
|
||||
*s = nw
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s JSONSchemaPropsOrStringArray) MarshalJSON() ([]byte, error) {
|
||||
if len(s.Property) > 0 {
|
||||
return json.Marshal(s.Property)
|
||||
}
|
||||
if s.Schema != nil {
|
||||
return json.Marshal(s.Schema)
|
||||
}
|
||||
return []byte("null"), nil
|
||||
}
|
||||
|
||||
func (s *JSONSchemaPropsOrStringArray) UnmarshalJSON(data []byte) error {
|
||||
var first byte
|
||||
if len(data) > 1 {
|
||||
first = data[0]
|
||||
}
|
||||
var nw JSONSchemaPropsOrStringArray
|
||||
if first == '{' {
|
||||
var sch JSONSchemaProps
|
||||
if err := json.Unmarshal(data, &sch); err != nil {
|
||||
return err
|
||||
}
|
||||
nw.Schema = &sch
|
||||
}
|
||||
if first == '[' {
|
||||
if err := json.Unmarshal(data, &nw.Property); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
*s = nw
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s JSONSchemaPropsOrArray) MarshalJSON() ([]byte, error) {
|
||||
if len(s.JSONSchemas) > 0 {
|
||||
return json.Marshal(s.JSONSchemas)
|
||||
}
|
||||
return json.Marshal(s.Schema)
|
||||
}
|
||||
|
||||
func (s *JSONSchemaPropsOrArray) UnmarshalJSON(data []byte) error {
|
||||
var nw JSONSchemaPropsOrArray
|
||||
var first byte
|
||||
if len(data) > 1 {
|
||||
first = data[0]
|
||||
}
|
||||
if first == '{' {
|
||||
var sch JSONSchemaProps
|
||||
if err := json.Unmarshal(data, &sch); err != nil {
|
||||
return err
|
||||
}
|
||||
nw.Schema = &sch
|
||||
}
|
||||
if first == '[' {
|
||||
if err := json.Unmarshal(data, &nw.JSONSchemas); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
*s = nw
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s JSON) MarshalJSON() ([]byte, error) {
|
||||
if len(s.Raw) > 0 {
|
||||
return s.Raw, nil
|
||||
}
|
||||
return []byte("null"), nil
|
||||
|
||||
}
|
||||
|
||||
func (s *JSON) UnmarshalJSON(data []byte) error {
|
||||
if len(data) > 0 && string(data) != "null" {
|
||||
s.Raw = data
|
||||
}
|
||||
return nil
|
||||
}
|
||||
150
vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1/marshal_test.go
generated
vendored
Normal file
150
vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1/marshal_test.go
generated
vendored
Normal file
@@ -0,0 +1,150 @@
|
||||
/*
|
||||
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 v1beta1
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"reflect"
|
||||
"testing"
|
||||
)
|
||||
|
||||
type JSONSchemaPropsOrBoolHolder struct {
|
||||
JSPoB JSONSchemaPropsOrBool `json:"val1"`
|
||||
JSPoBOmitEmpty *JSONSchemaPropsOrBool `json:"val2,omitempty"`
|
||||
}
|
||||
|
||||
func TestJSONSchemaPropsOrBoolUnmarshalJSON(t *testing.T) {
|
||||
cases := []struct {
|
||||
input string
|
||||
result JSONSchemaPropsOrBoolHolder
|
||||
}{
|
||||
{`{}`, JSONSchemaPropsOrBoolHolder{}},
|
||||
|
||||
{`{"val1": {}}`, JSONSchemaPropsOrBoolHolder{JSPoB: JSONSchemaPropsOrBool{Allows: true, Schema: &JSONSchemaProps{}}}},
|
||||
{`{"val1": {"type":"string"}}`, JSONSchemaPropsOrBoolHolder{JSPoB: JSONSchemaPropsOrBool{Allows: true, Schema: &JSONSchemaProps{Type: "string"}}}},
|
||||
{`{"val1": false}`, JSONSchemaPropsOrBoolHolder{JSPoB: JSONSchemaPropsOrBool{}}},
|
||||
{`{"val1": true}`, JSONSchemaPropsOrBoolHolder{JSPoB: JSONSchemaPropsOrBool{Allows: true}}},
|
||||
|
||||
{`{"val2": {}}`, JSONSchemaPropsOrBoolHolder{JSPoBOmitEmpty: &JSONSchemaPropsOrBool{Allows: true, Schema: &JSONSchemaProps{}}}},
|
||||
{`{"val2": {"type":"string"}}`, JSONSchemaPropsOrBoolHolder{JSPoBOmitEmpty: &JSONSchemaPropsOrBool{Allows: true, Schema: &JSONSchemaProps{Type: "string"}}}},
|
||||
{`{"val2": false}`, JSONSchemaPropsOrBoolHolder{JSPoBOmitEmpty: &JSONSchemaPropsOrBool{}}},
|
||||
{`{"val2": true}`, JSONSchemaPropsOrBoolHolder{JSPoBOmitEmpty: &JSONSchemaPropsOrBool{Allows: true}}},
|
||||
}
|
||||
|
||||
for _, c := range cases {
|
||||
var result JSONSchemaPropsOrBoolHolder
|
||||
if err := json.Unmarshal([]byte(c.input), &result); err != nil {
|
||||
t.Errorf("Failed to unmarshal input '%v': %v", c.input, err)
|
||||
}
|
||||
if !reflect.DeepEqual(result, c.result) {
|
||||
t.Errorf("Failed to unmarshal input '%v': expected %+v, got %+v", c.input, c.result, result)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestStringArrayOrStringMarshalJSON(t *testing.T) {
|
||||
cases := []struct {
|
||||
input JSONSchemaPropsOrBoolHolder
|
||||
result string
|
||||
}{
|
||||
{JSONSchemaPropsOrBoolHolder{}, `{"val1":false}`},
|
||||
|
||||
{JSONSchemaPropsOrBoolHolder{JSPoB: JSONSchemaPropsOrBool{Schema: &JSONSchemaProps{}}}, `{"val1":{}}`},
|
||||
{JSONSchemaPropsOrBoolHolder{JSPoB: JSONSchemaPropsOrBool{Schema: &JSONSchemaProps{Type: "string"}}}, `{"val1":{"type":"string"}}`},
|
||||
{JSONSchemaPropsOrBoolHolder{JSPoB: JSONSchemaPropsOrBool{}}, `{"val1":false}`},
|
||||
{JSONSchemaPropsOrBoolHolder{JSPoB: JSONSchemaPropsOrBool{Allows: true}}, `{"val1":true}`},
|
||||
|
||||
{JSONSchemaPropsOrBoolHolder{JSPoBOmitEmpty: &JSONSchemaPropsOrBool{Schema: &JSONSchemaProps{}}}, `{"val1":false,"val2":{}}`},
|
||||
{JSONSchemaPropsOrBoolHolder{JSPoBOmitEmpty: &JSONSchemaPropsOrBool{Schema: &JSONSchemaProps{Type: "string"}}}, `{"val1":false,"val2":{"type":"string"}}`},
|
||||
{JSONSchemaPropsOrBoolHolder{JSPoBOmitEmpty: &JSONSchemaPropsOrBool{}}, `{"val1":false,"val2":false}`},
|
||||
{JSONSchemaPropsOrBoolHolder{JSPoBOmitEmpty: &JSONSchemaPropsOrBool{Allows: true}}, `{"val1":false,"val2":true}`},
|
||||
}
|
||||
|
||||
for _, c := range cases {
|
||||
result, err := json.Marshal(&c.input)
|
||||
if err != nil {
|
||||
t.Errorf("Unexpected error marshaling input '%v': %v", c.input, err)
|
||||
}
|
||||
if string(result) != c.result {
|
||||
t.Errorf("Failed to marshal input '%v': expected: %q, got %q", c.input, c.result, string(result))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type JSONSchemaPropsOrArrayHolder struct {
|
||||
JSPoA JSONSchemaPropsOrArray `json:"val1"`
|
||||
JSPoAOmitEmpty *JSONSchemaPropsOrArray `json:"val2,omitempty"`
|
||||
}
|
||||
|
||||
func TestJSONSchemaPropsOrArrayUnmarshalJSON(t *testing.T) {
|
||||
cases := []struct {
|
||||
input string
|
||||
result JSONSchemaPropsOrArrayHolder
|
||||
}{
|
||||
{`{}`, JSONSchemaPropsOrArrayHolder{}},
|
||||
|
||||
{`{"val1": {}}`, JSONSchemaPropsOrArrayHolder{JSPoA: JSONSchemaPropsOrArray{Schema: &JSONSchemaProps{}}}},
|
||||
{`{"val1": {"type":"string"}}`, JSONSchemaPropsOrArrayHolder{JSPoA: JSONSchemaPropsOrArray{Schema: &JSONSchemaProps{Type: "string"}}}},
|
||||
{`{"val1": [{}]}`, JSONSchemaPropsOrArrayHolder{JSPoA: JSONSchemaPropsOrArray{JSONSchemas: []JSONSchemaProps{{}}}}},
|
||||
{`{"val1": [{},{"type":"string"}]}`, JSONSchemaPropsOrArrayHolder{JSPoA: JSONSchemaPropsOrArray{JSONSchemas: []JSONSchemaProps{{}, {Type: "string"}}}}},
|
||||
|
||||
{`{"val2": {}}`, JSONSchemaPropsOrArrayHolder{JSPoAOmitEmpty: &JSONSchemaPropsOrArray{Schema: &JSONSchemaProps{}}}},
|
||||
{`{"val2": {"type":"string"}}`, JSONSchemaPropsOrArrayHolder{JSPoAOmitEmpty: &JSONSchemaPropsOrArray{Schema: &JSONSchemaProps{Type: "string"}}}},
|
||||
{`{"val2": [{}]}`, JSONSchemaPropsOrArrayHolder{JSPoAOmitEmpty: &JSONSchemaPropsOrArray{JSONSchemas: []JSONSchemaProps{{}}}}},
|
||||
{`{"val2": [{},{"type":"string"}]}`, JSONSchemaPropsOrArrayHolder{JSPoAOmitEmpty: &JSONSchemaPropsOrArray{JSONSchemas: []JSONSchemaProps{{}, {Type: "string"}}}}},
|
||||
}
|
||||
|
||||
for _, c := range cases {
|
||||
var result JSONSchemaPropsOrArrayHolder
|
||||
if err := json.Unmarshal([]byte(c.input), &result); err != nil {
|
||||
t.Errorf("Failed to unmarshal input '%v': %v", c.input, err)
|
||||
}
|
||||
if !reflect.DeepEqual(result, c.result) {
|
||||
t.Errorf("Failed to unmarshal input '%v': expected %+v, got %+v", c.input, c.result, result)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestJSONSchemaPropsOrArrayMarshalJSON(t *testing.T) {
|
||||
cases := []struct {
|
||||
input JSONSchemaPropsOrArrayHolder
|
||||
result string
|
||||
}{
|
||||
{JSONSchemaPropsOrArrayHolder{}, `{"val1":null}`},
|
||||
|
||||
{JSONSchemaPropsOrArrayHolder{JSPoA: JSONSchemaPropsOrArray{Schema: &JSONSchemaProps{}}}, `{"val1":{}}`},
|
||||
{JSONSchemaPropsOrArrayHolder{JSPoA: JSONSchemaPropsOrArray{Schema: &JSONSchemaProps{Type: "string"}}}, `{"val1":{"type":"string"}}`},
|
||||
{JSONSchemaPropsOrArrayHolder{JSPoA: JSONSchemaPropsOrArray{JSONSchemas: []JSONSchemaProps{{}}}}, `{"val1":[{}]}`},
|
||||
{JSONSchemaPropsOrArrayHolder{JSPoA: JSONSchemaPropsOrArray{JSONSchemas: []JSONSchemaProps{{}, {Type: "string"}}}}, `{"val1":[{},{"type":"string"}]}`},
|
||||
|
||||
{JSONSchemaPropsOrArrayHolder{JSPoAOmitEmpty: &JSONSchemaPropsOrArray{}}, `{"val1":null,"val2":null}`},
|
||||
{JSONSchemaPropsOrArrayHolder{JSPoAOmitEmpty: &JSONSchemaPropsOrArray{Schema: &JSONSchemaProps{}}}, `{"val1":null,"val2":{}}`},
|
||||
{JSONSchemaPropsOrArrayHolder{JSPoAOmitEmpty: &JSONSchemaPropsOrArray{Schema: &JSONSchemaProps{Type: "string"}}}, `{"val1":null,"val2":{"type":"string"}}`},
|
||||
{JSONSchemaPropsOrArrayHolder{JSPoAOmitEmpty: &JSONSchemaPropsOrArray{JSONSchemas: []JSONSchemaProps{{}}}}, `{"val1":null,"val2":[{}]}`},
|
||||
{JSONSchemaPropsOrArrayHolder{JSPoAOmitEmpty: &JSONSchemaPropsOrArray{JSONSchemas: []JSONSchemaProps{{}, {Type: "string"}}}}, `{"val1":null,"val2":[{},{"type":"string"}]}`},
|
||||
}
|
||||
|
||||
for i, c := range cases {
|
||||
result, err := json.Marshal(&c.input)
|
||||
if err != nil {
|
||||
t.Errorf("%d: Unexpected error marshaling input '%v': %v", i, c.input, err)
|
||||
}
|
||||
if string(result) != c.result {
|
||||
t.Errorf("%d: Failed to marshal input '%v': expected: %q, got %q", i, c.input, c.result, string(result))
|
||||
}
|
||||
}
|
||||
}
|
||||
61
vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1/register.go
generated
vendored
Normal file
61
vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1/register.go
generated
vendored
Normal file
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
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 v1beta1
|
||||
|
||||
import (
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
)
|
||||
|
||||
const GroupName = "apiextensions.k8s.io"
|
||||
|
||||
// SchemeGroupVersion is group version used to register these objects
|
||||
var SchemeGroupVersion = schema.GroupVersion{Group: GroupName, Version: "v1beta1"}
|
||||
|
||||
// Kind takes an unqualified kind and returns back a Group qualified GroupKind
|
||||
func Kind(kind string) schema.GroupKind {
|
||||
return SchemeGroupVersion.WithKind(kind).GroupKind()
|
||||
}
|
||||
|
||||
// Resource takes an unqualified resource and returns back a Group qualified GroupResource
|
||||
func Resource(resource string) schema.GroupResource {
|
||||
return SchemeGroupVersion.WithResource(resource).GroupResource()
|
||||
}
|
||||
|
||||
var (
|
||||
SchemeBuilder = runtime.NewSchemeBuilder(addKnownTypes, addDefaultingFuncs, addConversionFuncs)
|
||||
localSchemeBuilder = &SchemeBuilder
|
||||
AddToScheme = localSchemeBuilder.AddToScheme
|
||||
)
|
||||
|
||||
// Adds the list of known types to the given scheme.
|
||||
func addKnownTypes(scheme *runtime.Scheme) error {
|
||||
scheme.AddKnownTypes(SchemeGroupVersion,
|
||||
&CustomResourceDefinition{},
|
||||
&CustomResourceDefinitionList{},
|
||||
)
|
||||
metav1.AddToGroupVersion(scheme, SchemeGroupVersion)
|
||||
return nil
|
||||
}
|
||||
|
||||
func init() {
|
||||
// We only register manually written functions here. The registration of the
|
||||
// generated functions takes place in the generated files. The separation
|
||||
// makes the code compile even when the generated files are missing.
|
||||
localSchemeBuilder.Register(addDefaultingFuncs, addConversionFuncs)
|
||||
}
|
||||
253
vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1/types.go
generated
vendored
Normal file
253
vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1/types.go
generated
vendored
Normal file
@@ -0,0 +1,253 @@
|
||||
/*
|
||||
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 v1beta1
|
||||
|
||||
import (
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
)
|
||||
|
||||
// CustomResourceDefinitionSpec describes how a user wants their resource to appear
|
||||
type CustomResourceDefinitionSpec struct {
|
||||
// Group is the group this resource belongs in
|
||||
Group string `json:"group" protobuf:"bytes,1,opt,name=group"`
|
||||
// Version is the version this resource belongs in
|
||||
// Should be always first item in Versions field if provided.
|
||||
// Optional, but at least one of Version or Versions must be set.
|
||||
// Deprecated: Please use `Versions`.
|
||||
// +optional
|
||||
Version string `json:"version,omitempty" protobuf:"bytes,2,opt,name=version"`
|
||||
// Names are the names used to describe this custom resource
|
||||
Names CustomResourceDefinitionNames `json:"names" protobuf:"bytes,3,opt,name=names"`
|
||||
// Scope indicates whether this resource is cluster or namespace scoped. Default is namespaced
|
||||
Scope ResourceScope `json:"scope" protobuf:"bytes,4,opt,name=scope,casttype=ResourceScope"`
|
||||
// Validation describes the validation methods for CustomResources
|
||||
// +optional
|
||||
Validation *CustomResourceValidation `json:"validation,omitempty" protobuf:"bytes,5,opt,name=validation"`
|
||||
// Subresources describes the subresources for CustomResources
|
||||
// +optional
|
||||
Subresources *CustomResourceSubresources `json:"subresources,omitempty" protobuf:"bytes,6,opt,name=subresources"`
|
||||
// Versions is the list of all supported versions for this resource.
|
||||
// If Version field is provided, this field is optional.
|
||||
// Validation: All versions must use the same validation schema for now. i.e., top
|
||||
// level Validation field is applied to all of these versions.
|
||||
// Order: The version name will be used to compute the order.
|
||||
// If the version string is "kube-like", it will sort above non "kube-like" version strings, which are ordered
|
||||
// lexicographically. "Kube-like" versions start with a "v", then are followed by a number (the major version),
|
||||
// then optionally the string "alpha" or "beta" and another number (the minor version). These are sorted first
|
||||
// by GA > beta > alpha (where GA is a version with no suffix such as beta or alpha), and then by comparing
|
||||
// major version, then minor version. An example sorted list of versions:
|
||||
// v10, v2, v1, v11beta2, v10beta3, v3beta1, v12alpha1, v11alpha2, foo1, foo10.
|
||||
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 {
|
||||
// Name is the version name, e.g. “v1”, “v2beta1”, etc.
|
||||
Name string `json:"name" protobuf:"bytes,1,opt,name=name"`
|
||||
// Served is a flag enabling/disabling this version from being served via REST APIs
|
||||
Served bool `json:"served" protobuf:"varint,2,opt,name=served"`
|
||||
// Storage flags the version as storage version. There must be exactly one
|
||||
// flagged as storage version.
|
||||
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
|
||||
type CustomResourceDefinitionNames struct {
|
||||
// Plural is the plural name of the resource to serve. It must match the name of the CustomResourceDefinition-registration
|
||||
// too: plural.group and it must be all lowercase.
|
||||
Plural string `json:"plural" protobuf:"bytes,1,opt,name=plural"`
|
||||
// Singular is the singular name of the resource. It must be all lowercase Defaults to lowercased <kind>
|
||||
Singular string `json:"singular,omitempty" protobuf:"bytes,2,opt,name=singular"`
|
||||
// ShortNames are short names for the resource. It must be all lowercase.
|
||||
ShortNames []string `json:"shortNames,omitempty" protobuf:"bytes,3,opt,name=shortNames"`
|
||||
// Kind is the serialized kind of the resource. It is normally CamelCase and singular.
|
||||
Kind string `json:"kind" protobuf:"bytes,4,opt,name=kind"`
|
||||
// ListKind is the serialized kind of the list for this resource. Defaults to <kind>List.
|
||||
ListKind string `json:"listKind,omitempty" protobuf:"bytes,5,opt,name=listKind"`
|
||||
// Categories is a list of grouped resources custom resources belong to (e.g. 'all')
|
||||
// +optional
|
||||
Categories []string `json:"categories,omitempty" protobuf:"bytes,6,rep,name=categories"`
|
||||
}
|
||||
|
||||
// ResourceScope is an enum defining the different scopes available to a custom resource
|
||||
type ResourceScope string
|
||||
|
||||
const (
|
||||
ClusterScoped ResourceScope = "Cluster"
|
||||
NamespaceScoped ResourceScope = "Namespaced"
|
||||
)
|
||||
|
||||
type ConditionStatus string
|
||||
|
||||
// These are valid condition statuses. "ConditionTrue" means a resource is in the condition.
|
||||
// "ConditionFalse" means a resource is not in the condition. "ConditionUnknown" means kubernetes
|
||||
// can't decide if a resource is in the condition or not. In the future, we could add other
|
||||
// intermediate conditions, e.g. ConditionDegraded.
|
||||
const (
|
||||
ConditionTrue ConditionStatus = "True"
|
||||
ConditionFalse ConditionStatus = "False"
|
||||
ConditionUnknown ConditionStatus = "Unknown"
|
||||
)
|
||||
|
||||
// CustomResourceDefinitionConditionType is a valid value for CustomResourceDefinitionCondition.Type
|
||||
type CustomResourceDefinitionConditionType string
|
||||
|
||||
const (
|
||||
// Established means that the resource has become active. A resource is established when all names are
|
||||
// accepted without a conflict for the first time. A resource stays established until deleted, even during
|
||||
// a later NamesAccepted due to changed names. Note that not all names can be changed.
|
||||
Established CustomResourceDefinitionConditionType = "Established"
|
||||
// NamesAccepted means the names chosen for this CustomResourceDefinition do not conflict with others in
|
||||
// the group and are therefore accepted.
|
||||
NamesAccepted CustomResourceDefinitionConditionType = "NamesAccepted"
|
||||
// Terminating means that the CustomResourceDefinition has been deleted and is cleaning up.
|
||||
Terminating CustomResourceDefinitionConditionType = "Terminating"
|
||||
)
|
||||
|
||||
// CustomResourceDefinitionCondition contains details for the current condition of this pod.
|
||||
type CustomResourceDefinitionCondition struct {
|
||||
// Type is the type of the condition.
|
||||
Type CustomResourceDefinitionConditionType `json:"type" protobuf:"bytes,1,opt,name=type,casttype=CustomResourceDefinitionConditionType"`
|
||||
// Status is the status of the condition.
|
||||
// Can be True, False, Unknown.
|
||||
Status ConditionStatus `json:"status" protobuf:"bytes,2,opt,name=status,casttype=ConditionStatus"`
|
||||
// Last time the condition transitioned from one status to another.
|
||||
// +optional
|
||||
LastTransitionTime metav1.Time `json:"lastTransitionTime,omitempty" protobuf:"bytes,3,opt,name=lastTransitionTime"`
|
||||
// Unique, one-word, CamelCase reason for the condition's last transition.
|
||||
// +optional
|
||||
Reason string `json:"reason,omitempty" protobuf:"bytes,4,opt,name=reason"`
|
||||
// Human-readable message indicating details about last transition.
|
||||
// +optional
|
||||
Message string `json:"message,omitempty" protobuf:"bytes,5,opt,name=message"`
|
||||
}
|
||||
|
||||
// CustomResourceDefinitionStatus indicates the state of the CustomResourceDefinition
|
||||
type CustomResourceDefinitionStatus struct {
|
||||
// Conditions indicate state for particular aspects of a CustomResourceDefinition
|
||||
Conditions []CustomResourceDefinitionCondition `json:"conditions" protobuf:"bytes,1,opt,name=conditions"`
|
||||
|
||||
// AcceptedNames are the names that are actually being used to serve discovery
|
||||
// They may be different than the names in spec.
|
||||
AcceptedNames CustomResourceDefinitionNames `json:"acceptedNames" protobuf:"bytes,2,opt,name=acceptedNames"`
|
||||
|
||||
// StoredVersions are all versions of CustomResources that were ever persisted. Tracking these
|
||||
// versions allows a migration path for stored versions in etcd. The field is mutable
|
||||
// so the migration controller can first finish a migration to another version (i.e.
|
||||
// that no old objects are left in the storage), and then remove the rest of the
|
||||
// versions from this list.
|
||||
// None of the versions in this list can be removed from the spec.Versions field.
|
||||
StoredVersions []string `json:"storedVersions" protobuf:"bytes,3,rep,name=storedVersions"`
|
||||
}
|
||||
|
||||
// CustomResourceCleanupFinalizer is the name of the finalizer which will delete instances of
|
||||
// a CustomResourceDefinition
|
||||
const CustomResourceCleanupFinalizer = "customresourcecleanup.apiextensions.k8s.io"
|
||||
|
||||
// +genclient
|
||||
// +genclient:nonNamespaced
|
||||
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
|
||||
|
||||
// CustomResourceDefinition represents a resource that should be exposed on the API server. Its name MUST be in the format
|
||||
// <.spec.name>.<.spec.group>.
|
||||
type CustomResourceDefinition struct {
|
||||
metav1.TypeMeta `json:",inline"`
|
||||
metav1.ObjectMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"`
|
||||
|
||||
// Spec describes how the user wants the resources to appear
|
||||
Spec CustomResourceDefinitionSpec `json:"spec,omitempty" protobuf:"bytes,2,opt,name=spec"`
|
||||
// Status indicates the actual state of the CustomResourceDefinition
|
||||
Status CustomResourceDefinitionStatus `json:"status,omitempty" protobuf:"bytes,3,opt,name=status"`
|
||||
}
|
||||
|
||||
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
|
||||
|
||||
// CustomResourceDefinitionList is a list of CustomResourceDefinition objects.
|
||||
type CustomResourceDefinitionList struct {
|
||||
metav1.TypeMeta `json:",inline"`
|
||||
metav1.ListMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"`
|
||||
|
||||
// Items individual CustomResourceDefinitions
|
||||
Items []CustomResourceDefinition `json:"items" protobuf:"bytes,2,rep,name=items"`
|
||||
}
|
||||
|
||||
// CustomResourceValidation is a list of validation methods for CustomResources.
|
||||
type CustomResourceValidation struct {
|
||||
// OpenAPIV3Schema is the OpenAPI v3 schema to be validated against.
|
||||
OpenAPIV3Schema *JSONSchemaProps `json:"openAPIV3Schema,omitempty" protobuf:"bytes,1,opt,name=openAPIV3Schema"`
|
||||
}
|
||||
|
||||
// CustomResourceSubresources defines the status and scale subresources for CustomResources.
|
||||
type CustomResourceSubresources struct {
|
||||
// Status denotes the status subresource for CustomResources
|
||||
Status *CustomResourceSubresourceStatus `json:"status,omitempty" protobuf:"bytes,1,opt,name=status"`
|
||||
// Scale denotes the scale subresource for CustomResources
|
||||
Scale *CustomResourceSubresourceScale `json:"scale,omitempty" protobuf:"bytes,2,opt,name=scale"`
|
||||
}
|
||||
|
||||
// CustomResourceSubresourceStatus defines how to serve the status subresource for CustomResources.
|
||||
// Status is represented by the `.status` JSON path inside of a CustomResource. When set,
|
||||
// * exposes a /status subresource for the custom resource
|
||||
// * PUT requests to the /status subresource take a custom resource object, and ignore changes to anything except the status stanza
|
||||
// * PUT/POST/PATCH requests to the custom resource ignore changes to the status stanza
|
||||
type CustomResourceSubresourceStatus struct{}
|
||||
|
||||
// CustomResourceSubresourceScale defines how to serve the scale subresource for CustomResources.
|
||||
type CustomResourceSubresourceScale struct {
|
||||
// SpecReplicasPath defines the JSON path inside of a CustomResource that corresponds to Scale.Spec.Replicas.
|
||||
// Only JSON paths without the array notation are allowed.
|
||||
// Must be a JSON Path under .spec.
|
||||
// If there is no value under the given path in the CustomResource, the /scale subresource will return an error on GET.
|
||||
SpecReplicasPath string `json:"specReplicasPath" protobuf:"bytes,1,name=specReplicasPath"`
|
||||
// StatusReplicasPath defines the JSON path inside of a CustomResource that corresponds to Scale.Status.Replicas.
|
||||
// Only JSON paths without the array notation are allowed.
|
||||
// Must be a JSON Path under .status.
|
||||
// If there is no value under the given path in the CustomResource, the status replica value in the /scale subresource
|
||||
// will default to 0.
|
||||
StatusReplicasPath string `json:"statusReplicasPath" protobuf:"bytes,2,opt,name=statusReplicasPath"`
|
||||
// LabelSelectorPath defines the JSON path inside of a CustomResource that corresponds to Scale.Status.Selector.
|
||||
// Only JSON paths without the array notation are allowed.
|
||||
// Must be a JSON Path under .status.
|
||||
// Must be set to work with HPA.
|
||||
// If there is no value under the given path in the CustomResource, the status label selector value in the /scale
|
||||
// subresource will default to the empty string.
|
||||
// +optional
|
||||
LabelSelectorPath *string `json:"labelSelectorPath,omitempty" protobuf:"bytes,3,opt,name=labelSelectorPath"`
|
||||
}
|
||||
150
vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1/types_jsonschema.go
generated
vendored
Normal file
150
vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1/types_jsonschema.go
generated
vendored
Normal file
@@ -0,0 +1,150 @@
|
||||
/*
|
||||
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 v1beta1
|
||||
|
||||
// JSONSchemaProps is a JSON-Schema following Specification Draft 4 (http://json-schema.org/).
|
||||
type JSONSchemaProps struct {
|
||||
ID string `json:"id,omitempty" protobuf:"bytes,1,opt,name=id"`
|
||||
Schema JSONSchemaURL `json:"$schema,omitempty" protobuf:"bytes,2,opt,name=schema"`
|
||||
Ref *string `json:"$ref,omitempty" protobuf:"bytes,3,opt,name=ref"`
|
||||
Description string `json:"description,omitempty" protobuf:"bytes,4,opt,name=description"`
|
||||
Type string `json:"type,omitempty" protobuf:"bytes,5,opt,name=type"`
|
||||
Format string `json:"format,omitempty" protobuf:"bytes,6,opt,name=format"`
|
||||
Title string `json:"title,omitempty" protobuf:"bytes,7,opt,name=title"`
|
||||
Default *JSON `json:"default,omitempty" protobuf:"bytes,8,opt,name=default"`
|
||||
Maximum *float64 `json:"maximum,omitempty" protobuf:"bytes,9,opt,name=maximum"`
|
||||
ExclusiveMaximum bool `json:"exclusiveMaximum,omitempty" protobuf:"bytes,10,opt,name=exclusiveMaximum"`
|
||||
Minimum *float64 `json:"minimum,omitempty" protobuf:"bytes,11,opt,name=minimum"`
|
||||
ExclusiveMinimum bool `json:"exclusiveMinimum,omitempty" protobuf:"bytes,12,opt,name=exclusiveMinimum"`
|
||||
MaxLength *int64 `json:"maxLength,omitempty" protobuf:"bytes,13,opt,name=maxLength"`
|
||||
MinLength *int64 `json:"minLength,omitempty" protobuf:"bytes,14,opt,name=minLength"`
|
||||
Pattern string `json:"pattern,omitempty" protobuf:"bytes,15,opt,name=pattern"`
|
||||
MaxItems *int64 `json:"maxItems,omitempty" protobuf:"bytes,16,opt,name=maxItems"`
|
||||
MinItems *int64 `json:"minItems,omitempty" protobuf:"bytes,17,opt,name=minItems"`
|
||||
UniqueItems bool `json:"uniqueItems,omitempty" protobuf:"bytes,18,opt,name=uniqueItems"`
|
||||
MultipleOf *float64 `json:"multipleOf,omitempty" protobuf:"bytes,19,opt,name=multipleOf"`
|
||||
Enum []JSON `json:"enum,omitempty" protobuf:"bytes,20,rep,name=enum"`
|
||||
MaxProperties *int64 `json:"maxProperties,omitempty" protobuf:"bytes,21,opt,name=maxProperties"`
|
||||
MinProperties *int64 `json:"minProperties,omitempty" protobuf:"bytes,22,opt,name=minProperties"`
|
||||
Required []string `json:"required,omitempty" protobuf:"bytes,23,rep,name=required"`
|
||||
Items *JSONSchemaPropsOrArray `json:"items,omitempty" protobuf:"bytes,24,opt,name=items"`
|
||||
AllOf []JSONSchemaProps `json:"allOf,omitempty" protobuf:"bytes,25,rep,name=allOf"`
|
||||
OneOf []JSONSchemaProps `json:"oneOf,omitempty" protobuf:"bytes,26,rep,name=oneOf"`
|
||||
AnyOf []JSONSchemaProps `json:"anyOf,omitempty" protobuf:"bytes,27,rep,name=anyOf"`
|
||||
Not *JSONSchemaProps `json:"not,omitempty" protobuf:"bytes,28,opt,name=not"`
|
||||
Properties map[string]JSONSchemaProps `json:"properties,omitempty" protobuf:"bytes,29,rep,name=properties"`
|
||||
AdditionalProperties *JSONSchemaPropsOrBool `json:"additionalProperties,omitempty" protobuf:"bytes,30,opt,name=additionalProperties"`
|
||||
PatternProperties map[string]JSONSchemaProps `json:"patternProperties,omitempty" protobuf:"bytes,31,rep,name=patternProperties"`
|
||||
Dependencies JSONSchemaDependencies `json:"dependencies,omitempty" protobuf:"bytes,32,opt,name=dependencies"`
|
||||
AdditionalItems *JSONSchemaPropsOrBool `json:"additionalItems,omitempty" protobuf:"bytes,33,opt,name=additionalItems"`
|
||||
Definitions JSONSchemaDefinitions `json:"definitions,omitempty" protobuf:"bytes,34,opt,name=definitions"`
|
||||
ExternalDocs *ExternalDocumentation `json:"externalDocs,omitempty" protobuf:"bytes,35,opt,name=externalDocs"`
|
||||
Example *JSON `json:"example,omitempty" protobuf:"bytes,36,opt,name=example"`
|
||||
}
|
||||
|
||||
// JSON represents any valid JSON value.
|
||||
// These types are supported: bool, int64, float64, string, []interface{}, map[string]interface{} and nil.
|
||||
type JSON struct {
|
||||
Raw []byte `protobuf:"bytes,1,opt,name=raw"`
|
||||
}
|
||||
|
||||
// OpenAPISchemaType is used by the kube-openapi generator when constructing
|
||||
// the OpenAPI spec of this type.
|
||||
//
|
||||
// See: https://github.com/kubernetes/kube-openapi/tree/master/pkg/generators
|
||||
func (_ JSON) OpenAPISchemaType() []string {
|
||||
// TODO: return actual types when anyOf is supported
|
||||
return []string{}
|
||||
}
|
||||
|
||||
// OpenAPISchemaFormat is used by the kube-openapi generator when constructing
|
||||
// the OpenAPI spec of this type.
|
||||
func (_ JSON) OpenAPISchemaFormat() string { return "" }
|
||||
|
||||
// JSONSchemaURL represents a schema url.
|
||||
type JSONSchemaURL string
|
||||
|
||||
// JSONSchemaPropsOrArray represents a value that can either be a JSONSchemaProps
|
||||
// or an array of JSONSchemaProps. Mainly here for serialization purposes.
|
||||
type JSONSchemaPropsOrArray struct {
|
||||
Schema *JSONSchemaProps `protobuf:"bytes,1,opt,name=schema"`
|
||||
JSONSchemas []JSONSchemaProps `protobuf:"bytes,2,rep,name=jSONSchemas"`
|
||||
}
|
||||
|
||||
// OpenAPISchemaType is used by the kube-openapi generator when constructing
|
||||
// the OpenAPI spec of this type.
|
||||
//
|
||||
// See: https://github.com/kubernetes/kube-openapi/tree/master/pkg/generators
|
||||
func (_ JSONSchemaPropsOrArray) OpenAPISchemaType() []string {
|
||||
// TODO: return actual types when anyOf is supported
|
||||
return []string{}
|
||||
}
|
||||
|
||||
// OpenAPISchemaFormat is used by the kube-openapi generator when constructing
|
||||
// the OpenAPI spec of this type.
|
||||
func (_ JSONSchemaPropsOrArray) OpenAPISchemaFormat() string { return "" }
|
||||
|
||||
// JSONSchemaPropsOrBool represents JSONSchemaProps or a boolean value.
|
||||
// Defaults to true for the boolean property.
|
||||
type JSONSchemaPropsOrBool struct {
|
||||
Allows bool `protobuf:"varint,1,opt,name=allows"`
|
||||
Schema *JSONSchemaProps `protobuf:"bytes,2,opt,name=schema"`
|
||||
}
|
||||
|
||||
// OpenAPISchemaType is used by the kube-openapi generator when constructing
|
||||
// the OpenAPI spec of this type.
|
||||
//
|
||||
// See: https://github.com/kubernetes/kube-openapi/tree/master/pkg/generators
|
||||
func (_ JSONSchemaPropsOrBool) OpenAPISchemaType() []string {
|
||||
// TODO: return actual types when anyOf is supported
|
||||
return []string{}
|
||||
}
|
||||
|
||||
// OpenAPISchemaFormat is used by the kube-openapi generator when constructing
|
||||
// the OpenAPI spec of this type.
|
||||
func (_ JSONSchemaPropsOrBool) OpenAPISchemaFormat() string { return "" }
|
||||
|
||||
// JSONSchemaDependencies represent a dependencies property.
|
||||
type JSONSchemaDependencies map[string]JSONSchemaPropsOrStringArray
|
||||
|
||||
// JSONSchemaPropsOrStringArray represents a JSONSchemaProps or a string array.
|
||||
type JSONSchemaPropsOrStringArray struct {
|
||||
Schema *JSONSchemaProps `protobuf:"bytes,1,opt,name=schema"`
|
||||
Property []string `protobuf:"bytes,2,rep,name=property"`
|
||||
}
|
||||
|
||||
// OpenAPISchemaType is used by the kube-openapi generator when constructing
|
||||
// the OpenAPI spec of this type.
|
||||
//
|
||||
// See: https://github.com/kubernetes/kube-openapi/tree/master/pkg/generators
|
||||
func (_ JSONSchemaPropsOrStringArray) OpenAPISchemaType() []string {
|
||||
// TODO: return actual types when anyOf is supported
|
||||
return []string{}
|
||||
}
|
||||
|
||||
// OpenAPISchemaFormat is used by the kube-openapi generator when constructing
|
||||
// the OpenAPI spec of this type.
|
||||
func (_ JSONSchemaPropsOrStringArray) OpenAPISchemaFormat() string { return "" }
|
||||
|
||||
// JSONSchemaDefinitions contains the models explicitly defined in this spec.
|
||||
type JSONSchemaDefinitions map[string]JSONSchemaProps
|
||||
|
||||
// ExternalDocumentation allows referencing an external resource for extended documentation.
|
||||
type ExternalDocumentation struct {
|
||||
Description string `json:"description,omitempty" protobuf:"bytes,1,opt,name=description"`
|
||||
URL string `json:"url,omitempty" protobuf:"bytes,2,opt,name=url"`
|
||||
}
|
||||
967
vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1/zz_generated.conversion.go
generated
vendored
Normal file
967
vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1/zz_generated.conversion.go
generated
vendored
Normal file
@@ -0,0 +1,967 @@
|
||||
// +build !ignore_autogenerated
|
||||
|
||||
/*
|
||||
Copyright 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.
|
||||
*/
|
||||
|
||||
// Code generated by conversion-gen. DO NOT EDIT.
|
||||
|
||||
package v1beta1
|
||||
|
||||
import (
|
||||
unsafe "unsafe"
|
||||
|
||||
apiextensions "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions"
|
||||
conversion "k8s.io/apimachinery/pkg/conversion"
|
||||
runtime "k8s.io/apimachinery/pkg/runtime"
|
||||
)
|
||||
|
||||
func init() {
|
||||
localSchemeBuilder.Register(RegisterConversions)
|
||||
}
|
||||
|
||||
// RegisterConversions adds conversion functions to the given scheme.
|
||||
// Public to allow building arbitrary schemes.
|
||||
func RegisterConversions(scheme *runtime.Scheme) error {
|
||||
return scheme.AddGeneratedConversionFuncs(
|
||||
Convert_v1beta1_CustomResourceColumnDefinition_To_apiextensions_CustomResourceColumnDefinition,
|
||||
Convert_apiextensions_CustomResourceColumnDefinition_To_v1beta1_CustomResourceColumnDefinition,
|
||||
Convert_v1beta1_CustomResourceDefinition_To_apiextensions_CustomResourceDefinition,
|
||||
Convert_apiextensions_CustomResourceDefinition_To_v1beta1_CustomResourceDefinition,
|
||||
Convert_v1beta1_CustomResourceDefinitionCondition_To_apiextensions_CustomResourceDefinitionCondition,
|
||||
Convert_apiextensions_CustomResourceDefinitionCondition_To_v1beta1_CustomResourceDefinitionCondition,
|
||||
Convert_v1beta1_CustomResourceDefinitionList_To_apiextensions_CustomResourceDefinitionList,
|
||||
Convert_apiextensions_CustomResourceDefinitionList_To_v1beta1_CustomResourceDefinitionList,
|
||||
Convert_v1beta1_CustomResourceDefinitionNames_To_apiextensions_CustomResourceDefinitionNames,
|
||||
Convert_apiextensions_CustomResourceDefinitionNames_To_v1beta1_CustomResourceDefinitionNames,
|
||||
Convert_v1beta1_CustomResourceDefinitionSpec_To_apiextensions_CustomResourceDefinitionSpec,
|
||||
Convert_apiextensions_CustomResourceDefinitionSpec_To_v1beta1_CustomResourceDefinitionSpec,
|
||||
Convert_v1beta1_CustomResourceDefinitionStatus_To_apiextensions_CustomResourceDefinitionStatus,
|
||||
Convert_apiextensions_CustomResourceDefinitionStatus_To_v1beta1_CustomResourceDefinitionStatus,
|
||||
Convert_v1beta1_CustomResourceDefinitionVersion_To_apiextensions_CustomResourceDefinitionVersion,
|
||||
Convert_apiextensions_CustomResourceDefinitionVersion_To_v1beta1_CustomResourceDefinitionVersion,
|
||||
Convert_v1beta1_CustomResourceSubresourceScale_To_apiextensions_CustomResourceSubresourceScale,
|
||||
Convert_apiextensions_CustomResourceSubresourceScale_To_v1beta1_CustomResourceSubresourceScale,
|
||||
Convert_v1beta1_CustomResourceSubresourceStatus_To_apiextensions_CustomResourceSubresourceStatus,
|
||||
Convert_apiextensions_CustomResourceSubresourceStatus_To_v1beta1_CustomResourceSubresourceStatus,
|
||||
Convert_v1beta1_CustomResourceSubresources_To_apiextensions_CustomResourceSubresources,
|
||||
Convert_apiextensions_CustomResourceSubresources_To_v1beta1_CustomResourceSubresources,
|
||||
Convert_v1beta1_CustomResourceValidation_To_apiextensions_CustomResourceValidation,
|
||||
Convert_apiextensions_CustomResourceValidation_To_v1beta1_CustomResourceValidation,
|
||||
Convert_v1beta1_ExternalDocumentation_To_apiextensions_ExternalDocumentation,
|
||||
Convert_apiextensions_ExternalDocumentation_To_v1beta1_ExternalDocumentation,
|
||||
Convert_v1beta1_JSON_To_apiextensions_JSON,
|
||||
Convert_apiextensions_JSON_To_v1beta1_JSON,
|
||||
Convert_v1beta1_JSONSchemaProps_To_apiextensions_JSONSchemaProps,
|
||||
Convert_apiextensions_JSONSchemaProps_To_v1beta1_JSONSchemaProps,
|
||||
Convert_v1beta1_JSONSchemaPropsOrArray_To_apiextensions_JSONSchemaPropsOrArray,
|
||||
Convert_apiextensions_JSONSchemaPropsOrArray_To_v1beta1_JSONSchemaPropsOrArray,
|
||||
Convert_v1beta1_JSONSchemaPropsOrBool_To_apiextensions_JSONSchemaPropsOrBool,
|
||||
Convert_apiextensions_JSONSchemaPropsOrBool_To_v1beta1_JSONSchemaPropsOrBool,
|
||||
Convert_v1beta1_JSONSchemaPropsOrStringArray_To_apiextensions_JSONSchemaPropsOrStringArray,
|
||||
Convert_apiextensions_JSONSchemaPropsOrStringArray_To_v1beta1_JSONSchemaPropsOrStringArray,
|
||||
)
|
||||
}
|
||||
|
||||
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 {
|
||||
out.ObjectMeta = in.ObjectMeta
|
||||
if err := Convert_v1beta1_CustomResourceDefinitionSpec_To_apiextensions_CustomResourceDefinitionSpec(&in.Spec, &out.Spec, s); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := Convert_v1beta1_CustomResourceDefinitionStatus_To_apiextensions_CustomResourceDefinitionStatus(&in.Status, &out.Status, s); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_v1beta1_CustomResourceDefinition_To_apiextensions_CustomResourceDefinition is an autogenerated conversion function.
|
||||
func Convert_v1beta1_CustomResourceDefinition_To_apiextensions_CustomResourceDefinition(in *CustomResourceDefinition, out *apiextensions.CustomResourceDefinition, s conversion.Scope) error {
|
||||
return autoConvert_v1beta1_CustomResourceDefinition_To_apiextensions_CustomResourceDefinition(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_apiextensions_CustomResourceDefinition_To_v1beta1_CustomResourceDefinition(in *apiextensions.CustomResourceDefinition, out *CustomResourceDefinition, s conversion.Scope) error {
|
||||
out.ObjectMeta = in.ObjectMeta
|
||||
if err := Convert_apiextensions_CustomResourceDefinitionSpec_To_v1beta1_CustomResourceDefinitionSpec(&in.Spec, &out.Spec, s); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := Convert_apiextensions_CustomResourceDefinitionStatus_To_v1beta1_CustomResourceDefinitionStatus(&in.Status, &out.Status, s); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_apiextensions_CustomResourceDefinition_To_v1beta1_CustomResourceDefinition is an autogenerated conversion function.
|
||||
func Convert_apiextensions_CustomResourceDefinition_To_v1beta1_CustomResourceDefinition(in *apiextensions.CustomResourceDefinition, out *CustomResourceDefinition, s conversion.Scope) error {
|
||||
return autoConvert_apiextensions_CustomResourceDefinition_To_v1beta1_CustomResourceDefinition(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_v1beta1_CustomResourceDefinitionCondition_To_apiextensions_CustomResourceDefinitionCondition(in *CustomResourceDefinitionCondition, out *apiextensions.CustomResourceDefinitionCondition, s conversion.Scope) error {
|
||||
out.Type = apiextensions.CustomResourceDefinitionConditionType(in.Type)
|
||||
out.Status = apiextensions.ConditionStatus(in.Status)
|
||||
out.LastTransitionTime = in.LastTransitionTime
|
||||
out.Reason = in.Reason
|
||||
out.Message = in.Message
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_v1beta1_CustomResourceDefinitionCondition_To_apiextensions_CustomResourceDefinitionCondition is an autogenerated conversion function.
|
||||
func Convert_v1beta1_CustomResourceDefinitionCondition_To_apiextensions_CustomResourceDefinitionCondition(in *CustomResourceDefinitionCondition, out *apiextensions.CustomResourceDefinitionCondition, s conversion.Scope) error {
|
||||
return autoConvert_v1beta1_CustomResourceDefinitionCondition_To_apiextensions_CustomResourceDefinitionCondition(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_apiextensions_CustomResourceDefinitionCondition_To_v1beta1_CustomResourceDefinitionCondition(in *apiextensions.CustomResourceDefinitionCondition, out *CustomResourceDefinitionCondition, s conversion.Scope) error {
|
||||
out.Type = CustomResourceDefinitionConditionType(in.Type)
|
||||
out.Status = ConditionStatus(in.Status)
|
||||
out.LastTransitionTime = in.LastTransitionTime
|
||||
out.Reason = in.Reason
|
||||
out.Message = in.Message
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_apiextensions_CustomResourceDefinitionCondition_To_v1beta1_CustomResourceDefinitionCondition is an autogenerated conversion function.
|
||||
func Convert_apiextensions_CustomResourceDefinitionCondition_To_v1beta1_CustomResourceDefinitionCondition(in *apiextensions.CustomResourceDefinitionCondition, out *CustomResourceDefinitionCondition, s conversion.Scope) error {
|
||||
return autoConvert_apiextensions_CustomResourceDefinitionCondition_To_v1beta1_CustomResourceDefinitionCondition(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_v1beta1_CustomResourceDefinitionList_To_apiextensions_CustomResourceDefinitionList(in *CustomResourceDefinitionList, out *apiextensions.CustomResourceDefinitionList, s conversion.Scope) error {
|
||||
out.ListMeta = in.ListMeta
|
||||
if in.Items != nil {
|
||||
in, out := &in.Items, &out.Items
|
||||
*out = make([]apiextensions.CustomResourceDefinition, len(*in))
|
||||
for i := range *in {
|
||||
if err := Convert_v1beta1_CustomResourceDefinition_To_apiextensions_CustomResourceDefinition(&(*in)[i], &(*out)[i], s); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
} else {
|
||||
out.Items = nil
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_v1beta1_CustomResourceDefinitionList_To_apiextensions_CustomResourceDefinitionList is an autogenerated conversion function.
|
||||
func Convert_v1beta1_CustomResourceDefinitionList_To_apiextensions_CustomResourceDefinitionList(in *CustomResourceDefinitionList, out *apiextensions.CustomResourceDefinitionList, s conversion.Scope) error {
|
||||
return autoConvert_v1beta1_CustomResourceDefinitionList_To_apiextensions_CustomResourceDefinitionList(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_apiextensions_CustomResourceDefinitionList_To_v1beta1_CustomResourceDefinitionList(in *apiextensions.CustomResourceDefinitionList, out *CustomResourceDefinitionList, s conversion.Scope) error {
|
||||
out.ListMeta = in.ListMeta
|
||||
if in.Items != nil {
|
||||
in, out := &in.Items, &out.Items
|
||||
*out = make([]CustomResourceDefinition, len(*in))
|
||||
for i := range *in {
|
||||
if err := Convert_apiextensions_CustomResourceDefinition_To_v1beta1_CustomResourceDefinition(&(*in)[i], &(*out)[i], s); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
} else {
|
||||
out.Items = nil
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_apiextensions_CustomResourceDefinitionList_To_v1beta1_CustomResourceDefinitionList is an autogenerated conversion function.
|
||||
func Convert_apiextensions_CustomResourceDefinitionList_To_v1beta1_CustomResourceDefinitionList(in *apiextensions.CustomResourceDefinitionList, out *CustomResourceDefinitionList, s conversion.Scope) error {
|
||||
return autoConvert_apiextensions_CustomResourceDefinitionList_To_v1beta1_CustomResourceDefinitionList(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_v1beta1_CustomResourceDefinitionNames_To_apiextensions_CustomResourceDefinitionNames(in *CustomResourceDefinitionNames, out *apiextensions.CustomResourceDefinitionNames, s conversion.Scope) error {
|
||||
out.Plural = in.Plural
|
||||
out.Singular = in.Singular
|
||||
out.ShortNames = *(*[]string)(unsafe.Pointer(&in.ShortNames))
|
||||
out.Kind = in.Kind
|
||||
out.ListKind = in.ListKind
|
||||
out.Categories = *(*[]string)(unsafe.Pointer(&in.Categories))
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_v1beta1_CustomResourceDefinitionNames_To_apiextensions_CustomResourceDefinitionNames is an autogenerated conversion function.
|
||||
func Convert_v1beta1_CustomResourceDefinitionNames_To_apiextensions_CustomResourceDefinitionNames(in *CustomResourceDefinitionNames, out *apiextensions.CustomResourceDefinitionNames, s conversion.Scope) error {
|
||||
return autoConvert_v1beta1_CustomResourceDefinitionNames_To_apiextensions_CustomResourceDefinitionNames(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_apiextensions_CustomResourceDefinitionNames_To_v1beta1_CustomResourceDefinitionNames(in *apiextensions.CustomResourceDefinitionNames, out *CustomResourceDefinitionNames, s conversion.Scope) error {
|
||||
out.Plural = in.Plural
|
||||
out.Singular = in.Singular
|
||||
out.ShortNames = *(*[]string)(unsafe.Pointer(&in.ShortNames))
|
||||
out.Kind = in.Kind
|
||||
out.ListKind = in.ListKind
|
||||
out.Categories = *(*[]string)(unsafe.Pointer(&in.Categories))
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_apiextensions_CustomResourceDefinitionNames_To_v1beta1_CustomResourceDefinitionNames is an autogenerated conversion function.
|
||||
func Convert_apiextensions_CustomResourceDefinitionNames_To_v1beta1_CustomResourceDefinitionNames(in *apiextensions.CustomResourceDefinitionNames, out *CustomResourceDefinitionNames, s conversion.Scope) error {
|
||||
return autoConvert_apiextensions_CustomResourceDefinitionNames_To_v1beta1_CustomResourceDefinitionNames(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_v1beta1_CustomResourceDefinitionSpec_To_apiextensions_CustomResourceDefinitionSpec(in *CustomResourceDefinitionSpec, out *apiextensions.CustomResourceDefinitionSpec, s conversion.Scope) error {
|
||||
out.Group = in.Group
|
||||
out.Version = in.Version
|
||||
if err := Convert_v1beta1_CustomResourceDefinitionNames_To_apiextensions_CustomResourceDefinitionNames(&in.Names, &out.Names, s); err != nil {
|
||||
return err
|
||||
}
|
||||
out.Scope = apiextensions.ResourceScope(in.Scope)
|
||||
if in.Validation != nil {
|
||||
in, out := &in.Validation, &out.Validation
|
||||
*out = new(apiextensions.CustomResourceValidation)
|
||||
if err := Convert_v1beta1_CustomResourceValidation_To_apiextensions_CustomResourceValidation(*in, *out, s); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
out.Validation = nil
|
||||
}
|
||||
out.Subresources = (*apiextensions.CustomResourceSubresources)(unsafe.Pointer(in.Subresources))
|
||||
out.Versions = *(*[]apiextensions.CustomResourceDefinitionVersion)(unsafe.Pointer(&in.Versions))
|
||||
out.AdditionalPrinterColumns = *(*[]apiextensions.CustomResourceColumnDefinition)(unsafe.Pointer(&in.AdditionalPrinterColumns))
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_v1beta1_CustomResourceDefinitionSpec_To_apiextensions_CustomResourceDefinitionSpec is an autogenerated conversion function.
|
||||
func Convert_v1beta1_CustomResourceDefinitionSpec_To_apiextensions_CustomResourceDefinitionSpec(in *CustomResourceDefinitionSpec, out *apiextensions.CustomResourceDefinitionSpec, s conversion.Scope) error {
|
||||
return autoConvert_v1beta1_CustomResourceDefinitionSpec_To_apiextensions_CustomResourceDefinitionSpec(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_apiextensions_CustomResourceDefinitionSpec_To_v1beta1_CustomResourceDefinitionSpec(in *apiextensions.CustomResourceDefinitionSpec, out *CustomResourceDefinitionSpec, s conversion.Scope) error {
|
||||
out.Group = in.Group
|
||||
out.Version = in.Version
|
||||
if err := Convert_apiextensions_CustomResourceDefinitionNames_To_v1beta1_CustomResourceDefinitionNames(&in.Names, &out.Names, s); err != nil {
|
||||
return err
|
||||
}
|
||||
out.Scope = ResourceScope(in.Scope)
|
||||
if in.Validation != nil {
|
||||
in, out := &in.Validation, &out.Validation
|
||||
*out = new(CustomResourceValidation)
|
||||
if err := Convert_apiextensions_CustomResourceValidation_To_v1beta1_CustomResourceValidation(*in, *out, s); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
out.Validation = nil
|
||||
}
|
||||
out.Subresources = (*CustomResourceSubresources)(unsafe.Pointer(in.Subresources))
|
||||
out.Versions = *(*[]CustomResourceDefinitionVersion)(unsafe.Pointer(&in.Versions))
|
||||
out.AdditionalPrinterColumns = *(*[]CustomResourceColumnDefinition)(unsafe.Pointer(&in.AdditionalPrinterColumns))
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_apiextensions_CustomResourceDefinitionSpec_To_v1beta1_CustomResourceDefinitionSpec is an autogenerated conversion function.
|
||||
func Convert_apiextensions_CustomResourceDefinitionSpec_To_v1beta1_CustomResourceDefinitionSpec(in *apiextensions.CustomResourceDefinitionSpec, out *CustomResourceDefinitionSpec, s conversion.Scope) error {
|
||||
return autoConvert_apiextensions_CustomResourceDefinitionSpec_To_v1beta1_CustomResourceDefinitionSpec(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_v1beta1_CustomResourceDefinitionStatus_To_apiextensions_CustomResourceDefinitionStatus(in *CustomResourceDefinitionStatus, out *apiextensions.CustomResourceDefinitionStatus, s conversion.Scope) error {
|
||||
out.Conditions = *(*[]apiextensions.CustomResourceDefinitionCondition)(unsafe.Pointer(&in.Conditions))
|
||||
if err := Convert_v1beta1_CustomResourceDefinitionNames_To_apiextensions_CustomResourceDefinitionNames(&in.AcceptedNames, &out.AcceptedNames, s); err != nil {
|
||||
return err
|
||||
}
|
||||
out.StoredVersions = *(*[]string)(unsafe.Pointer(&in.StoredVersions))
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_v1beta1_CustomResourceDefinitionStatus_To_apiextensions_CustomResourceDefinitionStatus is an autogenerated conversion function.
|
||||
func Convert_v1beta1_CustomResourceDefinitionStatus_To_apiextensions_CustomResourceDefinitionStatus(in *CustomResourceDefinitionStatus, out *apiextensions.CustomResourceDefinitionStatus, s conversion.Scope) error {
|
||||
return autoConvert_v1beta1_CustomResourceDefinitionStatus_To_apiextensions_CustomResourceDefinitionStatus(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_apiextensions_CustomResourceDefinitionStatus_To_v1beta1_CustomResourceDefinitionStatus(in *apiextensions.CustomResourceDefinitionStatus, out *CustomResourceDefinitionStatus, s conversion.Scope) error {
|
||||
out.Conditions = *(*[]CustomResourceDefinitionCondition)(unsafe.Pointer(&in.Conditions))
|
||||
if err := Convert_apiextensions_CustomResourceDefinitionNames_To_v1beta1_CustomResourceDefinitionNames(&in.AcceptedNames, &out.AcceptedNames, s); err != nil {
|
||||
return err
|
||||
}
|
||||
out.StoredVersions = *(*[]string)(unsafe.Pointer(&in.StoredVersions))
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_apiextensions_CustomResourceDefinitionStatus_To_v1beta1_CustomResourceDefinitionStatus is an autogenerated conversion function.
|
||||
func Convert_apiextensions_CustomResourceDefinitionStatus_To_v1beta1_CustomResourceDefinitionStatus(in *apiextensions.CustomResourceDefinitionStatus, out *CustomResourceDefinitionStatus, s conversion.Scope) error {
|
||||
return autoConvert_apiextensions_CustomResourceDefinitionStatus_To_v1beta1_CustomResourceDefinitionStatus(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_v1beta1_CustomResourceDefinitionVersion_To_apiextensions_CustomResourceDefinitionVersion(in *CustomResourceDefinitionVersion, out *apiextensions.CustomResourceDefinitionVersion, s conversion.Scope) error {
|
||||
out.Name = in.Name
|
||||
out.Served = in.Served
|
||||
out.Storage = in.Storage
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_v1beta1_CustomResourceDefinitionVersion_To_apiextensions_CustomResourceDefinitionVersion is an autogenerated conversion function.
|
||||
func Convert_v1beta1_CustomResourceDefinitionVersion_To_apiextensions_CustomResourceDefinitionVersion(in *CustomResourceDefinitionVersion, out *apiextensions.CustomResourceDefinitionVersion, s conversion.Scope) error {
|
||||
return autoConvert_v1beta1_CustomResourceDefinitionVersion_To_apiextensions_CustomResourceDefinitionVersion(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_apiextensions_CustomResourceDefinitionVersion_To_v1beta1_CustomResourceDefinitionVersion(in *apiextensions.CustomResourceDefinitionVersion, out *CustomResourceDefinitionVersion, s conversion.Scope) error {
|
||||
out.Name = in.Name
|
||||
out.Served = in.Served
|
||||
out.Storage = in.Storage
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_apiextensions_CustomResourceDefinitionVersion_To_v1beta1_CustomResourceDefinitionVersion is an autogenerated conversion function.
|
||||
func Convert_apiextensions_CustomResourceDefinitionVersion_To_v1beta1_CustomResourceDefinitionVersion(in *apiextensions.CustomResourceDefinitionVersion, out *CustomResourceDefinitionVersion, s conversion.Scope) error {
|
||||
return autoConvert_apiextensions_CustomResourceDefinitionVersion_To_v1beta1_CustomResourceDefinitionVersion(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_v1beta1_CustomResourceSubresourceScale_To_apiextensions_CustomResourceSubresourceScale(in *CustomResourceSubresourceScale, out *apiextensions.CustomResourceSubresourceScale, s conversion.Scope) error {
|
||||
out.SpecReplicasPath = in.SpecReplicasPath
|
||||
out.StatusReplicasPath = in.StatusReplicasPath
|
||||
out.LabelSelectorPath = (*string)(unsafe.Pointer(in.LabelSelectorPath))
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_v1beta1_CustomResourceSubresourceScale_To_apiextensions_CustomResourceSubresourceScale is an autogenerated conversion function.
|
||||
func Convert_v1beta1_CustomResourceSubresourceScale_To_apiextensions_CustomResourceSubresourceScale(in *CustomResourceSubresourceScale, out *apiextensions.CustomResourceSubresourceScale, s conversion.Scope) error {
|
||||
return autoConvert_v1beta1_CustomResourceSubresourceScale_To_apiextensions_CustomResourceSubresourceScale(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_apiextensions_CustomResourceSubresourceScale_To_v1beta1_CustomResourceSubresourceScale(in *apiextensions.CustomResourceSubresourceScale, out *CustomResourceSubresourceScale, s conversion.Scope) error {
|
||||
out.SpecReplicasPath = in.SpecReplicasPath
|
||||
out.StatusReplicasPath = in.StatusReplicasPath
|
||||
out.LabelSelectorPath = (*string)(unsafe.Pointer(in.LabelSelectorPath))
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_apiextensions_CustomResourceSubresourceScale_To_v1beta1_CustomResourceSubresourceScale is an autogenerated conversion function.
|
||||
func Convert_apiextensions_CustomResourceSubresourceScale_To_v1beta1_CustomResourceSubresourceScale(in *apiextensions.CustomResourceSubresourceScale, out *CustomResourceSubresourceScale, s conversion.Scope) error {
|
||||
return autoConvert_apiextensions_CustomResourceSubresourceScale_To_v1beta1_CustomResourceSubresourceScale(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_v1beta1_CustomResourceSubresourceStatus_To_apiextensions_CustomResourceSubresourceStatus(in *CustomResourceSubresourceStatus, out *apiextensions.CustomResourceSubresourceStatus, s conversion.Scope) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_v1beta1_CustomResourceSubresourceStatus_To_apiextensions_CustomResourceSubresourceStatus is an autogenerated conversion function.
|
||||
func Convert_v1beta1_CustomResourceSubresourceStatus_To_apiextensions_CustomResourceSubresourceStatus(in *CustomResourceSubresourceStatus, out *apiextensions.CustomResourceSubresourceStatus, s conversion.Scope) error {
|
||||
return autoConvert_v1beta1_CustomResourceSubresourceStatus_To_apiextensions_CustomResourceSubresourceStatus(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_apiextensions_CustomResourceSubresourceStatus_To_v1beta1_CustomResourceSubresourceStatus(in *apiextensions.CustomResourceSubresourceStatus, out *CustomResourceSubresourceStatus, s conversion.Scope) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_apiextensions_CustomResourceSubresourceStatus_To_v1beta1_CustomResourceSubresourceStatus is an autogenerated conversion function.
|
||||
func Convert_apiextensions_CustomResourceSubresourceStatus_To_v1beta1_CustomResourceSubresourceStatus(in *apiextensions.CustomResourceSubresourceStatus, out *CustomResourceSubresourceStatus, s conversion.Scope) error {
|
||||
return autoConvert_apiextensions_CustomResourceSubresourceStatus_To_v1beta1_CustomResourceSubresourceStatus(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_v1beta1_CustomResourceSubresources_To_apiextensions_CustomResourceSubresources(in *CustomResourceSubresources, out *apiextensions.CustomResourceSubresources, s conversion.Scope) error {
|
||||
out.Status = (*apiextensions.CustomResourceSubresourceStatus)(unsafe.Pointer(in.Status))
|
||||
out.Scale = (*apiextensions.CustomResourceSubresourceScale)(unsafe.Pointer(in.Scale))
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_v1beta1_CustomResourceSubresources_To_apiextensions_CustomResourceSubresources is an autogenerated conversion function.
|
||||
func Convert_v1beta1_CustomResourceSubresources_To_apiextensions_CustomResourceSubresources(in *CustomResourceSubresources, out *apiextensions.CustomResourceSubresources, s conversion.Scope) error {
|
||||
return autoConvert_v1beta1_CustomResourceSubresources_To_apiextensions_CustomResourceSubresources(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_apiextensions_CustomResourceSubresources_To_v1beta1_CustomResourceSubresources(in *apiextensions.CustomResourceSubresources, out *CustomResourceSubresources, s conversion.Scope) error {
|
||||
out.Status = (*CustomResourceSubresourceStatus)(unsafe.Pointer(in.Status))
|
||||
out.Scale = (*CustomResourceSubresourceScale)(unsafe.Pointer(in.Scale))
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_apiextensions_CustomResourceSubresources_To_v1beta1_CustomResourceSubresources is an autogenerated conversion function.
|
||||
func Convert_apiextensions_CustomResourceSubresources_To_v1beta1_CustomResourceSubresources(in *apiextensions.CustomResourceSubresources, out *CustomResourceSubresources, s conversion.Scope) error {
|
||||
return autoConvert_apiextensions_CustomResourceSubresources_To_v1beta1_CustomResourceSubresources(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_v1beta1_CustomResourceValidation_To_apiextensions_CustomResourceValidation(in *CustomResourceValidation, out *apiextensions.CustomResourceValidation, s conversion.Scope) error {
|
||||
if in.OpenAPIV3Schema != nil {
|
||||
in, out := &in.OpenAPIV3Schema, &out.OpenAPIV3Schema
|
||||
*out = new(apiextensions.JSONSchemaProps)
|
||||
if err := Convert_v1beta1_JSONSchemaProps_To_apiextensions_JSONSchemaProps(*in, *out, s); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
out.OpenAPIV3Schema = nil
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_v1beta1_CustomResourceValidation_To_apiextensions_CustomResourceValidation is an autogenerated conversion function.
|
||||
func Convert_v1beta1_CustomResourceValidation_To_apiextensions_CustomResourceValidation(in *CustomResourceValidation, out *apiextensions.CustomResourceValidation, s conversion.Scope) error {
|
||||
return autoConvert_v1beta1_CustomResourceValidation_To_apiextensions_CustomResourceValidation(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_apiextensions_CustomResourceValidation_To_v1beta1_CustomResourceValidation(in *apiextensions.CustomResourceValidation, out *CustomResourceValidation, s conversion.Scope) error {
|
||||
if in.OpenAPIV3Schema != nil {
|
||||
in, out := &in.OpenAPIV3Schema, &out.OpenAPIV3Schema
|
||||
*out = new(JSONSchemaProps)
|
||||
if err := Convert_apiextensions_JSONSchemaProps_To_v1beta1_JSONSchemaProps(*in, *out, s); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
out.OpenAPIV3Schema = nil
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_apiextensions_CustomResourceValidation_To_v1beta1_CustomResourceValidation is an autogenerated conversion function.
|
||||
func Convert_apiextensions_CustomResourceValidation_To_v1beta1_CustomResourceValidation(in *apiextensions.CustomResourceValidation, out *CustomResourceValidation, s conversion.Scope) error {
|
||||
return autoConvert_apiextensions_CustomResourceValidation_To_v1beta1_CustomResourceValidation(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_v1beta1_ExternalDocumentation_To_apiextensions_ExternalDocumentation(in *ExternalDocumentation, out *apiextensions.ExternalDocumentation, s conversion.Scope) error {
|
||||
out.Description = in.Description
|
||||
out.URL = in.URL
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_v1beta1_ExternalDocumentation_To_apiextensions_ExternalDocumentation is an autogenerated conversion function.
|
||||
func Convert_v1beta1_ExternalDocumentation_To_apiextensions_ExternalDocumentation(in *ExternalDocumentation, out *apiextensions.ExternalDocumentation, s conversion.Scope) error {
|
||||
return autoConvert_v1beta1_ExternalDocumentation_To_apiextensions_ExternalDocumentation(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_apiextensions_ExternalDocumentation_To_v1beta1_ExternalDocumentation(in *apiextensions.ExternalDocumentation, out *ExternalDocumentation, s conversion.Scope) error {
|
||||
out.Description = in.Description
|
||||
out.URL = in.URL
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_apiextensions_ExternalDocumentation_To_v1beta1_ExternalDocumentation is an autogenerated conversion function.
|
||||
func Convert_apiextensions_ExternalDocumentation_To_v1beta1_ExternalDocumentation(in *apiextensions.ExternalDocumentation, out *ExternalDocumentation, s conversion.Scope) error {
|
||||
return autoConvert_apiextensions_ExternalDocumentation_To_v1beta1_ExternalDocumentation(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_v1beta1_JSON_To_apiextensions_JSON(in *JSON, out *apiextensions.JSON, s conversion.Scope) error {
|
||||
// WARNING: in.Raw requires manual conversion: does not exist in peer-type
|
||||
return nil
|
||||
}
|
||||
|
||||
func autoConvert_apiextensions_JSON_To_v1beta1_JSON(in *apiextensions.JSON, out *JSON, s conversion.Scope) error {
|
||||
// FIXME: Type apiextensions.JSON is unsupported.
|
||||
return nil
|
||||
}
|
||||
|
||||
func autoConvert_v1beta1_JSONSchemaProps_To_apiextensions_JSONSchemaProps(in *JSONSchemaProps, out *apiextensions.JSONSchemaProps, s conversion.Scope) error {
|
||||
out.ID = in.ID
|
||||
out.Schema = apiextensions.JSONSchemaURL(in.Schema)
|
||||
out.Ref = (*string)(unsafe.Pointer(in.Ref))
|
||||
out.Description = in.Description
|
||||
out.Type = in.Type
|
||||
out.Format = in.Format
|
||||
out.Title = in.Title
|
||||
if in.Default != nil {
|
||||
in, out := &in.Default, &out.Default
|
||||
*out = new(apiextensions.JSON)
|
||||
if err := Convert_v1beta1_JSON_To_apiextensions_JSON(*in, *out, s); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
out.Default = nil
|
||||
}
|
||||
out.Maximum = (*float64)(unsafe.Pointer(in.Maximum))
|
||||
out.ExclusiveMaximum = in.ExclusiveMaximum
|
||||
out.Minimum = (*float64)(unsafe.Pointer(in.Minimum))
|
||||
out.ExclusiveMinimum = in.ExclusiveMinimum
|
||||
out.MaxLength = (*int64)(unsafe.Pointer(in.MaxLength))
|
||||
out.MinLength = (*int64)(unsafe.Pointer(in.MinLength))
|
||||
out.Pattern = in.Pattern
|
||||
out.MaxItems = (*int64)(unsafe.Pointer(in.MaxItems))
|
||||
out.MinItems = (*int64)(unsafe.Pointer(in.MinItems))
|
||||
out.UniqueItems = in.UniqueItems
|
||||
out.MultipleOf = (*float64)(unsafe.Pointer(in.MultipleOf))
|
||||
if in.Enum != nil {
|
||||
in, out := &in.Enum, &out.Enum
|
||||
*out = make([]apiextensions.JSON, len(*in))
|
||||
for i := range *in {
|
||||
if err := Convert_v1beta1_JSON_To_apiextensions_JSON(&(*in)[i], &(*out)[i], s); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
} else {
|
||||
out.Enum = nil
|
||||
}
|
||||
out.MaxProperties = (*int64)(unsafe.Pointer(in.MaxProperties))
|
||||
out.MinProperties = (*int64)(unsafe.Pointer(in.MinProperties))
|
||||
out.Required = *(*[]string)(unsafe.Pointer(&in.Required))
|
||||
if in.Items != nil {
|
||||
in, out := &in.Items, &out.Items
|
||||
*out = new(apiextensions.JSONSchemaPropsOrArray)
|
||||
if err := Convert_v1beta1_JSONSchemaPropsOrArray_To_apiextensions_JSONSchemaPropsOrArray(*in, *out, s); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
out.Items = nil
|
||||
}
|
||||
if in.AllOf != nil {
|
||||
in, out := &in.AllOf, &out.AllOf
|
||||
*out = make([]apiextensions.JSONSchemaProps, len(*in))
|
||||
for i := range *in {
|
||||
if err := Convert_v1beta1_JSONSchemaProps_To_apiextensions_JSONSchemaProps(&(*in)[i], &(*out)[i], s); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
} else {
|
||||
out.AllOf = nil
|
||||
}
|
||||
if in.OneOf != nil {
|
||||
in, out := &in.OneOf, &out.OneOf
|
||||
*out = make([]apiextensions.JSONSchemaProps, len(*in))
|
||||
for i := range *in {
|
||||
if err := Convert_v1beta1_JSONSchemaProps_To_apiextensions_JSONSchemaProps(&(*in)[i], &(*out)[i], s); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
} else {
|
||||
out.OneOf = nil
|
||||
}
|
||||
if in.AnyOf != nil {
|
||||
in, out := &in.AnyOf, &out.AnyOf
|
||||
*out = make([]apiextensions.JSONSchemaProps, len(*in))
|
||||
for i := range *in {
|
||||
if err := Convert_v1beta1_JSONSchemaProps_To_apiextensions_JSONSchemaProps(&(*in)[i], &(*out)[i], s); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
} else {
|
||||
out.AnyOf = nil
|
||||
}
|
||||
if in.Not != nil {
|
||||
in, out := &in.Not, &out.Not
|
||||
*out = new(apiextensions.JSONSchemaProps)
|
||||
if err := Convert_v1beta1_JSONSchemaProps_To_apiextensions_JSONSchemaProps(*in, *out, s); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
out.Not = nil
|
||||
}
|
||||
if in.Properties != nil {
|
||||
in, out := &in.Properties, &out.Properties
|
||||
*out = make(map[string]apiextensions.JSONSchemaProps, len(*in))
|
||||
for key, val := range *in {
|
||||
newVal := new(apiextensions.JSONSchemaProps)
|
||||
if err := Convert_v1beta1_JSONSchemaProps_To_apiextensions_JSONSchemaProps(&val, newVal, s); err != nil {
|
||||
return err
|
||||
}
|
||||
(*out)[key] = *newVal
|
||||
}
|
||||
} else {
|
||||
out.Properties = nil
|
||||
}
|
||||
if in.AdditionalProperties != nil {
|
||||
in, out := &in.AdditionalProperties, &out.AdditionalProperties
|
||||
*out = new(apiextensions.JSONSchemaPropsOrBool)
|
||||
if err := Convert_v1beta1_JSONSchemaPropsOrBool_To_apiextensions_JSONSchemaPropsOrBool(*in, *out, s); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
out.AdditionalProperties = nil
|
||||
}
|
||||
if in.PatternProperties != nil {
|
||||
in, out := &in.PatternProperties, &out.PatternProperties
|
||||
*out = make(map[string]apiextensions.JSONSchemaProps, len(*in))
|
||||
for key, val := range *in {
|
||||
newVal := new(apiextensions.JSONSchemaProps)
|
||||
if err := Convert_v1beta1_JSONSchemaProps_To_apiextensions_JSONSchemaProps(&val, newVal, s); err != nil {
|
||||
return err
|
||||
}
|
||||
(*out)[key] = *newVal
|
||||
}
|
||||
} else {
|
||||
out.PatternProperties = nil
|
||||
}
|
||||
if in.Dependencies != nil {
|
||||
in, out := &in.Dependencies, &out.Dependencies
|
||||
*out = make(apiextensions.JSONSchemaDependencies, len(*in))
|
||||
for key, val := range *in {
|
||||
newVal := new(apiextensions.JSONSchemaPropsOrStringArray)
|
||||
if err := Convert_v1beta1_JSONSchemaPropsOrStringArray_To_apiextensions_JSONSchemaPropsOrStringArray(&val, newVal, s); err != nil {
|
||||
return err
|
||||
}
|
||||
(*out)[key] = *newVal
|
||||
}
|
||||
} else {
|
||||
out.Dependencies = nil
|
||||
}
|
||||
if in.AdditionalItems != nil {
|
||||
in, out := &in.AdditionalItems, &out.AdditionalItems
|
||||
*out = new(apiextensions.JSONSchemaPropsOrBool)
|
||||
if err := Convert_v1beta1_JSONSchemaPropsOrBool_To_apiextensions_JSONSchemaPropsOrBool(*in, *out, s); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
out.AdditionalItems = nil
|
||||
}
|
||||
if in.Definitions != nil {
|
||||
in, out := &in.Definitions, &out.Definitions
|
||||
*out = make(apiextensions.JSONSchemaDefinitions, len(*in))
|
||||
for key, val := range *in {
|
||||
newVal := new(apiextensions.JSONSchemaProps)
|
||||
if err := Convert_v1beta1_JSONSchemaProps_To_apiextensions_JSONSchemaProps(&val, newVal, s); err != nil {
|
||||
return err
|
||||
}
|
||||
(*out)[key] = *newVal
|
||||
}
|
||||
} else {
|
||||
out.Definitions = nil
|
||||
}
|
||||
out.ExternalDocs = (*apiextensions.ExternalDocumentation)(unsafe.Pointer(in.ExternalDocs))
|
||||
if in.Example != nil {
|
||||
in, out := &in.Example, &out.Example
|
||||
*out = new(apiextensions.JSON)
|
||||
if err := Convert_v1beta1_JSON_To_apiextensions_JSON(*in, *out, s); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
out.Example = nil
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_v1beta1_JSONSchemaProps_To_apiextensions_JSONSchemaProps is an autogenerated conversion function.
|
||||
func Convert_v1beta1_JSONSchemaProps_To_apiextensions_JSONSchemaProps(in *JSONSchemaProps, out *apiextensions.JSONSchemaProps, s conversion.Scope) error {
|
||||
return autoConvert_v1beta1_JSONSchemaProps_To_apiextensions_JSONSchemaProps(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_apiextensions_JSONSchemaProps_To_v1beta1_JSONSchemaProps(in *apiextensions.JSONSchemaProps, out *JSONSchemaProps, s conversion.Scope) error {
|
||||
out.ID = in.ID
|
||||
out.Schema = JSONSchemaURL(in.Schema)
|
||||
out.Ref = (*string)(unsafe.Pointer(in.Ref))
|
||||
out.Description = in.Description
|
||||
out.Type = in.Type
|
||||
out.Format = in.Format
|
||||
out.Title = in.Title
|
||||
if in.Default != nil {
|
||||
in, out := &in.Default, &out.Default
|
||||
*out = new(JSON)
|
||||
if err := Convert_apiextensions_JSON_To_v1beta1_JSON(*in, *out, s); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
out.Default = nil
|
||||
}
|
||||
out.Maximum = (*float64)(unsafe.Pointer(in.Maximum))
|
||||
out.ExclusiveMaximum = in.ExclusiveMaximum
|
||||
out.Minimum = (*float64)(unsafe.Pointer(in.Minimum))
|
||||
out.ExclusiveMinimum = in.ExclusiveMinimum
|
||||
out.MaxLength = (*int64)(unsafe.Pointer(in.MaxLength))
|
||||
out.MinLength = (*int64)(unsafe.Pointer(in.MinLength))
|
||||
out.Pattern = in.Pattern
|
||||
out.MaxItems = (*int64)(unsafe.Pointer(in.MaxItems))
|
||||
out.MinItems = (*int64)(unsafe.Pointer(in.MinItems))
|
||||
out.UniqueItems = in.UniqueItems
|
||||
out.MultipleOf = (*float64)(unsafe.Pointer(in.MultipleOf))
|
||||
if in.Enum != nil {
|
||||
in, out := &in.Enum, &out.Enum
|
||||
*out = make([]JSON, len(*in))
|
||||
for i := range *in {
|
||||
if err := Convert_apiextensions_JSON_To_v1beta1_JSON(&(*in)[i], &(*out)[i], s); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
} else {
|
||||
out.Enum = nil
|
||||
}
|
||||
out.MaxProperties = (*int64)(unsafe.Pointer(in.MaxProperties))
|
||||
out.MinProperties = (*int64)(unsafe.Pointer(in.MinProperties))
|
||||
out.Required = *(*[]string)(unsafe.Pointer(&in.Required))
|
||||
if in.Items != nil {
|
||||
in, out := &in.Items, &out.Items
|
||||
*out = new(JSONSchemaPropsOrArray)
|
||||
if err := Convert_apiextensions_JSONSchemaPropsOrArray_To_v1beta1_JSONSchemaPropsOrArray(*in, *out, s); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
out.Items = nil
|
||||
}
|
||||
if in.AllOf != nil {
|
||||
in, out := &in.AllOf, &out.AllOf
|
||||
*out = make([]JSONSchemaProps, len(*in))
|
||||
for i := range *in {
|
||||
if err := Convert_apiextensions_JSONSchemaProps_To_v1beta1_JSONSchemaProps(&(*in)[i], &(*out)[i], s); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
} else {
|
||||
out.AllOf = nil
|
||||
}
|
||||
if in.OneOf != nil {
|
||||
in, out := &in.OneOf, &out.OneOf
|
||||
*out = make([]JSONSchemaProps, len(*in))
|
||||
for i := range *in {
|
||||
if err := Convert_apiextensions_JSONSchemaProps_To_v1beta1_JSONSchemaProps(&(*in)[i], &(*out)[i], s); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
} else {
|
||||
out.OneOf = nil
|
||||
}
|
||||
if in.AnyOf != nil {
|
||||
in, out := &in.AnyOf, &out.AnyOf
|
||||
*out = make([]JSONSchemaProps, len(*in))
|
||||
for i := range *in {
|
||||
if err := Convert_apiextensions_JSONSchemaProps_To_v1beta1_JSONSchemaProps(&(*in)[i], &(*out)[i], s); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
} else {
|
||||
out.AnyOf = nil
|
||||
}
|
||||
if in.Not != nil {
|
||||
in, out := &in.Not, &out.Not
|
||||
*out = new(JSONSchemaProps)
|
||||
if err := Convert_apiextensions_JSONSchemaProps_To_v1beta1_JSONSchemaProps(*in, *out, s); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
out.Not = nil
|
||||
}
|
||||
if in.Properties != nil {
|
||||
in, out := &in.Properties, &out.Properties
|
||||
*out = make(map[string]JSONSchemaProps, len(*in))
|
||||
for key, val := range *in {
|
||||
newVal := new(JSONSchemaProps)
|
||||
if err := Convert_apiextensions_JSONSchemaProps_To_v1beta1_JSONSchemaProps(&val, newVal, s); err != nil {
|
||||
return err
|
||||
}
|
||||
(*out)[key] = *newVal
|
||||
}
|
||||
} else {
|
||||
out.Properties = nil
|
||||
}
|
||||
if in.AdditionalProperties != nil {
|
||||
in, out := &in.AdditionalProperties, &out.AdditionalProperties
|
||||
*out = new(JSONSchemaPropsOrBool)
|
||||
if err := Convert_apiextensions_JSONSchemaPropsOrBool_To_v1beta1_JSONSchemaPropsOrBool(*in, *out, s); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
out.AdditionalProperties = nil
|
||||
}
|
||||
if in.PatternProperties != nil {
|
||||
in, out := &in.PatternProperties, &out.PatternProperties
|
||||
*out = make(map[string]JSONSchemaProps, len(*in))
|
||||
for key, val := range *in {
|
||||
newVal := new(JSONSchemaProps)
|
||||
if err := Convert_apiextensions_JSONSchemaProps_To_v1beta1_JSONSchemaProps(&val, newVal, s); err != nil {
|
||||
return err
|
||||
}
|
||||
(*out)[key] = *newVal
|
||||
}
|
||||
} else {
|
||||
out.PatternProperties = nil
|
||||
}
|
||||
if in.Dependencies != nil {
|
||||
in, out := &in.Dependencies, &out.Dependencies
|
||||
*out = make(JSONSchemaDependencies, len(*in))
|
||||
for key, val := range *in {
|
||||
newVal := new(JSONSchemaPropsOrStringArray)
|
||||
if err := Convert_apiextensions_JSONSchemaPropsOrStringArray_To_v1beta1_JSONSchemaPropsOrStringArray(&val, newVal, s); err != nil {
|
||||
return err
|
||||
}
|
||||
(*out)[key] = *newVal
|
||||
}
|
||||
} else {
|
||||
out.Dependencies = nil
|
||||
}
|
||||
if in.AdditionalItems != nil {
|
||||
in, out := &in.AdditionalItems, &out.AdditionalItems
|
||||
*out = new(JSONSchemaPropsOrBool)
|
||||
if err := Convert_apiextensions_JSONSchemaPropsOrBool_To_v1beta1_JSONSchemaPropsOrBool(*in, *out, s); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
out.AdditionalItems = nil
|
||||
}
|
||||
if in.Definitions != nil {
|
||||
in, out := &in.Definitions, &out.Definitions
|
||||
*out = make(JSONSchemaDefinitions, len(*in))
|
||||
for key, val := range *in {
|
||||
newVal := new(JSONSchemaProps)
|
||||
if err := Convert_apiextensions_JSONSchemaProps_To_v1beta1_JSONSchemaProps(&val, newVal, s); err != nil {
|
||||
return err
|
||||
}
|
||||
(*out)[key] = *newVal
|
||||
}
|
||||
} else {
|
||||
out.Definitions = nil
|
||||
}
|
||||
out.ExternalDocs = (*ExternalDocumentation)(unsafe.Pointer(in.ExternalDocs))
|
||||
if in.Example != nil {
|
||||
in, out := &in.Example, &out.Example
|
||||
*out = new(JSON)
|
||||
if err := Convert_apiextensions_JSON_To_v1beta1_JSON(*in, *out, s); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
out.Example = nil
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func autoConvert_v1beta1_JSONSchemaPropsOrArray_To_apiextensions_JSONSchemaPropsOrArray(in *JSONSchemaPropsOrArray, out *apiextensions.JSONSchemaPropsOrArray, s conversion.Scope) error {
|
||||
if in.Schema != nil {
|
||||
in, out := &in.Schema, &out.Schema
|
||||
*out = new(apiextensions.JSONSchemaProps)
|
||||
if err := Convert_v1beta1_JSONSchemaProps_To_apiextensions_JSONSchemaProps(*in, *out, s); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
out.Schema = nil
|
||||
}
|
||||
if in.JSONSchemas != nil {
|
||||
in, out := &in.JSONSchemas, &out.JSONSchemas
|
||||
*out = make([]apiextensions.JSONSchemaProps, len(*in))
|
||||
for i := range *in {
|
||||
if err := Convert_v1beta1_JSONSchemaProps_To_apiextensions_JSONSchemaProps(&(*in)[i], &(*out)[i], s); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
} else {
|
||||
out.JSONSchemas = nil
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_v1beta1_JSONSchemaPropsOrArray_To_apiextensions_JSONSchemaPropsOrArray is an autogenerated conversion function.
|
||||
func Convert_v1beta1_JSONSchemaPropsOrArray_To_apiextensions_JSONSchemaPropsOrArray(in *JSONSchemaPropsOrArray, out *apiextensions.JSONSchemaPropsOrArray, s conversion.Scope) error {
|
||||
return autoConvert_v1beta1_JSONSchemaPropsOrArray_To_apiextensions_JSONSchemaPropsOrArray(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_apiextensions_JSONSchemaPropsOrArray_To_v1beta1_JSONSchemaPropsOrArray(in *apiextensions.JSONSchemaPropsOrArray, out *JSONSchemaPropsOrArray, s conversion.Scope) error {
|
||||
if in.Schema != nil {
|
||||
in, out := &in.Schema, &out.Schema
|
||||
*out = new(JSONSchemaProps)
|
||||
if err := Convert_apiextensions_JSONSchemaProps_To_v1beta1_JSONSchemaProps(*in, *out, s); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
out.Schema = nil
|
||||
}
|
||||
if in.JSONSchemas != nil {
|
||||
in, out := &in.JSONSchemas, &out.JSONSchemas
|
||||
*out = make([]JSONSchemaProps, len(*in))
|
||||
for i := range *in {
|
||||
if err := Convert_apiextensions_JSONSchemaProps_To_v1beta1_JSONSchemaProps(&(*in)[i], &(*out)[i], s); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
} else {
|
||||
out.JSONSchemas = nil
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_apiextensions_JSONSchemaPropsOrArray_To_v1beta1_JSONSchemaPropsOrArray is an autogenerated conversion function.
|
||||
func Convert_apiextensions_JSONSchemaPropsOrArray_To_v1beta1_JSONSchemaPropsOrArray(in *apiextensions.JSONSchemaPropsOrArray, out *JSONSchemaPropsOrArray, s conversion.Scope) error {
|
||||
return autoConvert_apiextensions_JSONSchemaPropsOrArray_To_v1beta1_JSONSchemaPropsOrArray(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_v1beta1_JSONSchemaPropsOrBool_To_apiextensions_JSONSchemaPropsOrBool(in *JSONSchemaPropsOrBool, out *apiextensions.JSONSchemaPropsOrBool, s conversion.Scope) error {
|
||||
out.Allows = in.Allows
|
||||
if in.Schema != nil {
|
||||
in, out := &in.Schema, &out.Schema
|
||||
*out = new(apiextensions.JSONSchemaProps)
|
||||
if err := Convert_v1beta1_JSONSchemaProps_To_apiextensions_JSONSchemaProps(*in, *out, s); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
out.Schema = nil
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_v1beta1_JSONSchemaPropsOrBool_To_apiextensions_JSONSchemaPropsOrBool is an autogenerated conversion function.
|
||||
func Convert_v1beta1_JSONSchemaPropsOrBool_To_apiextensions_JSONSchemaPropsOrBool(in *JSONSchemaPropsOrBool, out *apiextensions.JSONSchemaPropsOrBool, s conversion.Scope) error {
|
||||
return autoConvert_v1beta1_JSONSchemaPropsOrBool_To_apiextensions_JSONSchemaPropsOrBool(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_apiextensions_JSONSchemaPropsOrBool_To_v1beta1_JSONSchemaPropsOrBool(in *apiextensions.JSONSchemaPropsOrBool, out *JSONSchemaPropsOrBool, s conversion.Scope) error {
|
||||
out.Allows = in.Allows
|
||||
if in.Schema != nil {
|
||||
in, out := &in.Schema, &out.Schema
|
||||
*out = new(JSONSchemaProps)
|
||||
if err := Convert_apiextensions_JSONSchemaProps_To_v1beta1_JSONSchemaProps(*in, *out, s); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
out.Schema = nil
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_apiextensions_JSONSchemaPropsOrBool_To_v1beta1_JSONSchemaPropsOrBool is an autogenerated conversion function.
|
||||
func Convert_apiextensions_JSONSchemaPropsOrBool_To_v1beta1_JSONSchemaPropsOrBool(in *apiextensions.JSONSchemaPropsOrBool, out *JSONSchemaPropsOrBool, s conversion.Scope) error {
|
||||
return autoConvert_apiextensions_JSONSchemaPropsOrBool_To_v1beta1_JSONSchemaPropsOrBool(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_v1beta1_JSONSchemaPropsOrStringArray_To_apiextensions_JSONSchemaPropsOrStringArray(in *JSONSchemaPropsOrStringArray, out *apiextensions.JSONSchemaPropsOrStringArray, s conversion.Scope) error {
|
||||
if in.Schema != nil {
|
||||
in, out := &in.Schema, &out.Schema
|
||||
*out = new(apiextensions.JSONSchemaProps)
|
||||
if err := Convert_v1beta1_JSONSchemaProps_To_apiextensions_JSONSchemaProps(*in, *out, s); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
out.Schema = nil
|
||||
}
|
||||
out.Property = *(*[]string)(unsafe.Pointer(&in.Property))
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_v1beta1_JSONSchemaPropsOrStringArray_To_apiextensions_JSONSchemaPropsOrStringArray is an autogenerated conversion function.
|
||||
func Convert_v1beta1_JSONSchemaPropsOrStringArray_To_apiextensions_JSONSchemaPropsOrStringArray(in *JSONSchemaPropsOrStringArray, out *apiextensions.JSONSchemaPropsOrStringArray, s conversion.Scope) error {
|
||||
return autoConvert_v1beta1_JSONSchemaPropsOrStringArray_To_apiextensions_JSONSchemaPropsOrStringArray(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_apiextensions_JSONSchemaPropsOrStringArray_To_v1beta1_JSONSchemaPropsOrStringArray(in *apiextensions.JSONSchemaPropsOrStringArray, out *JSONSchemaPropsOrStringArray, s conversion.Scope) error {
|
||||
if in.Schema != nil {
|
||||
in, out := &in.Schema, &out.Schema
|
||||
*out = new(JSONSchemaProps)
|
||||
if err := Convert_apiextensions_JSONSchemaProps_To_v1beta1_JSONSchemaProps(*in, *out, s); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
out.Schema = nil
|
||||
}
|
||||
out.Property = *(*[]string)(unsafe.Pointer(&in.Property))
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_apiextensions_JSONSchemaPropsOrStringArray_To_v1beta1_JSONSchemaPropsOrStringArray is an autogenerated conversion function.
|
||||
func Convert_apiextensions_JSONSchemaPropsOrStringArray_To_v1beta1_JSONSchemaPropsOrStringArray(in *apiextensions.JSONSchemaPropsOrStringArray, out *JSONSchemaPropsOrStringArray, s conversion.Scope) error {
|
||||
return autoConvert_apiextensions_JSONSchemaPropsOrStringArray_To_v1beta1_JSONSchemaPropsOrStringArray(in, out, s)
|
||||
}
|
||||
470
vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1/zz_generated.deepcopy.go
generated
vendored
Normal file
470
vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1/zz_generated.deepcopy.go
generated
vendored
Normal file
@@ -0,0 +1,470 @@
|
||||
// +build !ignore_autogenerated
|
||||
|
||||
/*
|
||||
Copyright 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.
|
||||
*/
|
||||
|
||||
// Code generated by deepcopy-gen. DO NOT EDIT.
|
||||
|
||||
package v1beta1
|
||||
|
||||
import (
|
||||
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.
|
||||
func (in *CustomResourceDefinition) DeepCopyInto(out *CustomResourceDefinition) {
|
||||
*out = *in
|
||||
out.TypeMeta = in.TypeMeta
|
||||
in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
|
||||
in.Spec.DeepCopyInto(&out.Spec)
|
||||
in.Status.DeepCopyInto(&out.Status)
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CustomResourceDefinition.
|
||||
func (in *CustomResourceDefinition) DeepCopy() *CustomResourceDefinition {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(CustomResourceDefinition)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
|
||||
func (in *CustomResourceDefinition) DeepCopyObject() runtime.Object {
|
||||
if c := in.DeepCopy(); c != nil {
|
||||
return c
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *CustomResourceDefinitionCondition) DeepCopyInto(out *CustomResourceDefinitionCondition) {
|
||||
*out = *in
|
||||
in.LastTransitionTime.DeepCopyInto(&out.LastTransitionTime)
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CustomResourceDefinitionCondition.
|
||||
func (in *CustomResourceDefinitionCondition) DeepCopy() *CustomResourceDefinitionCondition {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(CustomResourceDefinitionCondition)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *CustomResourceDefinitionList) DeepCopyInto(out *CustomResourceDefinitionList) {
|
||||
*out = *in
|
||||
out.TypeMeta = in.TypeMeta
|
||||
out.ListMeta = in.ListMeta
|
||||
if in.Items != nil {
|
||||
in, out := &in.Items, &out.Items
|
||||
*out = make([]CustomResourceDefinition, len(*in))
|
||||
for i := range *in {
|
||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CustomResourceDefinitionList.
|
||||
func (in *CustomResourceDefinitionList) DeepCopy() *CustomResourceDefinitionList {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(CustomResourceDefinitionList)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
|
||||
func (in *CustomResourceDefinitionList) DeepCopyObject() runtime.Object {
|
||||
if c := in.DeepCopy(); c != nil {
|
||||
return c
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *CustomResourceDefinitionNames) DeepCopyInto(out *CustomResourceDefinitionNames) {
|
||||
*out = *in
|
||||
if in.ShortNames != nil {
|
||||
in, out := &in.ShortNames, &out.ShortNames
|
||||
*out = make([]string, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
if in.Categories != nil {
|
||||
in, out := &in.Categories, &out.Categories
|
||||
*out = make([]string, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CustomResourceDefinitionNames.
|
||||
func (in *CustomResourceDefinitionNames) DeepCopy() *CustomResourceDefinitionNames {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(CustomResourceDefinitionNames)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *CustomResourceDefinitionSpec) DeepCopyInto(out *CustomResourceDefinitionSpec) {
|
||||
*out = *in
|
||||
in.Names.DeepCopyInto(&out.Names)
|
||||
if in.Validation != nil {
|
||||
in, out := &in.Validation, &out.Validation
|
||||
*out = new(CustomResourceValidation)
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
if in.Subresources != nil {
|
||||
in, out := &in.Subresources, &out.Subresources
|
||||
*out = new(CustomResourceSubresources)
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
if in.Versions != nil {
|
||||
in, out := &in.Versions, &out.Versions
|
||||
*out = make([]CustomResourceDefinitionVersion, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
if in.AdditionalPrinterColumns != nil {
|
||||
in, out := &in.AdditionalPrinterColumns, &out.AdditionalPrinterColumns
|
||||
*out = make([]CustomResourceColumnDefinition, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CustomResourceDefinitionSpec.
|
||||
func (in *CustomResourceDefinitionSpec) DeepCopy() *CustomResourceDefinitionSpec {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(CustomResourceDefinitionSpec)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *CustomResourceDefinitionStatus) DeepCopyInto(out *CustomResourceDefinitionStatus) {
|
||||
*out = *in
|
||||
if in.Conditions != nil {
|
||||
in, out := &in.Conditions, &out.Conditions
|
||||
*out = make([]CustomResourceDefinitionCondition, len(*in))
|
||||
for i := range *in {
|
||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||
}
|
||||
}
|
||||
in.AcceptedNames.DeepCopyInto(&out.AcceptedNames)
|
||||
if in.StoredVersions != nil {
|
||||
in, out := &in.StoredVersions, &out.StoredVersions
|
||||
*out = make([]string, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CustomResourceDefinitionStatus.
|
||||
func (in *CustomResourceDefinitionStatus) DeepCopy() *CustomResourceDefinitionStatus {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(CustomResourceDefinitionStatus)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *CustomResourceDefinitionVersion) DeepCopyInto(out *CustomResourceDefinitionVersion) {
|
||||
*out = *in
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CustomResourceDefinitionVersion.
|
||||
func (in *CustomResourceDefinitionVersion) DeepCopy() *CustomResourceDefinitionVersion {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(CustomResourceDefinitionVersion)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *CustomResourceSubresourceScale) DeepCopyInto(out *CustomResourceSubresourceScale) {
|
||||
*out = *in
|
||||
if in.LabelSelectorPath != nil {
|
||||
in, out := &in.LabelSelectorPath, &out.LabelSelectorPath
|
||||
*out = new(string)
|
||||
**out = **in
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CustomResourceSubresourceScale.
|
||||
func (in *CustomResourceSubresourceScale) DeepCopy() *CustomResourceSubresourceScale {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(CustomResourceSubresourceScale)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *CustomResourceSubresourceStatus) DeepCopyInto(out *CustomResourceSubresourceStatus) {
|
||||
*out = *in
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CustomResourceSubresourceStatus.
|
||||
func (in *CustomResourceSubresourceStatus) DeepCopy() *CustomResourceSubresourceStatus {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(CustomResourceSubresourceStatus)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *CustomResourceSubresources) DeepCopyInto(out *CustomResourceSubresources) {
|
||||
*out = *in
|
||||
if in.Status != nil {
|
||||
in, out := &in.Status, &out.Status
|
||||
*out = new(CustomResourceSubresourceStatus)
|
||||
**out = **in
|
||||
}
|
||||
if in.Scale != nil {
|
||||
in, out := &in.Scale, &out.Scale
|
||||
*out = new(CustomResourceSubresourceScale)
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CustomResourceSubresources.
|
||||
func (in *CustomResourceSubresources) DeepCopy() *CustomResourceSubresources {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(CustomResourceSubresources)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *CustomResourceValidation) DeepCopyInto(out *CustomResourceValidation) {
|
||||
*out = *in
|
||||
if in.OpenAPIV3Schema != nil {
|
||||
in, out := &in.OpenAPIV3Schema, &out.OpenAPIV3Schema
|
||||
*out = (*in).DeepCopy()
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CustomResourceValidation.
|
||||
func (in *CustomResourceValidation) DeepCopy() *CustomResourceValidation {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(CustomResourceValidation)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *ExternalDocumentation) DeepCopyInto(out *ExternalDocumentation) {
|
||||
*out = *in
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ExternalDocumentation.
|
||||
func (in *ExternalDocumentation) DeepCopy() *ExternalDocumentation {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(ExternalDocumentation)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *JSON) DeepCopyInto(out *JSON) {
|
||||
*out = *in
|
||||
if in.Raw != nil {
|
||||
in, out := &in.Raw, &out.Raw
|
||||
*out = make([]byte, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new JSON.
|
||||
func (in *JSON) DeepCopy() *JSON {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(JSON)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in JSONSchemaDefinitions) DeepCopyInto(out *JSONSchemaDefinitions) {
|
||||
{
|
||||
in := &in
|
||||
*out = make(JSONSchemaDefinitions, len(*in))
|
||||
for key, val := range *in {
|
||||
(*out)[key] = *val.DeepCopy()
|
||||
}
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new JSONSchemaDefinitions.
|
||||
func (in JSONSchemaDefinitions) DeepCopy() JSONSchemaDefinitions {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(JSONSchemaDefinitions)
|
||||
in.DeepCopyInto(out)
|
||||
return *out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in JSONSchemaDependencies) DeepCopyInto(out *JSONSchemaDependencies) {
|
||||
{
|
||||
in := &in
|
||||
*out = make(JSONSchemaDependencies, len(*in))
|
||||
for key, val := range *in {
|
||||
(*out)[key] = *val.DeepCopy()
|
||||
}
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new JSONSchemaDependencies.
|
||||
func (in JSONSchemaDependencies) DeepCopy() JSONSchemaDependencies {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(JSONSchemaDependencies)
|
||||
in.DeepCopyInto(out)
|
||||
return *out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *JSONSchemaProps) DeepCopyInto(out *JSONSchemaProps) {
|
||||
clone := in.DeepCopy()
|
||||
*out = *clone
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *JSONSchemaPropsOrArray) DeepCopyInto(out *JSONSchemaPropsOrArray) {
|
||||
*out = *in
|
||||
if in.Schema != nil {
|
||||
in, out := &in.Schema, &out.Schema
|
||||
*out = (*in).DeepCopy()
|
||||
}
|
||||
if in.JSONSchemas != nil {
|
||||
in, out := &in.JSONSchemas, &out.JSONSchemas
|
||||
*out = make([]JSONSchemaProps, len(*in))
|
||||
for i := range *in {
|
||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new JSONSchemaPropsOrArray.
|
||||
func (in *JSONSchemaPropsOrArray) DeepCopy() *JSONSchemaPropsOrArray {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(JSONSchemaPropsOrArray)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *JSONSchemaPropsOrBool) DeepCopyInto(out *JSONSchemaPropsOrBool) {
|
||||
*out = *in
|
||||
if in.Schema != nil {
|
||||
in, out := &in.Schema, &out.Schema
|
||||
*out = (*in).DeepCopy()
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new JSONSchemaPropsOrBool.
|
||||
func (in *JSONSchemaPropsOrBool) DeepCopy() *JSONSchemaPropsOrBool {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(JSONSchemaPropsOrBool)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *JSONSchemaPropsOrStringArray) DeepCopyInto(out *JSONSchemaPropsOrStringArray) {
|
||||
*out = *in
|
||||
if in.Schema != nil {
|
||||
in, out := &in.Schema, &out.Schema
|
||||
*out = (*in).DeepCopy()
|
||||
}
|
||||
if in.Property != nil {
|
||||
in, out := &in.Property, &out.Property
|
||||
*out = make([]string, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new JSONSchemaPropsOrStringArray.
|
||||
func (in *JSONSchemaPropsOrStringArray) DeepCopy() *JSONSchemaPropsOrStringArray {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(JSONSchemaPropsOrStringArray)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
48
vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1/zz_generated.defaults.go
generated
vendored
Normal file
48
vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1/zz_generated.defaults.go
generated
vendored
Normal file
@@ -0,0 +1,48 @@
|
||||
// +build !ignore_autogenerated
|
||||
|
||||
/*
|
||||
Copyright 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.
|
||||
*/
|
||||
|
||||
// Code generated by defaulter-gen. DO NOT EDIT.
|
||||
|
||||
package v1beta1
|
||||
|
||||
import (
|
||||
runtime "k8s.io/apimachinery/pkg/runtime"
|
||||
)
|
||||
|
||||
// RegisterDefaults adds defaulters functions to the given scheme.
|
||||
// Public to allow building arbitrary schemes.
|
||||
// All generated defaulters are covering - they call all nested defaulters.
|
||||
func RegisterDefaults(scheme *runtime.Scheme) error {
|
||||
scheme.AddTypeDefaultingFunc(&CustomResourceDefinition{}, func(obj interface{}) { SetObjectDefaults_CustomResourceDefinition(obj.(*CustomResourceDefinition)) })
|
||||
scheme.AddTypeDefaultingFunc(&CustomResourceDefinitionList{}, func(obj interface{}) {
|
||||
SetObjectDefaults_CustomResourceDefinitionList(obj.(*CustomResourceDefinitionList))
|
||||
})
|
||||
return nil
|
||||
}
|
||||
|
||||
func SetObjectDefaults_CustomResourceDefinition(in *CustomResourceDefinition) {
|
||||
SetDefaults_CustomResourceDefinition(in)
|
||||
SetDefaults_CustomResourceDefinitionSpec(&in.Spec)
|
||||
}
|
||||
|
||||
func SetObjectDefaults_CustomResourceDefinitionList(in *CustomResourceDefinitionList) {
|
||||
for i := range in.Items {
|
||||
a := &in.Items[i]
|
||||
SetObjectDefaults_CustomResourceDefinition(a)
|
||||
}
|
||||
}
|
||||
546
vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/validation/validation.go
generated
vendored
Normal file
546
vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/validation/validation.go
generated
vendored
Normal file
@@ -0,0 +1,546 @@
|
||||
/*
|
||||
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 validation
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"strings"
|
||||
|
||||
genericvalidation "k8s.io/apimachinery/pkg/api/validation"
|
||||
"k8s.io/apimachinery/pkg/util/sets"
|
||||
validationutil "k8s.io/apimachinery/pkg/util/validation"
|
||||
"k8s.io/apimachinery/pkg/util/validation/field"
|
||||
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||
|
||||
"k8s.io/apiextensions-apiserver/pkg/apis/apiextensions"
|
||||
apiservervalidation "k8s.io/apiextensions-apiserver/pkg/apiserver/validation"
|
||||
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
|
||||
func ValidateCustomResourceDefinition(obj *apiextensions.CustomResourceDefinition) field.ErrorList {
|
||||
nameValidationFn := func(name string, prefix bool) []string {
|
||||
ret := genericvalidation.NameIsDNSSubdomain(name, prefix)
|
||||
requiredName := obj.Spec.Names.Plural + "." + obj.Spec.Group
|
||||
if name != requiredName {
|
||||
ret = append(ret, fmt.Sprintf(`must be spec.names.plural+"."+spec.group`))
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
allErrs := genericvalidation.ValidateObjectMeta(&obj.ObjectMeta, false, nameValidationFn, field.NewPath("metadata"))
|
||||
allErrs = append(allErrs, ValidateCustomResourceDefinitionSpec(&obj.Spec, field.NewPath("spec"))...)
|
||||
allErrs = append(allErrs, ValidateCustomResourceDefinitionStatus(&obj.Status, field.NewPath("status"))...)
|
||||
allErrs = append(allErrs, ValidateCustomResourceDefinitionStoredVersions(obj.Status.StoredVersions, obj.Spec.Versions, field.NewPath("status").Child("storedVersions"))...)
|
||||
return allErrs
|
||||
}
|
||||
|
||||
// ValidateCustomResourceDefinitionUpdate statically validates
|
||||
func ValidateCustomResourceDefinitionUpdate(obj, oldObj *apiextensions.CustomResourceDefinition) field.ErrorList {
|
||||
allErrs := genericvalidation.ValidateObjectMetaUpdate(&obj.ObjectMeta, &oldObj.ObjectMeta, field.NewPath("metadata"))
|
||||
allErrs = append(allErrs, ValidateCustomResourceDefinitionSpecUpdate(&obj.Spec, &oldObj.Spec, apiextensions.IsCRDConditionTrue(oldObj, apiextensions.Established), field.NewPath("spec"))...)
|
||||
allErrs = append(allErrs, ValidateCustomResourceDefinitionStatus(&obj.Status, field.NewPath("status"))...)
|
||||
allErrs = append(allErrs, ValidateCustomResourceDefinitionStoredVersions(obj.Status.StoredVersions, obj.Spec.Versions, field.NewPath("status").Child("storedVersions"))...)
|
||||
return allErrs
|
||||
}
|
||||
|
||||
// ValidateCustomResourceDefinitionStoredVersions statically validates
|
||||
func ValidateCustomResourceDefinitionStoredVersions(storedVersions []string, versions []apiextensions.CustomResourceDefinitionVersion, fldPath *field.Path) field.ErrorList {
|
||||
if len(storedVersions) == 0 {
|
||||
return field.ErrorList{field.Invalid(fldPath, storedVersions, "must have at least one stored version")}
|
||||
}
|
||||
allErrs := field.ErrorList{}
|
||||
storedVersionsMap := map[string]int{}
|
||||
for i, v := range storedVersions {
|
||||
storedVersionsMap[v] = i
|
||||
}
|
||||
for _, v := range versions {
|
||||
_, ok := storedVersionsMap[v.Name]
|
||||
if v.Storage && !ok {
|
||||
allErrs = append(allErrs, field.Invalid(fldPath, v, "must have the storage version "+v.Name))
|
||||
}
|
||||
if ok {
|
||||
delete(storedVersionsMap, v.Name)
|
||||
}
|
||||
}
|
||||
|
||||
for v, i := range storedVersionsMap {
|
||||
allErrs = append(allErrs, field.Invalid(fldPath.Index(i), v, "must appear in spec.versions"))
|
||||
}
|
||||
|
||||
return allErrs
|
||||
}
|
||||
|
||||
// ValidateUpdateCustomResourceDefinitionStatus statically validates
|
||||
func ValidateUpdateCustomResourceDefinitionStatus(obj, oldObj *apiextensions.CustomResourceDefinition) field.ErrorList {
|
||||
allErrs := genericvalidation.ValidateObjectMetaUpdate(&obj.ObjectMeta, &oldObj.ObjectMeta, field.NewPath("metadata"))
|
||||
allErrs = append(allErrs, ValidateCustomResourceDefinitionStatus(&obj.Status, field.NewPath("status"))...)
|
||||
return allErrs
|
||||
}
|
||||
|
||||
// ValidateCustomResourceDefinitionSpec statically validates
|
||||
func ValidateCustomResourceDefinitionSpec(spec *apiextensions.CustomResourceDefinitionSpec, fldPath *field.Path) field.ErrorList {
|
||||
allErrs := field.ErrorList{}
|
||||
|
||||
if len(spec.Group) == 0 {
|
||||
allErrs = append(allErrs, field.Required(fldPath.Child("group"), ""))
|
||||
} else if errs := validationutil.IsDNS1123Subdomain(spec.Group); len(errs) > 0 {
|
||||
allErrs = append(allErrs, field.Invalid(fldPath.Child("group"), spec.Group, strings.Join(errs, ",")))
|
||||
} else if len(strings.Split(spec.Group, ".")) < 2 {
|
||||
allErrs = append(allErrs, field.Invalid(fldPath.Child("group"), spec.Group, "should be a domain with at least one dot"))
|
||||
}
|
||||
|
||||
switch spec.Scope {
|
||||
case "":
|
||||
allErrs = append(allErrs, field.Required(fldPath.Child("scope"), ""))
|
||||
case apiextensions.ClusterScoped, apiextensions.NamespaceScoped:
|
||||
default:
|
||||
allErrs = append(allErrs, field.NotSupported(fldPath.Child("scope"), spec.Scope, []string{string(apiextensions.ClusterScoped), string(apiextensions.NamespaceScoped)}))
|
||||
}
|
||||
|
||||
storageFlagCount := 0
|
||||
versionsMap := map[string]bool{}
|
||||
uniqueNames := true
|
||||
for i, version := range spec.Versions {
|
||||
if version.Storage {
|
||||
storageFlagCount++
|
||||
}
|
||||
if versionsMap[version.Name] {
|
||||
uniqueNames = false
|
||||
} else {
|
||||
versionsMap[version.Name] = true
|
||||
}
|
||||
if errs := validationutil.IsDNS1035Label(version.Name); len(errs) > 0 {
|
||||
allErrs = append(allErrs, field.Invalid(fldPath.Child("versions").Index(i).Child("name"), spec.Versions[i].Name, strings.Join(errs, ",")))
|
||||
}
|
||||
}
|
||||
if !uniqueNames {
|
||||
allErrs = append(allErrs, field.Invalid(fldPath.Child("versions"), spec.Versions, "must contain unique version names"))
|
||||
}
|
||||
if storageFlagCount != 1 {
|
||||
allErrs = append(allErrs, field.Invalid(fldPath.Child("versions"), spec.Versions, "must have exactly one version marked as storage version"))
|
||||
}
|
||||
if len(spec.Version) != 0 {
|
||||
if errs := validationutil.IsDNS1035Label(spec.Version); len(errs) > 0 {
|
||||
allErrs = append(allErrs, field.Invalid(fldPath.Child("version"), spec.Version, strings.Join(errs, ",")))
|
||||
}
|
||||
if len(spec.Versions) >= 1 && spec.Versions[0].Name != spec.Version {
|
||||
allErrs = append(allErrs, field.Invalid(fldPath.Child("version"), spec.Version, "must match the first version in spec.versions"))
|
||||
}
|
||||
}
|
||||
|
||||
// in addition to the basic name restrictions, some names are required for spec, but not for status
|
||||
if len(spec.Names.Plural) == 0 {
|
||||
allErrs = append(allErrs, field.Required(fldPath.Child("names", "plural"), ""))
|
||||
}
|
||||
if len(spec.Names.Singular) == 0 {
|
||||
allErrs = append(allErrs, field.Required(fldPath.Child("names", "singular"), ""))
|
||||
}
|
||||
if len(spec.Names.Kind) == 0 {
|
||||
allErrs = append(allErrs, field.Required(fldPath.Child("names", "kind"), ""))
|
||||
}
|
||||
if len(spec.Names.ListKind) == 0 {
|
||||
allErrs = append(allErrs, field.Required(fldPath.Child("names", "listKind"), ""))
|
||||
}
|
||||
|
||||
allErrs = append(allErrs, ValidateCustomResourceDefinitionNames(&spec.Names, fldPath.Child("names"))...)
|
||||
|
||||
if utilfeature.DefaultFeatureGate.Enabled(apiextensionsfeatures.CustomResourceValidation) {
|
||||
statusEnabled := false
|
||||
if spec.Subresources != nil && spec.Subresources.Status != nil {
|
||||
statusEnabled = true
|
||||
}
|
||||
allErrs = append(allErrs, ValidateCustomResourceDefinitionValidation(spec.Validation, statusEnabled, fldPath.Child("validation"))...)
|
||||
} else if spec.Validation != nil {
|
||||
allErrs = append(allErrs, field.Forbidden(fldPath.Child("validation"), "disabled by feature-gate CustomResourceValidation"))
|
||||
}
|
||||
|
||||
if utilfeature.DefaultFeatureGate.Enabled(apiextensionsfeatures.CustomResourceSubresources) {
|
||||
allErrs = append(allErrs, ValidateCustomResourceDefinitionSubresources(spec.Subresources, fldPath.Child("subresources"))...)
|
||||
} else if spec.Subresources != nil {
|
||||
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
|
||||
}
|
||||
|
||||
// ValidateCustomResourceDefinitionSpecUpdate statically validates
|
||||
func ValidateCustomResourceDefinitionSpecUpdate(spec, oldSpec *apiextensions.CustomResourceDefinitionSpec, established bool, fldPath *field.Path) field.ErrorList {
|
||||
allErrs := ValidateCustomResourceDefinitionSpec(spec, fldPath)
|
||||
|
||||
if established {
|
||||
// these effect the storage and cannot be changed therefore
|
||||
allErrs = append(allErrs, genericvalidation.ValidateImmutableField(spec.Scope, oldSpec.Scope, fldPath.Child("scope"))...)
|
||||
allErrs = append(allErrs, genericvalidation.ValidateImmutableField(spec.Names.Kind, oldSpec.Names.Kind, fldPath.Child("names", "kind"))...)
|
||||
}
|
||||
|
||||
// these affects the resource name, which is always immutable, so this can't be updated.
|
||||
allErrs = append(allErrs, genericvalidation.ValidateImmutableField(spec.Group, oldSpec.Group, fldPath.Child("group"))...)
|
||||
allErrs = append(allErrs, genericvalidation.ValidateImmutableField(spec.Names.Plural, oldSpec.Names.Plural, fldPath.Child("names", "plural"))...)
|
||||
|
||||
return allErrs
|
||||
}
|
||||
|
||||
// ValidateCustomResourceDefinitionStatus statically validates
|
||||
func ValidateCustomResourceDefinitionStatus(status *apiextensions.CustomResourceDefinitionStatus, fldPath *field.Path) field.ErrorList {
|
||||
allErrs := field.ErrorList{}
|
||||
allErrs = append(allErrs, ValidateCustomResourceDefinitionNames(&status.AcceptedNames, fldPath.Child("acceptedNames"))...)
|
||||
return allErrs
|
||||
}
|
||||
|
||||
// ValidateCustomResourceDefinitionNames statically validates
|
||||
func ValidateCustomResourceDefinitionNames(names *apiextensions.CustomResourceDefinitionNames, fldPath *field.Path) field.ErrorList {
|
||||
allErrs := field.ErrorList{}
|
||||
if errs := validationutil.IsDNS1035Label(names.Plural); len(names.Plural) > 0 && len(errs) > 0 {
|
||||
allErrs = append(allErrs, field.Invalid(fldPath.Child("plural"), names.Plural, strings.Join(errs, ",")))
|
||||
}
|
||||
if errs := validationutil.IsDNS1035Label(names.Singular); len(names.Singular) > 0 && len(errs) > 0 {
|
||||
allErrs = append(allErrs, field.Invalid(fldPath.Child("singular"), names.Singular, strings.Join(errs, ",")))
|
||||
}
|
||||
if errs := validationutil.IsDNS1035Label(strings.ToLower(names.Kind)); len(names.Kind) > 0 && len(errs) > 0 {
|
||||
allErrs = append(allErrs, field.Invalid(fldPath.Child("kind"), names.Kind, "may have mixed case, but should otherwise match: "+strings.Join(errs, ",")))
|
||||
}
|
||||
if errs := validationutil.IsDNS1035Label(strings.ToLower(names.ListKind)); len(names.ListKind) > 0 && len(errs) > 0 {
|
||||
allErrs = append(allErrs, field.Invalid(fldPath.Child("listKind"), names.ListKind, "may have mixed case, but should otherwise match: "+strings.Join(errs, ",")))
|
||||
}
|
||||
|
||||
for i, shortName := range names.ShortNames {
|
||||
if errs := validationutil.IsDNS1035Label(shortName); len(errs) > 0 {
|
||||
allErrs = append(allErrs, field.Invalid(fldPath.Child("shortNames").Index(i), shortName, strings.Join(errs, ",")))
|
||||
}
|
||||
}
|
||||
|
||||
// kind and listKind may not be the same or parsing become ambiguous
|
||||
if len(names.Kind) > 0 && names.Kind == names.ListKind {
|
||||
allErrs = append(allErrs, field.Invalid(fldPath.Child("listKind"), names.ListKind, "kind and listKind may not be the same"))
|
||||
}
|
||||
|
||||
for i, category := range names.Categories {
|
||||
if errs := validationutil.IsDNS1035Label(category); len(errs) > 0 {
|
||||
allErrs = append(allErrs, field.Invalid(fldPath.Child("categories").Index(i), category, strings.Join(errs, ",")))
|
||||
}
|
||||
}
|
||||
|
||||
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.
|
||||
type specStandardValidator interface {
|
||||
validate(spec *apiextensions.JSONSchemaProps, fldPath *field.Path) field.ErrorList
|
||||
}
|
||||
|
||||
// ValidateCustomResourceDefinitionValidation statically validates
|
||||
func ValidateCustomResourceDefinitionValidation(customResourceValidation *apiextensions.CustomResourceValidation, statusSubresourceEnabled bool, fldPath *field.Path) field.ErrorList {
|
||||
allErrs := field.ErrorList{}
|
||||
|
||||
if customResourceValidation == nil {
|
||||
return allErrs
|
||||
}
|
||||
|
||||
if schema := customResourceValidation.OpenAPIV3Schema; schema != nil {
|
||||
// if the status subresource is enabled, only certain fields are allowed inside the root schema.
|
||||
// these fields are chosen such that, if status is extracted as properties["status"], it's validation is not lost.
|
||||
if utilfeature.DefaultFeatureGate.Enabled(apiextensionsfeatures.CustomResourceSubresources) && statusSubresourceEnabled {
|
||||
v := reflect.ValueOf(schema).Elem()
|
||||
for i := 0; i < v.NumField(); i++ {
|
||||
// skip zero values
|
||||
if value := v.Field(i).Interface(); reflect.DeepEqual(value, reflect.Zero(reflect.TypeOf(value)).Interface()) {
|
||||
continue
|
||||
}
|
||||
|
||||
fieldName := v.Type().Field(i).Name
|
||||
|
||||
// only "object" type is valid at root of the schema since validation schema for status is extracted as properties["status"]
|
||||
if fieldName == "Type" {
|
||||
if schema.Type != "object" {
|
||||
allErrs = append(allErrs, field.Invalid(fldPath.Child("openAPIV3Schema.type"), schema.Type, fmt.Sprintf(`only "object" is allowed as the type at the root of the schema if the status subresource is enabled`)))
|
||||
break
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
if !allowedAtRootSchema(fieldName) {
|
||||
allErrs = append(allErrs, field.Invalid(fldPath.Child("openAPIV3Schema"), *schema, fmt.Sprintf(`only %v fields are allowed at the root of the schema if the status subresource is enabled`, allowedFieldsAtRootSchema)))
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
openAPIV3Schema := &specStandardValidatorV3{}
|
||||
allErrs = append(allErrs, ValidateCustomResourceDefinitionOpenAPISchema(schema, fldPath.Child("openAPIV3Schema"), openAPIV3Schema)...)
|
||||
}
|
||||
|
||||
// if validation passed otherwise, make sure we can actually construct a schema validator from this custom resource validation.
|
||||
if len(allErrs) == 0 {
|
||||
if _, _, err := apiservervalidation.NewSchemaValidator(customResourceValidation); err != nil {
|
||||
allErrs = append(allErrs, field.Invalid(fldPath, "", fmt.Sprintf("error building validator: %v", err)))
|
||||
}
|
||||
}
|
||||
return allErrs
|
||||
}
|
||||
|
||||
// ValidateCustomResourceDefinitionOpenAPISchema statically validates
|
||||
func ValidateCustomResourceDefinitionOpenAPISchema(schema *apiextensions.JSONSchemaProps, fldPath *field.Path, ssv specStandardValidator) field.ErrorList {
|
||||
allErrs := field.ErrorList{}
|
||||
|
||||
if schema == nil {
|
||||
return allErrs
|
||||
}
|
||||
|
||||
allErrs = append(allErrs, ssv.validate(schema, fldPath)...)
|
||||
|
||||
if schema.UniqueItems == true {
|
||||
allErrs = append(allErrs, field.Forbidden(fldPath.Child("uniqueItems"), "uniqueItems cannot be set to true since the runtime complexity becomes quadratic"))
|
||||
}
|
||||
|
||||
// additionalProperties and properties are mutual exclusive because otherwise they
|
||||
// contradict Kubernetes' API convention to ignore unknown fields.
|
||||
//
|
||||
// In other words:
|
||||
// - properties are for structs,
|
||||
// - additionalProperties are for map[string]interface{}
|
||||
//
|
||||
// Note: when patternProperties is added to OpenAPI some day, this will have to be
|
||||
// restricted like additionalProperties.
|
||||
if schema.AdditionalProperties != nil {
|
||||
if len(schema.Properties) != 0 {
|
||||
if schema.AdditionalProperties.Allows == false || schema.AdditionalProperties.Schema != nil {
|
||||
allErrs = append(allErrs, field.Forbidden(fldPath.Child("additionalProperties"), "additionalProperties and properties are mutual exclusive"))
|
||||
}
|
||||
}
|
||||
allErrs = append(allErrs, ValidateCustomResourceDefinitionOpenAPISchema(schema.AdditionalProperties.Schema, fldPath.Child("additionalProperties"), ssv)...)
|
||||
}
|
||||
|
||||
if len(schema.Properties) != 0 {
|
||||
for property, jsonSchema := range schema.Properties {
|
||||
allErrs = append(allErrs, ValidateCustomResourceDefinitionOpenAPISchema(&jsonSchema, fldPath.Child("properties").Key(property), ssv)...)
|
||||
}
|
||||
}
|
||||
|
||||
if len(schema.PatternProperties) != 0 {
|
||||
for property, jsonSchema := range schema.PatternProperties {
|
||||
allErrs = append(allErrs, ValidateCustomResourceDefinitionOpenAPISchema(&jsonSchema, fldPath.Child("patternProperties").Key(property), ssv)...)
|
||||
}
|
||||
}
|
||||
|
||||
if schema.AdditionalItems != nil {
|
||||
allErrs = append(allErrs, ValidateCustomResourceDefinitionOpenAPISchema(schema.AdditionalItems.Schema, fldPath.Child("additionalItems"), ssv)...)
|
||||
}
|
||||
|
||||
allErrs = append(allErrs, ValidateCustomResourceDefinitionOpenAPISchema(schema.Not, fldPath.Child("not"), ssv)...)
|
||||
|
||||
if len(schema.AllOf) != 0 {
|
||||
for i, jsonSchema := range schema.AllOf {
|
||||
allErrs = append(allErrs, ValidateCustomResourceDefinitionOpenAPISchema(&jsonSchema, fldPath.Child("allOf").Index(i), ssv)...)
|
||||
}
|
||||
}
|
||||
|
||||
if len(schema.OneOf) != 0 {
|
||||
for i, jsonSchema := range schema.OneOf {
|
||||
allErrs = append(allErrs, ValidateCustomResourceDefinitionOpenAPISchema(&jsonSchema, fldPath.Child("oneOf").Index(i), ssv)...)
|
||||
}
|
||||
}
|
||||
|
||||
if len(schema.AnyOf) != 0 {
|
||||
for i, jsonSchema := range schema.AnyOf {
|
||||
allErrs = append(allErrs, ValidateCustomResourceDefinitionOpenAPISchema(&jsonSchema, fldPath.Child("anyOf").Index(i), ssv)...)
|
||||
}
|
||||
}
|
||||
|
||||
if len(schema.Definitions) != 0 {
|
||||
for definition, jsonSchema := range schema.Definitions {
|
||||
allErrs = append(allErrs, ValidateCustomResourceDefinitionOpenAPISchema(&jsonSchema, fldPath.Child("definitions").Key(definition), ssv)...)
|
||||
}
|
||||
}
|
||||
|
||||
if schema.Items != nil {
|
||||
allErrs = append(allErrs, ValidateCustomResourceDefinitionOpenAPISchema(schema.Items.Schema, fldPath.Child("items"), ssv)...)
|
||||
if len(schema.Items.JSONSchemas) != 0 {
|
||||
for i, jsonSchema := range schema.Items.JSONSchemas {
|
||||
allErrs = append(allErrs, ValidateCustomResourceDefinitionOpenAPISchema(&jsonSchema, fldPath.Child("items").Index(i), ssv)...)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if schema.Dependencies != nil {
|
||||
for dependency, jsonSchemaPropsOrStringArray := range schema.Dependencies {
|
||||
allErrs = append(allErrs, ValidateCustomResourceDefinitionOpenAPISchema(jsonSchemaPropsOrStringArray.Schema, fldPath.Child("dependencies").Key(dependency), ssv)...)
|
||||
}
|
||||
}
|
||||
|
||||
return allErrs
|
||||
}
|
||||
|
||||
type specStandardValidatorV3 struct{}
|
||||
|
||||
// validate validates against OpenAPI Schema v3.
|
||||
func (v *specStandardValidatorV3) validate(schema *apiextensions.JSONSchemaProps, fldPath *field.Path) field.ErrorList {
|
||||
allErrs := field.ErrorList{}
|
||||
|
||||
if schema == nil {
|
||||
return allErrs
|
||||
}
|
||||
|
||||
if schema.Default != nil {
|
||||
allErrs = append(allErrs, field.Forbidden(fldPath.Child("default"), "default is not supported"))
|
||||
}
|
||||
|
||||
if schema.ID != "" {
|
||||
allErrs = append(allErrs, field.Forbidden(fldPath.Child("id"), "id is not supported"))
|
||||
}
|
||||
|
||||
if schema.AdditionalItems != nil {
|
||||
allErrs = append(allErrs, field.Forbidden(fldPath.Child("additionalItems"), "additionalItems is not supported"))
|
||||
}
|
||||
|
||||
if len(schema.PatternProperties) != 0 {
|
||||
allErrs = append(allErrs, field.Forbidden(fldPath.Child("patternProperties"), "patternProperties is not supported"))
|
||||
}
|
||||
|
||||
if len(schema.Definitions) != 0 {
|
||||
allErrs = append(allErrs, field.Forbidden(fldPath.Child("definitions"), "definitions is not supported"))
|
||||
}
|
||||
|
||||
if schema.Dependencies != nil {
|
||||
allErrs = append(allErrs, field.Forbidden(fldPath.Child("dependencies"), "dependencies is not supported"))
|
||||
}
|
||||
|
||||
if schema.Ref != nil {
|
||||
allErrs = append(allErrs, field.Forbidden(fldPath.Child("$ref"), "$ref is not supported"))
|
||||
}
|
||||
|
||||
if schema.Type == "null" {
|
||||
allErrs = append(allErrs, field.Forbidden(fldPath.Child("type"), "type cannot be set to null"))
|
||||
}
|
||||
|
||||
if schema.Items != nil && len(schema.Items.JSONSchemas) != 0 {
|
||||
allErrs = append(allErrs, field.Forbidden(fldPath.Child("items"), "items must be a schema object and not an array"))
|
||||
}
|
||||
|
||||
return allErrs
|
||||
}
|
||||
|
||||
// ValidateCustomResourceDefinitionSubresources statically validates
|
||||
func ValidateCustomResourceDefinitionSubresources(subresources *apiextensions.CustomResourceSubresources, fldPath *field.Path) field.ErrorList {
|
||||
allErrs := field.ErrorList{}
|
||||
|
||||
if subresources == nil {
|
||||
return allErrs
|
||||
}
|
||||
|
||||
if subresources.Scale != nil {
|
||||
if len(subresources.Scale.SpecReplicasPath) == 0 {
|
||||
allErrs = append(allErrs, field.Required(fldPath.Child("scale.specReplicasPath"), ""))
|
||||
} else {
|
||||
// should be constrained json path under .spec
|
||||
if errs := validateSimpleJSONPath(subresources.Scale.SpecReplicasPath, fldPath.Child("scale.specReplicasPath")); len(errs) > 0 {
|
||||
allErrs = append(allErrs, errs...)
|
||||
} else if !strings.HasPrefix(subresources.Scale.SpecReplicasPath, ".spec.") {
|
||||
allErrs = append(allErrs, field.Invalid(fldPath.Child("scale.specReplicasPath"), subresources.Scale.SpecReplicasPath, "should be a json path under .spec"))
|
||||
}
|
||||
}
|
||||
|
||||
if len(subresources.Scale.StatusReplicasPath) == 0 {
|
||||
allErrs = append(allErrs, field.Required(fldPath.Child("scale.statusReplicasPath"), ""))
|
||||
} else {
|
||||
// should be constrained json path under .status
|
||||
if errs := validateSimpleJSONPath(subresources.Scale.StatusReplicasPath, fldPath.Child("scale.statusReplicasPath")); len(errs) > 0 {
|
||||
allErrs = append(allErrs, errs...)
|
||||
} else if !strings.HasPrefix(subresources.Scale.StatusReplicasPath, ".status.") {
|
||||
allErrs = append(allErrs, field.Invalid(fldPath.Child("scale.statusReplicasPath"), subresources.Scale.StatusReplicasPath, "should be a json path under .status"))
|
||||
}
|
||||
}
|
||||
|
||||
// if labelSelectorPath is present, it should be a constrained json path under .status
|
||||
if subresources.Scale.LabelSelectorPath != nil && len(*subresources.Scale.LabelSelectorPath) > 0 {
|
||||
if errs := validateSimpleJSONPath(*subresources.Scale.LabelSelectorPath, fldPath.Child("scale.labelSelectorPath")); len(errs) > 0 {
|
||||
allErrs = append(allErrs, errs...)
|
||||
} else if !strings.HasPrefix(*subresources.Scale.LabelSelectorPath, ".status.") {
|
||||
allErrs = append(allErrs, field.Invalid(fldPath.Child("scale.labelSelectorPath"), subresources.Scale.LabelSelectorPath, "should be a json path under .status"))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return allErrs
|
||||
}
|
||||
|
||||
func validateSimpleJSONPath(s string, fldPath *field.Path) field.ErrorList {
|
||||
allErrs := field.ErrorList{}
|
||||
|
||||
switch {
|
||||
case len(s) == 0:
|
||||
allErrs = append(allErrs, field.Invalid(fldPath, s, "must not be empty"))
|
||||
case s[0] != '.':
|
||||
allErrs = append(allErrs, field.Invalid(fldPath, s, "must be a simple json path starting with ."))
|
||||
case s != ".":
|
||||
if cs := strings.Split(s[1:], "."); len(cs) < 1 {
|
||||
allErrs = append(allErrs, field.Invalid(fldPath, s, "must be a json path in the dot notation"))
|
||||
}
|
||||
}
|
||||
|
||||
return allErrs
|
||||
}
|
||||
|
||||
var allowedFieldsAtRootSchema = []string{"Description", "Type", "Format", "Title", "Maximum", "ExclusiveMaximum", "Minimum", "ExclusiveMinimum", "MaxLength", "MinLength", "Pattern", "MaxItems", "MinItems", "UniqueItems", "MultipleOf", "Required", "Items", "Properties", "ExternalDocs", "Example"}
|
||||
|
||||
func allowedAtRootSchema(field string) bool {
|
||||
for _, v := range allowedFieldsAtRootSchema {
|
||||
if field == v {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
926
vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/validation/validation_test.go
generated
vendored
Normal file
926
vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/validation/validation_test.go
generated
vendored
Normal file
@@ -0,0 +1,926 @@
|
||||
/*
|
||||
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 validation
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"k8s.io/apiextensions-apiserver/pkg/apis/apiextensions"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/util/validation/field"
|
||||
)
|
||||
|
||||
type validationMatch struct {
|
||||
path *field.Path
|
||||
errorType field.ErrorType
|
||||
}
|
||||
|
||||
func required(path ...string) validationMatch {
|
||||
return validationMatch{path: field.NewPath(path[0], path[1:]...), errorType: field.ErrorTypeRequired}
|
||||
}
|
||||
func invalid(path ...string) validationMatch {
|
||||
return validationMatch{path: field.NewPath(path[0], path[1:]...), errorType: field.ErrorTypeInvalid}
|
||||
}
|
||||
func unsupported(path ...string) validationMatch {
|
||||
return validationMatch{path: field.NewPath(path[0], path[1:]...), errorType: field.ErrorTypeNotSupported}
|
||||
}
|
||||
func immutable(path ...string) validationMatch {
|
||||
return validationMatch{path: field.NewPath(path[0], path[1:]...), errorType: field.ErrorTypeInvalid}
|
||||
}
|
||||
func forbidden(path ...string) validationMatch {
|
||||
return validationMatch{path: field.NewPath(path[0], path[1:]...), errorType: field.ErrorTypeForbidden}
|
||||
}
|
||||
|
||||
func (v validationMatch) matches(err *field.Error) bool {
|
||||
return err.Type == v.errorType && err.Field == v.path.String()
|
||||
}
|
||||
|
||||
func TestValidateCustomResourceDefinition(t *testing.T) {
|
||||
singleVersionList := []apiextensions.CustomResourceDefinitionVersion{
|
||||
{
|
||||
Name: "version",
|
||||
Served: true,
|
||||
Storage: true,
|
||||
},
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
resource *apiextensions.CustomResourceDefinition
|
||||
errors []validationMatch
|
||||
}{
|
||||
{
|
||||
name: "no_storage_version",
|
||||
resource: &apiextensions.CustomResourceDefinition{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: "plural.group.com"},
|
||||
Spec: apiextensions.CustomResourceDefinitionSpec{
|
||||
Group: "group.com",
|
||||
Scope: apiextensions.ResourceScope("Cluster"),
|
||||
Names: apiextensions.CustomResourceDefinitionNames{
|
||||
Plural: "plural",
|
||||
Singular: "singular",
|
||||
Kind: "Plural",
|
||||
ListKind: "PluralList",
|
||||
},
|
||||
Versions: []apiextensions.CustomResourceDefinitionVersion{
|
||||
{
|
||||
Name: "version",
|
||||
Served: true,
|
||||
Storage: false,
|
||||
},
|
||||
{
|
||||
Name: "version2",
|
||||
Served: true,
|
||||
Storage: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
Status: apiextensions.CustomResourceDefinitionStatus{
|
||||
StoredVersions: []string{"version"},
|
||||
},
|
||||
},
|
||||
errors: []validationMatch{
|
||||
invalid("spec", "versions"),
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "multiple_storage_version",
|
||||
resource: &apiextensions.CustomResourceDefinition{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: "plural.group.com"},
|
||||
Spec: apiextensions.CustomResourceDefinitionSpec{
|
||||
Group: "group.com",
|
||||
Scope: apiextensions.ResourceScope("Cluster"),
|
||||
Names: apiextensions.CustomResourceDefinitionNames{
|
||||
Plural: "plural",
|
||||
Singular: "singular",
|
||||
Kind: "Plural",
|
||||
ListKind: "PluralList",
|
||||
},
|
||||
Versions: []apiextensions.CustomResourceDefinitionVersion{
|
||||
{
|
||||
Name: "version",
|
||||
Served: true,
|
||||
Storage: true,
|
||||
},
|
||||
{
|
||||
Name: "version2",
|
||||
Served: true,
|
||||
Storage: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
Status: apiextensions.CustomResourceDefinitionStatus{
|
||||
StoredVersions: []string{"version"},
|
||||
},
|
||||
},
|
||||
errors: []validationMatch{
|
||||
invalid("spec", "versions"),
|
||||
invalid("status", "storedVersions"),
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "missing_storage_version_in_stored_versions",
|
||||
resource: &apiextensions.CustomResourceDefinition{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: "plural.group.com"},
|
||||
Spec: apiextensions.CustomResourceDefinitionSpec{
|
||||
Group: "group.com",
|
||||
Scope: apiextensions.ResourceScope("Cluster"),
|
||||
Names: apiextensions.CustomResourceDefinitionNames{
|
||||
Plural: "plural",
|
||||
Singular: "singular",
|
||||
Kind: "Plural",
|
||||
ListKind: "PluralList",
|
||||
},
|
||||
Versions: []apiextensions.CustomResourceDefinitionVersion{
|
||||
{
|
||||
Name: "version",
|
||||
Served: true,
|
||||
Storage: false,
|
||||
},
|
||||
{
|
||||
Name: "version2",
|
||||
Served: true,
|
||||
Storage: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
Status: apiextensions.CustomResourceDefinitionStatus{
|
||||
StoredVersions: []string{"version"},
|
||||
},
|
||||
},
|
||||
errors: []validationMatch{
|
||||
invalid("status", "storedVersions"),
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "empty_stored_version",
|
||||
resource: &apiextensions.CustomResourceDefinition{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: "plural.group.com"},
|
||||
Spec: apiextensions.CustomResourceDefinitionSpec{
|
||||
Group: "group.com",
|
||||
Scope: apiextensions.ResourceScope("Cluster"),
|
||||
Names: apiextensions.CustomResourceDefinitionNames{
|
||||
Plural: "plural",
|
||||
Singular: "singular",
|
||||
Kind: "Plural",
|
||||
ListKind: "PluralList",
|
||||
},
|
||||
Versions: []apiextensions.CustomResourceDefinitionVersion{
|
||||
{
|
||||
Name: "version",
|
||||
Served: true,
|
||||
Storage: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
Status: apiextensions.CustomResourceDefinitionStatus{
|
||||
StoredVersions: []string{},
|
||||
},
|
||||
},
|
||||
errors: []validationMatch{
|
||||
invalid("status", "storedVersions"),
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "mismatched name",
|
||||
resource: &apiextensions.CustomResourceDefinition{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: "plural.not.group.com"},
|
||||
Spec: apiextensions.CustomResourceDefinitionSpec{
|
||||
Group: "group.com",
|
||||
Names: apiextensions.CustomResourceDefinitionNames{
|
||||
Plural: "plural",
|
||||
},
|
||||
},
|
||||
},
|
||||
errors: []validationMatch{
|
||||
invalid("status", "storedVersions"),
|
||||
invalid("metadata", "name"),
|
||||
invalid("spec", "versions"),
|
||||
required("spec", "scope"),
|
||||
required("spec", "names", "singular"),
|
||||
required("spec", "names", "kind"),
|
||||
required("spec", "names", "listKind"),
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "missing values",
|
||||
resource: &apiextensions.CustomResourceDefinition{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: "plural.group.com"},
|
||||
},
|
||||
errors: []validationMatch{
|
||||
invalid("status", "storedVersions"),
|
||||
invalid("metadata", "name"),
|
||||
invalid("spec", "versions"),
|
||||
required("spec", "group"),
|
||||
required("spec", "scope"),
|
||||
required("spec", "names", "plural"),
|
||||
required("spec", "names", "singular"),
|
||||
required("spec", "names", "kind"),
|
||||
required("spec", "names", "listKind"),
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "bad names 01",
|
||||
resource: &apiextensions.CustomResourceDefinition{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: "plural.group"},
|
||||
Spec: apiextensions.CustomResourceDefinitionSpec{
|
||||
Group: "group",
|
||||
Version: "ve()*rsion",
|
||||
Scope: apiextensions.ResourceScope("foo"),
|
||||
Names: apiextensions.CustomResourceDefinitionNames{
|
||||
Plural: "pl()*ural",
|
||||
Singular: "value()*a",
|
||||
Kind: "value()*a",
|
||||
ListKind: "value()*a",
|
||||
},
|
||||
},
|
||||
Status: apiextensions.CustomResourceDefinitionStatus{
|
||||
AcceptedNames: apiextensions.CustomResourceDefinitionNames{
|
||||
Plural: "pl()*ural",
|
||||
Singular: "value()*a",
|
||||
Kind: "value()*a",
|
||||
ListKind: "value()*a",
|
||||
},
|
||||
},
|
||||
},
|
||||
errors: []validationMatch{
|
||||
invalid("status", "storedVersions"),
|
||||
invalid("metadata", "name"),
|
||||
invalid("spec", "group"),
|
||||
unsupported("spec", "scope"),
|
||||
invalid("spec", "names", "plural"),
|
||||
invalid("spec", "names", "singular"),
|
||||
invalid("spec", "names", "kind"),
|
||||
invalid("spec", "names", "listKind"), // invalid format
|
||||
invalid("spec", "names", "listKind"), // kind == listKind
|
||||
invalid("status", "acceptedNames", "plural"),
|
||||
invalid("status", "acceptedNames", "singular"),
|
||||
invalid("status", "acceptedNames", "kind"),
|
||||
invalid("status", "acceptedNames", "listKind"), // invalid format
|
||||
invalid("status", "acceptedNames", "listKind"), // kind == listKind
|
||||
invalid("spec", "versions"),
|
||||
invalid("spec", "version"),
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "bad names 02",
|
||||
resource: &apiextensions.CustomResourceDefinition{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: "plural.group"},
|
||||
Spec: apiextensions.CustomResourceDefinitionSpec{
|
||||
Group: "group.c(*&om",
|
||||
Version: "version",
|
||||
Versions: singleVersionList,
|
||||
Names: apiextensions.CustomResourceDefinitionNames{
|
||||
Plural: "plural",
|
||||
Singular: "singular",
|
||||
Kind: "matching",
|
||||
ListKind: "matching",
|
||||
},
|
||||
},
|
||||
Status: apiextensions.CustomResourceDefinitionStatus{
|
||||
AcceptedNames: apiextensions.CustomResourceDefinitionNames{
|
||||
Plural: "plural",
|
||||
Singular: "singular",
|
||||
Kind: "matching",
|
||||
ListKind: "matching",
|
||||
},
|
||||
StoredVersions: []string{"version"},
|
||||
},
|
||||
},
|
||||
errors: []validationMatch{
|
||||
invalid("metadata", "name"),
|
||||
invalid("spec", "group"),
|
||||
required("spec", "scope"),
|
||||
invalid("spec", "names", "listKind"),
|
||||
invalid("status", "acceptedNames", "listKind"),
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "additionalProperties and properties forbidden",
|
||||
resource: &apiextensions.CustomResourceDefinition{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: "plural.group.com"},
|
||||
Spec: apiextensions.CustomResourceDefinitionSpec{
|
||||
Group: "group.com",
|
||||
Version: "version",
|
||||
Versions: singleVersionList,
|
||||
Scope: apiextensions.NamespaceScoped,
|
||||
Names: apiextensions.CustomResourceDefinitionNames{
|
||||
Plural: "plural",
|
||||
Singular: "singular",
|
||||
Kind: "Plural",
|
||||
ListKind: "PluralList",
|
||||
},
|
||||
Validation: &apiextensions.CustomResourceValidation{
|
||||
OpenAPIV3Schema: &apiextensions.JSONSchemaProps{
|
||||
Properties: map[string]apiextensions.JSONSchemaProps{
|
||||
"foo": {},
|
||||
},
|
||||
AdditionalProperties: &apiextensions.JSONSchemaPropsOrBool{Allows: false},
|
||||
},
|
||||
},
|
||||
},
|
||||
Status: apiextensions.CustomResourceDefinitionStatus{
|
||||
StoredVersions: []string{"version"},
|
||||
},
|
||||
},
|
||||
errors: []validationMatch{
|
||||
forbidden("spec", "validation", "openAPIV3Schema", "additionalProperties"),
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "additionalProperties without properties allowed (map[string]string)",
|
||||
resource: &apiextensions.CustomResourceDefinition{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: "plural.group.com"},
|
||||
Spec: apiextensions.CustomResourceDefinitionSpec{
|
||||
Group: "group.com",
|
||||
Version: "version",
|
||||
Versions: singleVersionList,
|
||||
Scope: apiextensions.NamespaceScoped,
|
||||
Names: apiextensions.CustomResourceDefinitionNames{
|
||||
Plural: "plural",
|
||||
Singular: "singular",
|
||||
Kind: "Plural",
|
||||
ListKind: "PluralList",
|
||||
},
|
||||
Validation: &apiextensions.CustomResourceValidation{
|
||||
OpenAPIV3Schema: &apiextensions.JSONSchemaProps{
|
||||
AdditionalProperties: &apiextensions.JSONSchemaPropsOrBool{
|
||||
Allows: true,
|
||||
Schema: &apiextensions.JSONSchemaProps{
|
||||
Type: "string",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
Status: apiextensions.CustomResourceDefinitionStatus{
|
||||
StoredVersions: []string{"version"},
|
||||
},
|
||||
},
|
||||
errors: []validationMatch{},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range tests {
|
||||
errs := ValidateCustomResourceDefinition(tc.resource)
|
||||
seenErrs := make([]bool, len(errs))
|
||||
|
||||
for _, expectedError := range tc.errors {
|
||||
found := false
|
||||
for i, err := range errs {
|
||||
if expectedError.matches(err) && !seenErrs[i] {
|
||||
found = true
|
||||
seenErrs[i] = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if !found {
|
||||
t.Errorf("%s: expected %v at %v, got %v", tc.name, expectedError.errorType, expectedError.path.String(), errs)
|
||||
}
|
||||
}
|
||||
|
||||
for i, seen := range seenErrs {
|
||||
if !seen {
|
||||
t.Errorf("%s: unexpected error: %v", tc.name, errs[i])
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestValidateCustomResourceDefinitionUpdate(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
old *apiextensions.CustomResourceDefinition
|
||||
resource *apiextensions.CustomResourceDefinition
|
||||
errors []validationMatch
|
||||
}{
|
||||
{
|
||||
name: "unchanged",
|
||||
old: &apiextensions.CustomResourceDefinition{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "plural.group.com",
|
||||
ResourceVersion: "42",
|
||||
},
|
||||
Spec: apiextensions.CustomResourceDefinitionSpec{
|
||||
Group: "group.com",
|
||||
Version: "version",
|
||||
Versions: []apiextensions.CustomResourceDefinitionVersion{
|
||||
{
|
||||
Name: "version",
|
||||
Served: true,
|
||||
Storage: true,
|
||||
},
|
||||
},
|
||||
Scope: apiextensions.ResourceScope("Cluster"),
|
||||
Names: apiextensions.CustomResourceDefinitionNames{
|
||||
Plural: "plural",
|
||||
Singular: "singular",
|
||||
Kind: "kind",
|
||||
ListKind: "listkind",
|
||||
},
|
||||
},
|
||||
Status: apiextensions.CustomResourceDefinitionStatus{
|
||||
AcceptedNames: apiextensions.CustomResourceDefinitionNames{
|
||||
Plural: "plural",
|
||||
Singular: "singular",
|
||||
Kind: "kind",
|
||||
ListKind: "listkind",
|
||||
},
|
||||
},
|
||||
},
|
||||
resource: &apiextensions.CustomResourceDefinition{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "plural.group.com",
|
||||
ResourceVersion: "42",
|
||||
},
|
||||
Spec: apiextensions.CustomResourceDefinitionSpec{
|
||||
Group: "group.com",
|
||||
Version: "version",
|
||||
Versions: []apiextensions.CustomResourceDefinitionVersion{
|
||||
{
|
||||
Name: "version",
|
||||
Served: true,
|
||||
Storage: true,
|
||||
},
|
||||
},
|
||||
Scope: apiextensions.ResourceScope("Cluster"),
|
||||
Names: apiextensions.CustomResourceDefinitionNames{
|
||||
Plural: "plural",
|
||||
Singular: "singular",
|
||||
Kind: "kind",
|
||||
ListKind: "listkind",
|
||||
},
|
||||
},
|
||||
Status: apiextensions.CustomResourceDefinitionStatus{
|
||||
AcceptedNames: apiextensions.CustomResourceDefinitionNames{
|
||||
Plural: "plural",
|
||||
Singular: "singular",
|
||||
Kind: "kind",
|
||||
ListKind: "listkind",
|
||||
},
|
||||
StoredVersions: []string{"version"},
|
||||
},
|
||||
},
|
||||
errors: []validationMatch{},
|
||||
},
|
||||
{
|
||||
name: "unchanged-established",
|
||||
old: &apiextensions.CustomResourceDefinition{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "plural.group.com",
|
||||
ResourceVersion: "42",
|
||||
},
|
||||
Spec: apiextensions.CustomResourceDefinitionSpec{
|
||||
Group: "group.com",
|
||||
Version: "version",
|
||||
Versions: []apiextensions.CustomResourceDefinitionVersion{
|
||||
{
|
||||
Name: "version",
|
||||
Served: true,
|
||||
Storage: true,
|
||||
},
|
||||
},
|
||||
Scope: apiextensions.ResourceScope("Cluster"),
|
||||
Names: apiextensions.CustomResourceDefinitionNames{
|
||||
Plural: "plural",
|
||||
Singular: "singular",
|
||||
Kind: "kind",
|
||||
ListKind: "listkind",
|
||||
},
|
||||
},
|
||||
Status: apiextensions.CustomResourceDefinitionStatus{
|
||||
AcceptedNames: apiextensions.CustomResourceDefinitionNames{
|
||||
Plural: "plural",
|
||||
Singular: "singular",
|
||||
Kind: "kind",
|
||||
ListKind: "listkind",
|
||||
},
|
||||
Conditions: []apiextensions.CustomResourceDefinitionCondition{
|
||||
{Type: apiextensions.Established, Status: apiextensions.ConditionTrue},
|
||||
},
|
||||
},
|
||||
},
|
||||
resource: &apiextensions.CustomResourceDefinition{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "plural.group.com",
|
||||
ResourceVersion: "42",
|
||||
},
|
||||
Spec: apiextensions.CustomResourceDefinitionSpec{
|
||||
Group: "group.com",
|
||||
Version: "version",
|
||||
Versions: []apiextensions.CustomResourceDefinitionVersion{
|
||||
{
|
||||
Name: "version",
|
||||
Served: true,
|
||||
Storage: true,
|
||||
},
|
||||
},
|
||||
Scope: apiextensions.ResourceScope("Cluster"),
|
||||
Names: apiextensions.CustomResourceDefinitionNames{
|
||||
Plural: "plural",
|
||||
Singular: "singular",
|
||||
Kind: "kind",
|
||||
ListKind: "listkind",
|
||||
},
|
||||
},
|
||||
Status: apiextensions.CustomResourceDefinitionStatus{
|
||||
AcceptedNames: apiextensions.CustomResourceDefinitionNames{
|
||||
Plural: "plural",
|
||||
Singular: "singular",
|
||||
Kind: "kind",
|
||||
ListKind: "listkind",
|
||||
},
|
||||
StoredVersions: []string{"version"},
|
||||
},
|
||||
},
|
||||
errors: []validationMatch{},
|
||||
},
|
||||
{
|
||||
name: "version-deleted",
|
||||
old: &apiextensions.CustomResourceDefinition{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "plural.group.com",
|
||||
ResourceVersion: "42",
|
||||
},
|
||||
Spec: apiextensions.CustomResourceDefinitionSpec{
|
||||
Group: "group.com",
|
||||
Version: "version",
|
||||
Versions: []apiextensions.CustomResourceDefinitionVersion{
|
||||
{
|
||||
Name: "version",
|
||||
Served: true,
|
||||
Storage: true,
|
||||
},
|
||||
{
|
||||
Name: "version2",
|
||||
Served: true,
|
||||
Storage: false,
|
||||
},
|
||||
},
|
||||
Scope: apiextensions.ResourceScope("Cluster"),
|
||||
Names: apiextensions.CustomResourceDefinitionNames{
|
||||
Plural: "plural",
|
||||
Singular: "singular",
|
||||
Kind: "kind",
|
||||
ListKind: "listkind",
|
||||
},
|
||||
},
|
||||
Status: apiextensions.CustomResourceDefinitionStatus{
|
||||
AcceptedNames: apiextensions.CustomResourceDefinitionNames{
|
||||
Plural: "plural",
|
||||
Singular: "singular",
|
||||
Kind: "kind",
|
||||
ListKind: "listkind",
|
||||
},
|
||||
StoredVersions: []string{"version", "version2"},
|
||||
Conditions: []apiextensions.CustomResourceDefinitionCondition{
|
||||
{Type: apiextensions.Established, Status: apiextensions.ConditionTrue},
|
||||
},
|
||||
},
|
||||
},
|
||||
resource: &apiextensions.CustomResourceDefinition{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "plural.group.com",
|
||||
ResourceVersion: "42",
|
||||
},
|
||||
Spec: apiextensions.CustomResourceDefinitionSpec{
|
||||
Group: "group.com",
|
||||
Version: "version",
|
||||
Versions: []apiextensions.CustomResourceDefinitionVersion{
|
||||
{
|
||||
Name: "version",
|
||||
Served: true,
|
||||
Storage: true,
|
||||
},
|
||||
},
|
||||
Scope: apiextensions.ResourceScope("Cluster"),
|
||||
Names: apiextensions.CustomResourceDefinitionNames{
|
||||
Plural: "plural",
|
||||
Singular: "singular",
|
||||
Kind: "kind",
|
||||
ListKind: "listkind",
|
||||
},
|
||||
},
|
||||
Status: apiextensions.CustomResourceDefinitionStatus{
|
||||
AcceptedNames: apiextensions.CustomResourceDefinitionNames{
|
||||
Plural: "plural",
|
||||
Singular: "singular",
|
||||
Kind: "kind",
|
||||
ListKind: "listkind",
|
||||
},
|
||||
StoredVersions: []string{"version", "version2"},
|
||||
},
|
||||
},
|
||||
errors: []validationMatch{
|
||||
invalid("status", "storedVersions[1]"),
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "changes",
|
||||
old: &apiextensions.CustomResourceDefinition{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "plural.group.com",
|
||||
ResourceVersion: "42",
|
||||
},
|
||||
Spec: apiextensions.CustomResourceDefinitionSpec{
|
||||
Group: "group.com",
|
||||
Version: "version",
|
||||
Versions: []apiextensions.CustomResourceDefinitionVersion{
|
||||
{
|
||||
Name: "version",
|
||||
Served: true,
|
||||
Storage: true,
|
||||
},
|
||||
},
|
||||
Scope: apiextensions.ResourceScope("Cluster"),
|
||||
Names: apiextensions.CustomResourceDefinitionNames{
|
||||
Plural: "plural",
|
||||
Singular: "singular",
|
||||
Kind: "kind",
|
||||
ListKind: "listkind",
|
||||
},
|
||||
},
|
||||
Status: apiextensions.CustomResourceDefinitionStatus{
|
||||
AcceptedNames: apiextensions.CustomResourceDefinitionNames{
|
||||
Plural: "plural",
|
||||
Singular: "singular",
|
||||
Kind: "kind",
|
||||
ListKind: "listkind",
|
||||
},
|
||||
Conditions: []apiextensions.CustomResourceDefinitionCondition{
|
||||
{Type: apiextensions.Established, Status: apiextensions.ConditionFalse},
|
||||
},
|
||||
},
|
||||
},
|
||||
resource: &apiextensions.CustomResourceDefinition{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "plural.group.com",
|
||||
ResourceVersion: "42",
|
||||
},
|
||||
Spec: apiextensions.CustomResourceDefinitionSpec{
|
||||
Group: "abc.com",
|
||||
Version: "version2",
|
||||
Versions: []apiextensions.CustomResourceDefinitionVersion{
|
||||
{
|
||||
Name: "version2",
|
||||
Served: true,
|
||||
Storage: true,
|
||||
},
|
||||
},
|
||||
Scope: apiextensions.ResourceScope("Namespaced"),
|
||||
Names: apiextensions.CustomResourceDefinitionNames{
|
||||
Plural: "plural2",
|
||||
Singular: "singular2",
|
||||
Kind: "kind2",
|
||||
ListKind: "listkind2",
|
||||
},
|
||||
},
|
||||
Status: apiextensions.CustomResourceDefinitionStatus{
|
||||
AcceptedNames: apiextensions.CustomResourceDefinitionNames{
|
||||
Plural: "plural2",
|
||||
Singular: "singular2",
|
||||
Kind: "kind2",
|
||||
ListKind: "listkind2",
|
||||
},
|
||||
StoredVersions: []string{"version2"},
|
||||
},
|
||||
},
|
||||
errors: []validationMatch{
|
||||
immutable("spec", "group"),
|
||||
immutable("spec", "names", "plural"),
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "changes-established",
|
||||
old: &apiextensions.CustomResourceDefinition{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "plural.group.com",
|
||||
ResourceVersion: "42",
|
||||
},
|
||||
Spec: apiextensions.CustomResourceDefinitionSpec{
|
||||
Group: "group.com",
|
||||
Version: "version",
|
||||
Versions: []apiextensions.CustomResourceDefinitionVersion{
|
||||
{
|
||||
Name: "version",
|
||||
Served: true,
|
||||
Storage: true,
|
||||
},
|
||||
},
|
||||
Scope: apiextensions.ResourceScope("Cluster"),
|
||||
Names: apiextensions.CustomResourceDefinitionNames{
|
||||
Plural: "plural",
|
||||
Singular: "singular",
|
||||
Kind: "kind",
|
||||
ListKind: "listkind",
|
||||
},
|
||||
},
|
||||
Status: apiextensions.CustomResourceDefinitionStatus{
|
||||
AcceptedNames: apiextensions.CustomResourceDefinitionNames{
|
||||
Plural: "plural",
|
||||
Singular: "singular",
|
||||
Kind: "kind",
|
||||
ListKind: "listkind",
|
||||
},
|
||||
Conditions: []apiextensions.CustomResourceDefinitionCondition{
|
||||
{Type: apiextensions.Established, Status: apiextensions.ConditionTrue},
|
||||
},
|
||||
},
|
||||
},
|
||||
resource: &apiextensions.CustomResourceDefinition{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "plural.group.com",
|
||||
ResourceVersion: "42",
|
||||
},
|
||||
Spec: apiextensions.CustomResourceDefinitionSpec{
|
||||
Group: "abc.com",
|
||||
Version: "version2",
|
||||
Versions: []apiextensions.CustomResourceDefinitionVersion{
|
||||
{
|
||||
Name: "version2",
|
||||
Served: true,
|
||||
Storage: true,
|
||||
},
|
||||
},
|
||||
Scope: apiextensions.ResourceScope("Namespaced"),
|
||||
Names: apiextensions.CustomResourceDefinitionNames{
|
||||
Plural: "plural2",
|
||||
Singular: "singular2",
|
||||
Kind: "kind2",
|
||||
ListKind: "listkind2",
|
||||
},
|
||||
},
|
||||
Status: apiextensions.CustomResourceDefinitionStatus{
|
||||
AcceptedNames: apiextensions.CustomResourceDefinitionNames{
|
||||
Plural: "plural2",
|
||||
Singular: "singular2",
|
||||
Kind: "kind2",
|
||||
ListKind: "listkind2",
|
||||
},
|
||||
StoredVersions: []string{"version2"},
|
||||
},
|
||||
},
|
||||
errors: []validationMatch{
|
||||
immutable("spec", "group"),
|
||||
immutable("spec", "scope"),
|
||||
immutable("spec", "names", "kind"),
|
||||
immutable("spec", "names", "plural"),
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range tests {
|
||||
errs := ValidateCustomResourceDefinitionUpdate(tc.resource, tc.old)
|
||||
seenErrs := make([]bool, len(errs))
|
||||
|
||||
for _, expectedError := range tc.errors {
|
||||
found := false
|
||||
for i, err := range errs {
|
||||
if expectedError.matches(err) && !seenErrs[i] {
|
||||
found = true
|
||||
seenErrs[i] = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if !found {
|
||||
t.Errorf("%s: expected %v at %v, got %v", tc.name, expectedError.errorType, expectedError.path.String(), errs)
|
||||
}
|
||||
}
|
||||
|
||||
for i, seen := range seenErrs {
|
||||
if !seen {
|
||||
t.Errorf("%s: unexpected error: %v", tc.name, errs[i])
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestValidateCustomResourceDefinitionValidation(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
input apiextensions.CustomResourceValidation
|
||||
statusEnabled bool
|
||||
wantError bool
|
||||
}{
|
||||
{
|
||||
name: "empty",
|
||||
input: apiextensions.CustomResourceValidation{},
|
||||
wantError: false,
|
||||
},
|
||||
{
|
||||
name: "empty with status",
|
||||
input: apiextensions.CustomResourceValidation{},
|
||||
statusEnabled: true,
|
||||
wantError: false,
|
||||
},
|
||||
{
|
||||
name: "root type without status",
|
||||
input: apiextensions.CustomResourceValidation{
|
||||
OpenAPIV3Schema: &apiextensions.JSONSchemaProps{
|
||||
Type: "string",
|
||||
},
|
||||
},
|
||||
statusEnabled: false,
|
||||
wantError: false,
|
||||
},
|
||||
{
|
||||
name: "root type having invalid value, with status",
|
||||
input: apiextensions.CustomResourceValidation{
|
||||
OpenAPIV3Schema: &apiextensions.JSONSchemaProps{
|
||||
Type: "string",
|
||||
},
|
||||
},
|
||||
statusEnabled: true,
|
||||
wantError: true,
|
||||
},
|
||||
{
|
||||
name: "non-allowed root field with status",
|
||||
input: apiextensions.CustomResourceValidation{
|
||||
OpenAPIV3Schema: &apiextensions.JSONSchemaProps{
|
||||
AnyOf: []apiextensions.JSONSchemaProps{
|
||||
{
|
||||
Description: "First schema",
|
||||
},
|
||||
{
|
||||
Description: "Second schema",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
statusEnabled: true,
|
||||
wantError: true,
|
||||
},
|
||||
{
|
||||
name: "all allowed fields at the root of the schema with status",
|
||||
input: apiextensions.CustomResourceValidation{
|
||||
OpenAPIV3Schema: &apiextensions.JSONSchemaProps{
|
||||
Description: "This is a description",
|
||||
Type: "object",
|
||||
Format: "date-time",
|
||||
Title: "This is a title",
|
||||
Maximum: float64Ptr(10),
|
||||
ExclusiveMaximum: true,
|
||||
Minimum: float64Ptr(5),
|
||||
ExclusiveMinimum: true,
|
||||
MaxLength: int64Ptr(10),
|
||||
MinLength: int64Ptr(5),
|
||||
Pattern: "^[a-z]$",
|
||||
MaxItems: int64Ptr(10),
|
||||
MinItems: int64Ptr(5),
|
||||
MultipleOf: float64Ptr(3),
|
||||
Required: []string{"spec", "status"},
|
||||
Items: &apiextensions.JSONSchemaPropsOrArray{
|
||||
Schema: &apiextensions.JSONSchemaProps{
|
||||
Description: "This is a schema nested under Items",
|
||||
},
|
||||
},
|
||||
Properties: map[string]apiextensions.JSONSchemaProps{
|
||||
"spec": {},
|
||||
"status": {},
|
||||
},
|
||||
ExternalDocs: &apiextensions.ExternalDocumentation{
|
||||
Description: "This is an external documentation description",
|
||||
},
|
||||
Example: &example,
|
||||
},
|
||||
},
|
||||
statusEnabled: true,
|
||||
wantError: false,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
got := ValidateCustomResourceDefinitionValidation(&tt.input, tt.statusEnabled, field.NewPath("spec", "validation"))
|
||||
if !tt.wantError && len(got) > 0 {
|
||||
t.Errorf("Expected no error, but got: %v", got)
|
||||
} else if tt.wantError && len(got) == 0 {
|
||||
t.Error("Expected error, but got none")
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
var example = apiextensions.JSON(`"This is an example"`)
|
||||
|
||||
func float64Ptr(f float64) *float64 {
|
||||
return &f
|
||||
}
|
||||
|
||||
func int64Ptr(f int64) *int64 {
|
||||
return &f
|
||||
}
|
||||
449
vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/zz_generated.deepcopy.go
generated
vendored
Normal file
449
vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/zz_generated.deepcopy.go
generated
vendored
Normal file
@@ -0,0 +1,449 @@
|
||||
// +build !ignore_autogenerated
|
||||
|
||||
/*
|
||||
Copyright 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.
|
||||
*/
|
||||
|
||||
// Code generated by deepcopy-gen. DO NOT EDIT.
|
||||
|
||||
package apiextensions
|
||||
|
||||
import (
|
||||
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.
|
||||
func (in *CustomResourceDefinition) DeepCopyInto(out *CustomResourceDefinition) {
|
||||
*out = *in
|
||||
out.TypeMeta = in.TypeMeta
|
||||
in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
|
||||
in.Spec.DeepCopyInto(&out.Spec)
|
||||
in.Status.DeepCopyInto(&out.Status)
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CustomResourceDefinition.
|
||||
func (in *CustomResourceDefinition) DeepCopy() *CustomResourceDefinition {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(CustomResourceDefinition)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
|
||||
func (in *CustomResourceDefinition) DeepCopyObject() runtime.Object {
|
||||
if c := in.DeepCopy(); c != nil {
|
||||
return c
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *CustomResourceDefinitionCondition) DeepCopyInto(out *CustomResourceDefinitionCondition) {
|
||||
*out = *in
|
||||
in.LastTransitionTime.DeepCopyInto(&out.LastTransitionTime)
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CustomResourceDefinitionCondition.
|
||||
func (in *CustomResourceDefinitionCondition) DeepCopy() *CustomResourceDefinitionCondition {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(CustomResourceDefinitionCondition)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *CustomResourceDefinitionList) DeepCopyInto(out *CustomResourceDefinitionList) {
|
||||
*out = *in
|
||||
out.TypeMeta = in.TypeMeta
|
||||
out.ListMeta = in.ListMeta
|
||||
if in.Items != nil {
|
||||
in, out := &in.Items, &out.Items
|
||||
*out = make([]CustomResourceDefinition, len(*in))
|
||||
for i := range *in {
|
||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CustomResourceDefinitionList.
|
||||
func (in *CustomResourceDefinitionList) DeepCopy() *CustomResourceDefinitionList {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(CustomResourceDefinitionList)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
|
||||
func (in *CustomResourceDefinitionList) DeepCopyObject() runtime.Object {
|
||||
if c := in.DeepCopy(); c != nil {
|
||||
return c
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *CustomResourceDefinitionNames) DeepCopyInto(out *CustomResourceDefinitionNames) {
|
||||
*out = *in
|
||||
if in.ShortNames != nil {
|
||||
in, out := &in.ShortNames, &out.ShortNames
|
||||
*out = make([]string, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
if in.Categories != nil {
|
||||
in, out := &in.Categories, &out.Categories
|
||||
*out = make([]string, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CustomResourceDefinitionNames.
|
||||
func (in *CustomResourceDefinitionNames) DeepCopy() *CustomResourceDefinitionNames {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(CustomResourceDefinitionNames)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *CustomResourceDefinitionSpec) DeepCopyInto(out *CustomResourceDefinitionSpec) {
|
||||
*out = *in
|
||||
in.Names.DeepCopyInto(&out.Names)
|
||||
if in.Validation != nil {
|
||||
in, out := &in.Validation, &out.Validation
|
||||
*out = new(CustomResourceValidation)
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
if in.Subresources != nil {
|
||||
in, out := &in.Subresources, &out.Subresources
|
||||
*out = new(CustomResourceSubresources)
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
if in.Versions != nil {
|
||||
in, out := &in.Versions, &out.Versions
|
||||
*out = make([]CustomResourceDefinitionVersion, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
if in.AdditionalPrinterColumns != nil {
|
||||
in, out := &in.AdditionalPrinterColumns, &out.AdditionalPrinterColumns
|
||||
*out = make([]CustomResourceColumnDefinition, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CustomResourceDefinitionSpec.
|
||||
func (in *CustomResourceDefinitionSpec) DeepCopy() *CustomResourceDefinitionSpec {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(CustomResourceDefinitionSpec)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *CustomResourceDefinitionStatus) DeepCopyInto(out *CustomResourceDefinitionStatus) {
|
||||
*out = *in
|
||||
if in.Conditions != nil {
|
||||
in, out := &in.Conditions, &out.Conditions
|
||||
*out = make([]CustomResourceDefinitionCondition, len(*in))
|
||||
for i := range *in {
|
||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||
}
|
||||
}
|
||||
in.AcceptedNames.DeepCopyInto(&out.AcceptedNames)
|
||||
if in.StoredVersions != nil {
|
||||
in, out := &in.StoredVersions, &out.StoredVersions
|
||||
*out = make([]string, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CustomResourceDefinitionStatus.
|
||||
func (in *CustomResourceDefinitionStatus) DeepCopy() *CustomResourceDefinitionStatus {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(CustomResourceDefinitionStatus)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *CustomResourceDefinitionVersion) DeepCopyInto(out *CustomResourceDefinitionVersion) {
|
||||
*out = *in
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CustomResourceDefinitionVersion.
|
||||
func (in *CustomResourceDefinitionVersion) DeepCopy() *CustomResourceDefinitionVersion {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(CustomResourceDefinitionVersion)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *CustomResourceSubresourceScale) DeepCopyInto(out *CustomResourceSubresourceScale) {
|
||||
*out = *in
|
||||
if in.LabelSelectorPath != nil {
|
||||
in, out := &in.LabelSelectorPath, &out.LabelSelectorPath
|
||||
*out = new(string)
|
||||
**out = **in
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CustomResourceSubresourceScale.
|
||||
func (in *CustomResourceSubresourceScale) DeepCopy() *CustomResourceSubresourceScale {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(CustomResourceSubresourceScale)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *CustomResourceSubresourceStatus) DeepCopyInto(out *CustomResourceSubresourceStatus) {
|
||||
*out = *in
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CustomResourceSubresourceStatus.
|
||||
func (in *CustomResourceSubresourceStatus) DeepCopy() *CustomResourceSubresourceStatus {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(CustomResourceSubresourceStatus)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *CustomResourceSubresources) DeepCopyInto(out *CustomResourceSubresources) {
|
||||
*out = *in
|
||||
if in.Status != nil {
|
||||
in, out := &in.Status, &out.Status
|
||||
*out = new(CustomResourceSubresourceStatus)
|
||||
**out = **in
|
||||
}
|
||||
if in.Scale != nil {
|
||||
in, out := &in.Scale, &out.Scale
|
||||
*out = new(CustomResourceSubresourceScale)
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CustomResourceSubresources.
|
||||
func (in *CustomResourceSubresources) DeepCopy() *CustomResourceSubresources {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(CustomResourceSubresources)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *CustomResourceValidation) DeepCopyInto(out *CustomResourceValidation) {
|
||||
*out = *in
|
||||
if in.OpenAPIV3Schema != nil {
|
||||
in, out := &in.OpenAPIV3Schema, &out.OpenAPIV3Schema
|
||||
*out = (*in).DeepCopy()
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CustomResourceValidation.
|
||||
func (in *CustomResourceValidation) DeepCopy() *CustomResourceValidation {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(CustomResourceValidation)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *ExternalDocumentation) DeepCopyInto(out *ExternalDocumentation) {
|
||||
*out = *in
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ExternalDocumentation.
|
||||
func (in *ExternalDocumentation) DeepCopy() *ExternalDocumentation {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(ExternalDocumentation)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in JSONSchemaDefinitions) DeepCopyInto(out *JSONSchemaDefinitions) {
|
||||
{
|
||||
in := &in
|
||||
*out = make(JSONSchemaDefinitions, len(*in))
|
||||
for key, val := range *in {
|
||||
(*out)[key] = *val.DeepCopy()
|
||||
}
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new JSONSchemaDefinitions.
|
||||
func (in JSONSchemaDefinitions) DeepCopy() JSONSchemaDefinitions {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(JSONSchemaDefinitions)
|
||||
in.DeepCopyInto(out)
|
||||
return *out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in JSONSchemaDependencies) DeepCopyInto(out *JSONSchemaDependencies) {
|
||||
{
|
||||
in := &in
|
||||
*out = make(JSONSchemaDependencies, len(*in))
|
||||
for key, val := range *in {
|
||||
(*out)[key] = *val.DeepCopy()
|
||||
}
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new JSONSchemaDependencies.
|
||||
func (in JSONSchemaDependencies) DeepCopy() JSONSchemaDependencies {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(JSONSchemaDependencies)
|
||||
in.DeepCopyInto(out)
|
||||
return *out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *JSONSchemaProps) DeepCopyInto(out *JSONSchemaProps) {
|
||||
clone := in.DeepCopy()
|
||||
*out = *clone
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *JSONSchemaPropsOrArray) DeepCopyInto(out *JSONSchemaPropsOrArray) {
|
||||
*out = *in
|
||||
if in.Schema != nil {
|
||||
in, out := &in.Schema, &out.Schema
|
||||
*out = (*in).DeepCopy()
|
||||
}
|
||||
if in.JSONSchemas != nil {
|
||||
in, out := &in.JSONSchemas, &out.JSONSchemas
|
||||
*out = make([]JSONSchemaProps, len(*in))
|
||||
for i := range *in {
|
||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new JSONSchemaPropsOrArray.
|
||||
func (in *JSONSchemaPropsOrArray) DeepCopy() *JSONSchemaPropsOrArray {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(JSONSchemaPropsOrArray)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *JSONSchemaPropsOrBool) DeepCopyInto(out *JSONSchemaPropsOrBool) {
|
||||
*out = *in
|
||||
if in.Schema != nil {
|
||||
in, out := &in.Schema, &out.Schema
|
||||
*out = (*in).DeepCopy()
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new JSONSchemaPropsOrBool.
|
||||
func (in *JSONSchemaPropsOrBool) DeepCopy() *JSONSchemaPropsOrBool {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(JSONSchemaPropsOrBool)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *JSONSchemaPropsOrStringArray) DeepCopyInto(out *JSONSchemaPropsOrStringArray) {
|
||||
*out = *in
|
||||
if in.Schema != nil {
|
||||
in, out := &in.Schema, &out.Schema
|
||||
*out = (*in).DeepCopy()
|
||||
}
|
||||
if in.Property != nil {
|
||||
in, out := &in.Property, &out.Property
|
||||
*out = make([]string, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new JSONSchemaPropsOrStringArray.
|
||||
func (in *JSONSchemaPropsOrStringArray) DeepCopy() *JSONSchemaPropsOrStringArray {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(JSONSchemaPropsOrStringArray)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
214
vendor/k8s.io/apiextensions-apiserver/pkg/apiserver/apiserver.go
generated
vendored
Normal file
214
vendor/k8s.io/apiextensions-apiserver/pkg/apiserver/apiserver.go
generated
vendored
Normal file
@@ -0,0 +1,214 @@
|
||||
/*
|
||||
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 apiserver
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"k8s.io/apimachinery/pkg/runtime/serializer"
|
||||
"k8s.io/apimachinery/pkg/version"
|
||||
"k8s.io/apiserver/pkg/endpoints/discovery"
|
||||
genericregistry "k8s.io/apiserver/pkg/registry/generic"
|
||||
"k8s.io/apiserver/pkg/registry/rest"
|
||||
genericapiserver "k8s.io/apiserver/pkg/server"
|
||||
serverstorage "k8s.io/apiserver/pkg/server/storage"
|
||||
|
||||
"k8s.io/apiextensions-apiserver/pkg/apis/apiextensions"
|
||||
"k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/install"
|
||||
"k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1"
|
||||
"k8s.io/apiextensions-apiserver/pkg/client/clientset/internalclientset"
|
||||
internalinformers "k8s.io/apiextensions-apiserver/pkg/client/informers/internalversion"
|
||||
"k8s.io/apiextensions-apiserver/pkg/controller/establish"
|
||||
"k8s.io/apiextensions-apiserver/pkg/controller/finalizer"
|
||||
"k8s.io/apiextensions-apiserver/pkg/controller/status"
|
||||
"k8s.io/apiextensions-apiserver/pkg/registry/customresourcedefinition"
|
||||
|
||||
_ "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset"
|
||||
_ "k8s.io/apiextensions-apiserver/pkg/client/informers/externalversions"
|
||||
_ "k8s.io/apiextensions-apiserver/pkg/client/informers/internalversion"
|
||||
)
|
||||
|
||||
var (
|
||||
Scheme = runtime.NewScheme()
|
||||
Codecs = serializer.NewCodecFactory(Scheme)
|
||||
|
||||
// if you modify this, make sure you update the crEncoder
|
||||
unversionedVersion = schema.GroupVersion{Group: "", Version: "v1"}
|
||||
unversionedTypes = []runtime.Object{
|
||||
&metav1.Status{},
|
||||
&metav1.WatchEvent{},
|
||||
&metav1.APIVersions{},
|
||||
&metav1.APIGroupList{},
|
||||
&metav1.APIGroup{},
|
||||
&metav1.APIResourceList{},
|
||||
}
|
||||
)
|
||||
|
||||
func init() {
|
||||
install.Install(Scheme)
|
||||
|
||||
// we need to add the options to empty v1
|
||||
metav1.AddToGroupVersion(Scheme, schema.GroupVersion{Group: "", Version: "v1"})
|
||||
|
||||
Scheme.AddUnversionedTypes(unversionedVersion, unversionedTypes...)
|
||||
}
|
||||
|
||||
type ExtraConfig struct {
|
||||
CRDRESTOptionsGetter genericregistry.RESTOptionsGetter
|
||||
|
||||
// MasterCount is used to detect whether cluster is HA, and if it is
|
||||
// the CRD Establishing will be hold by 5 seconds.
|
||||
MasterCount int
|
||||
}
|
||||
|
||||
type Config struct {
|
||||
GenericConfig *genericapiserver.RecommendedConfig
|
||||
ExtraConfig ExtraConfig
|
||||
}
|
||||
|
||||
type completedConfig struct {
|
||||
GenericConfig genericapiserver.CompletedConfig
|
||||
ExtraConfig *ExtraConfig
|
||||
}
|
||||
|
||||
type CompletedConfig struct {
|
||||
// Embed a private pointer that cannot be instantiated outside of this package.
|
||||
*completedConfig
|
||||
}
|
||||
|
||||
type CustomResourceDefinitions struct {
|
||||
GenericAPIServer *genericapiserver.GenericAPIServer
|
||||
|
||||
// provided for easier embedding
|
||||
Informers internalinformers.SharedInformerFactory
|
||||
}
|
||||
|
||||
// Complete fills in any fields not set that are required to have valid data. It's mutating the receiver.
|
||||
func (cfg *Config) Complete() CompletedConfig {
|
||||
c := completedConfig{
|
||||
cfg.GenericConfig.Complete(),
|
||||
&cfg.ExtraConfig,
|
||||
}
|
||||
|
||||
c.GenericConfig.EnableDiscovery = false
|
||||
c.GenericConfig.Version = &version.Info{
|
||||
Major: "0",
|
||||
Minor: "1",
|
||||
}
|
||||
|
||||
return CompletedConfig{&c}
|
||||
}
|
||||
|
||||
// New returns a new instance of CustomResourceDefinitions from the given config.
|
||||
func (c completedConfig) New(delegationTarget genericapiserver.DelegationTarget) (*CustomResourceDefinitions, error) {
|
||||
genericServer, err := c.GenericConfig.New("apiextensions-apiserver", delegationTarget)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
s := &CustomResourceDefinitions{
|
||||
GenericAPIServer: genericServer,
|
||||
}
|
||||
|
||||
apiResourceConfig := c.GenericConfig.MergedResourceConfig
|
||||
apiGroupInfo := genericapiserver.NewDefaultAPIGroupInfo(apiextensions.GroupName, Scheme, metav1.ParameterCodec, Codecs)
|
||||
if apiResourceConfig.VersionEnabled(v1beta1.SchemeGroupVersion) {
|
||||
storage := map[string]rest.Storage{}
|
||||
// customresourcedefinitions
|
||||
customResourceDefintionStorage := customresourcedefinition.NewREST(Scheme, c.GenericConfig.RESTOptionsGetter)
|
||||
storage["customresourcedefinitions"] = customResourceDefintionStorage
|
||||
storage["customresourcedefinitions/status"] = customresourcedefinition.NewStatusREST(Scheme, customResourceDefintionStorage)
|
||||
|
||||
apiGroupInfo.VersionedResourcesStorageMap["v1beta1"] = storage
|
||||
}
|
||||
|
||||
if err := s.GenericAPIServer.InstallAPIGroup(&apiGroupInfo); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
crdClient, err := internalclientset.NewForConfig(s.GenericAPIServer.LoopbackClientConfig)
|
||||
if err != nil {
|
||||
// it's really bad that this is leaking here, but until we can fix the test (which I'm pretty sure isn't even testing what it wants to test),
|
||||
// we need to be able to move forward
|
||||
return nil, fmt.Errorf("failed to create clientset: %v", err)
|
||||
}
|
||||
s.Informers = internalinformers.NewSharedInformerFactory(crdClient, 5*time.Minute)
|
||||
|
||||
delegateHandler := delegationTarget.UnprotectedHandler()
|
||||
if delegateHandler == nil {
|
||||
delegateHandler = http.NotFoundHandler()
|
||||
}
|
||||
|
||||
versionDiscoveryHandler := &versionDiscoveryHandler{
|
||||
discovery: map[schema.GroupVersion]*discovery.APIVersionHandler{},
|
||||
delegate: delegateHandler,
|
||||
}
|
||||
groupDiscoveryHandler := &groupDiscoveryHandler{
|
||||
discovery: map[string]*discovery.APIGroupHandler{},
|
||||
delegate: delegateHandler,
|
||||
}
|
||||
establishingController := establish.NewEstablishingController(s.Informers.Apiextensions().InternalVersion().CustomResourceDefinitions(), crdClient.Apiextensions())
|
||||
crdHandler := NewCustomResourceDefinitionHandler(
|
||||
versionDiscoveryHandler,
|
||||
groupDiscoveryHandler,
|
||||
s.Informers.Apiextensions().InternalVersion().CustomResourceDefinitions(),
|
||||
delegateHandler,
|
||||
c.ExtraConfig.CRDRESTOptionsGetter,
|
||||
c.GenericConfig.AdmissionControl,
|
||||
establishingController,
|
||||
c.ExtraConfig.MasterCount,
|
||||
)
|
||||
s.GenericAPIServer.Handler.NonGoRestfulMux.Handle("/apis", crdHandler)
|
||||
s.GenericAPIServer.Handler.NonGoRestfulMux.HandlePrefix("/apis/", crdHandler)
|
||||
|
||||
crdController := NewDiscoveryController(s.Informers.Apiextensions().InternalVersion().CustomResourceDefinitions(), versionDiscoveryHandler, groupDiscoveryHandler)
|
||||
namingController := status.NewNamingConditionController(s.Informers.Apiextensions().InternalVersion().CustomResourceDefinitions(), crdClient.Apiextensions())
|
||||
finalizingController := finalizer.NewCRDFinalizer(
|
||||
s.Informers.Apiextensions().InternalVersion().CustomResourceDefinitions(),
|
||||
crdClient.Apiextensions(),
|
||||
crdHandler,
|
||||
)
|
||||
|
||||
s.GenericAPIServer.AddPostStartHook("start-apiextensions-informers", func(context genericapiserver.PostStartHookContext) error {
|
||||
s.Informers.Start(context.StopCh)
|
||||
return nil
|
||||
})
|
||||
s.GenericAPIServer.AddPostStartHook("start-apiextensions-controllers", func(context genericapiserver.PostStartHookContext) error {
|
||||
go crdController.Run(context.StopCh)
|
||||
go namingController.Run(context.StopCh)
|
||||
go establishingController.Run(context.StopCh)
|
||||
go finalizingController.Run(5, context.StopCh)
|
||||
return nil
|
||||
})
|
||||
|
||||
return s, nil
|
||||
}
|
||||
|
||||
func DefaultAPIResourceConfigSource() *serverstorage.ResourceConfig {
|
||||
ret := serverstorage.NewResourceConfig()
|
||||
// NOTE: GroupVersions listed here will be enabled by default. Don't put alpha versions in the list.
|
||||
ret.EnableVersions(
|
||||
v1beta1.SchemeGroupVersion,
|
||||
)
|
||||
|
||||
return ret
|
||||
}
|
||||
117
vendor/k8s.io/apiextensions-apiserver/pkg/apiserver/conversion/converter.go
generated
vendored
Normal file
117
vendor/k8s.io/apiextensions-apiserver/pkg/apiserver/conversion/converter.go
generated
vendored
Normal file
@@ -0,0 +1,117 @@
|
||||
/*
|
||||
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 conversion
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"k8s.io/apiextensions-apiserver/pkg/apis/apiextensions"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
)
|
||||
|
||||
// NewCRDConverter returns a new CRD converter based on the conversion settings in crd object.
|
||||
func NewCRDConverter(crd *apiextensions.CustomResourceDefinition) (safe, unsafe runtime.ObjectConvertor) {
|
||||
validVersions := map[schema.GroupVersion]bool{}
|
||||
for _, version := range crd.Spec.Versions {
|
||||
validVersions[schema.GroupVersion{Group: crd.Spec.Group, Version: version.Name}] = true
|
||||
}
|
||||
|
||||
// The only converter right now is nopConverter. More converters will be returned based on the
|
||||
// CRD object when they introduced.
|
||||
unsafe = &crdConverter{
|
||||
clusterScoped: crd.Spec.Scope == apiextensions.ClusterScoped,
|
||||
delegate: &nopConverter{
|
||||
validVersions: validVersions,
|
||||
},
|
||||
}
|
||||
return &safeConverterWrapper{unsafe}, unsafe
|
||||
}
|
||||
|
||||
var _ runtime.ObjectConvertor = &crdConverter{}
|
||||
|
||||
// crdConverter extends the delegate with generic CRD conversion behaviour. The delegate will implement the
|
||||
// user defined conversion strategy given in the CustomResourceDefinition.
|
||||
type crdConverter struct {
|
||||
delegate runtime.ObjectConvertor
|
||||
clusterScoped bool
|
||||
}
|
||||
|
||||
func (c *crdConverter) ConvertFieldLabel(gvk schema.GroupVersionKind, label, value string) (string, string, error) {
|
||||
// We currently only support metadata.namespace and metadata.name.
|
||||
switch {
|
||||
case label == "metadata.name":
|
||||
return label, value, nil
|
||||
case !c.clusterScoped && label == "metadata.namespace":
|
||||
return label, value, nil
|
||||
default:
|
||||
return "", "", fmt.Errorf("field label not supported: %s", label)
|
||||
}
|
||||
}
|
||||
|
||||
func (c *crdConverter) Convert(in, out, context interface{}) error {
|
||||
return c.delegate.Convert(in, out, context)
|
||||
}
|
||||
|
||||
// ConvertToVersion converts in object to the given gvk in place and returns the same `in` object.
|
||||
func (c *crdConverter) ConvertToVersion(in runtime.Object, target runtime.GroupVersioner) (runtime.Object, error) {
|
||||
// Run the converter on the list items instead of list itself
|
||||
if list, ok := in.(*unstructured.UnstructuredList); ok {
|
||||
for i := range list.Items {
|
||||
obj, err := c.delegate.ConvertToVersion(&list.Items[i], target)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
u, ok := obj.(*unstructured.Unstructured)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("output type %T in not valid for unstructured conversion", obj)
|
||||
}
|
||||
list.Items[i] = *u
|
||||
}
|
||||
return list, nil
|
||||
}
|
||||
|
||||
return c.delegate.ConvertToVersion(in, target)
|
||||
}
|
||||
|
||||
// safeConverterWrapper is a wrapper over an unsafe object converter that makes copy of the input and then delegate to the unsafe converter.
|
||||
type safeConverterWrapper struct {
|
||||
unsafe runtime.ObjectConvertor
|
||||
}
|
||||
|
||||
var _ runtime.ObjectConvertor = &nopConverter{}
|
||||
|
||||
// ConvertFieldLabel delegate the call to the unsafe converter.
|
||||
func (c *safeConverterWrapper) ConvertFieldLabel(gvk schema.GroupVersionKind, label, value string) (string, string, error) {
|
||||
return c.unsafe.ConvertFieldLabel(gvk, label, value)
|
||||
}
|
||||
|
||||
// Convert makes a copy of in object and then delegate the call to the unsafe converter.
|
||||
func (c *safeConverterWrapper) Convert(in, out, context interface{}) error {
|
||||
inObject, ok := in.(runtime.Object)
|
||||
if !ok {
|
||||
return fmt.Errorf("input type %T in not valid for object conversion", in)
|
||||
}
|
||||
return c.unsafe.Convert(inObject.DeepCopyObject(), out, context)
|
||||
}
|
||||
|
||||
// ConvertToVersion makes a copy of in object and then delegate the call to the unsafe converter.
|
||||
func (c *safeConverterWrapper) ConvertToVersion(in runtime.Object, target runtime.GroupVersioner) (runtime.Object, error) {
|
||||
return c.unsafe.ConvertToVersion(in.DeepCopyObject(), target)
|
||||
}
|
||||
79
vendor/k8s.io/apiextensions-apiserver/pkg/apiserver/conversion/nop_converter.go
generated
vendored
Normal file
79
vendor/k8s.io/apiextensions-apiserver/pkg/apiserver/conversion/nop_converter.go
generated
vendored
Normal file
@@ -0,0 +1,79 @@
|
||||
/*
|
||||
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 conversion
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
)
|
||||
|
||||
// nopConverter is a converter that only sets the apiVersion fields, but does not real conversion.
|
||||
type nopConverter struct {
|
||||
validVersions map[schema.GroupVersion]bool
|
||||
}
|
||||
|
||||
var _ runtime.ObjectConvertor = &nopConverter{}
|
||||
|
||||
func (nopConverter) ConvertFieldLabel(gvk schema.GroupVersionKind, label, value string) (string, string, error) {
|
||||
return "", "", errors.New("unstructured cannot convert field labels")
|
||||
}
|
||||
|
||||
func (c *nopConverter) Convert(in, out, context interface{}) error {
|
||||
unstructIn, ok := in.(*unstructured.Unstructured)
|
||||
if !ok {
|
||||
return fmt.Errorf("input type %T in not valid for unstructured conversion", in)
|
||||
}
|
||||
|
||||
unstructOut, ok := out.(*unstructured.Unstructured)
|
||||
if !ok {
|
||||
return fmt.Errorf("output type %T in not valid for unstructured conversion", out)
|
||||
}
|
||||
|
||||
outGVK := unstructOut.GroupVersionKind()
|
||||
if !c.validVersions[outGVK.GroupVersion()] {
|
||||
return fmt.Errorf("request to convert CRD from an invalid group/version: %s", outGVK.String())
|
||||
}
|
||||
inGVK := unstructIn.GroupVersionKind()
|
||||
if !c.validVersions[inGVK.GroupVersion()] {
|
||||
return fmt.Errorf("request to convert CRD to an invalid group/version: %s", inGVK.String())
|
||||
}
|
||||
|
||||
unstructOut.SetUnstructuredContent(unstructIn.UnstructuredContent())
|
||||
_, err := c.ConvertToVersion(unstructOut, outGVK.GroupVersion())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *nopConverter) ConvertToVersion(in runtime.Object, target runtime.GroupVersioner) (runtime.Object, error) {
|
||||
kind := in.GetObjectKind().GroupVersionKind()
|
||||
gvk, ok := target.KindForGroupVersionKinds([]schema.GroupVersionKind{kind})
|
||||
if !ok {
|
||||
// TODO: should this be a typed error?
|
||||
return nil, fmt.Errorf("%v is unstructured and is not suitable for converting to %q", kind, target)
|
||||
}
|
||||
if !c.validVersions[gvk.GroupVersion()] {
|
||||
return nil, fmt.Errorf("request to convert CRD to an invalid group/version: %s", gvk.String())
|
||||
}
|
||||
in.GetObjectKind().SetGroupVersionKind(gvk)
|
||||
return in, nil
|
||||
}
|
||||
127
vendor/k8s.io/apiextensions-apiserver/pkg/apiserver/customresource_discovery.go
generated
vendored
Normal file
127
vendor/k8s.io/apiextensions-apiserver/pkg/apiserver/customresource_discovery.go
generated
vendored
Normal file
@@ -0,0 +1,127 @@
|
||||
/*
|
||||
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 apiserver
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"k8s.io/apiserver/pkg/endpoints/discovery"
|
||||
)
|
||||
|
||||
type versionDiscoveryHandler struct {
|
||||
// TODO, writing is infrequent, optimize this
|
||||
discoveryLock sync.RWMutex
|
||||
discovery map[schema.GroupVersion]*discovery.APIVersionHandler
|
||||
|
||||
delegate http.Handler
|
||||
}
|
||||
|
||||
func (r *versionDiscoveryHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
||||
pathParts := splitPath(req.URL.Path)
|
||||
// only match /apis/<group>/<version>
|
||||
if len(pathParts) != 3 || pathParts[0] != "apis" {
|
||||
r.delegate.ServeHTTP(w, req)
|
||||
return
|
||||
}
|
||||
discovery, ok := r.getDiscovery(schema.GroupVersion{Group: pathParts[1], Version: pathParts[2]})
|
||||
if !ok {
|
||||
r.delegate.ServeHTTP(w, req)
|
||||
return
|
||||
}
|
||||
|
||||
discovery.ServeHTTP(w, req)
|
||||
}
|
||||
|
||||
func (r *versionDiscoveryHandler) getDiscovery(gv schema.GroupVersion) (*discovery.APIVersionHandler, bool) {
|
||||
r.discoveryLock.RLock()
|
||||
defer r.discoveryLock.RUnlock()
|
||||
|
||||
ret, ok := r.discovery[gv]
|
||||
return ret, ok
|
||||
}
|
||||
|
||||
func (r *versionDiscoveryHandler) setDiscovery(gv schema.GroupVersion, discovery *discovery.APIVersionHandler) {
|
||||
r.discoveryLock.Lock()
|
||||
defer r.discoveryLock.Unlock()
|
||||
|
||||
r.discovery[gv] = discovery
|
||||
}
|
||||
|
||||
func (r *versionDiscoveryHandler) unsetDiscovery(gv schema.GroupVersion) {
|
||||
r.discoveryLock.Lock()
|
||||
defer r.discoveryLock.Unlock()
|
||||
|
||||
delete(r.discovery, gv)
|
||||
}
|
||||
|
||||
type groupDiscoveryHandler struct {
|
||||
// TODO, writing is infrequent, optimize this
|
||||
discoveryLock sync.RWMutex
|
||||
discovery map[string]*discovery.APIGroupHandler
|
||||
|
||||
delegate http.Handler
|
||||
}
|
||||
|
||||
func (r *groupDiscoveryHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
||||
pathParts := splitPath(req.URL.Path)
|
||||
// only match /apis/<group>
|
||||
if len(pathParts) != 2 || pathParts[0] != "apis" {
|
||||
r.delegate.ServeHTTP(w, req)
|
||||
return
|
||||
}
|
||||
discovery, ok := r.getDiscovery(pathParts[1])
|
||||
if !ok {
|
||||
r.delegate.ServeHTTP(w, req)
|
||||
return
|
||||
}
|
||||
|
||||
discovery.ServeHTTP(w, req)
|
||||
}
|
||||
|
||||
func (r *groupDiscoveryHandler) getDiscovery(group string) (*discovery.APIGroupHandler, bool) {
|
||||
r.discoveryLock.RLock()
|
||||
defer r.discoveryLock.RUnlock()
|
||||
|
||||
ret, ok := r.discovery[group]
|
||||
return ret, ok
|
||||
}
|
||||
|
||||
func (r *groupDiscoveryHandler) setDiscovery(group string, discovery *discovery.APIGroupHandler) {
|
||||
r.discoveryLock.Lock()
|
||||
defer r.discoveryLock.Unlock()
|
||||
|
||||
r.discovery[group] = discovery
|
||||
}
|
||||
|
||||
func (r *groupDiscoveryHandler) unsetDiscovery(group string) {
|
||||
r.discoveryLock.Lock()
|
||||
defer r.discoveryLock.Unlock()
|
||||
|
||||
delete(r.discovery, group)
|
||||
}
|
||||
|
||||
// splitPath returns the segments for a URL path.
|
||||
func splitPath(path string) []string {
|
||||
path = strings.Trim(path, "/")
|
||||
if path == "" {
|
||||
return []string{}
|
||||
}
|
||||
return strings.Split(path, "/")
|
||||
}
|
||||
275
vendor/k8s.io/apiextensions-apiserver/pkg/apiserver/customresource_discovery_controller.go
generated
vendored
Normal file
275
vendor/k8s.io/apiextensions-apiserver/pkg/apiserver/customresource_discovery_controller.go
generated
vendored
Normal file
@@ -0,0 +1,275 @@
|
||||
/*
|
||||
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 apiserver
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sort"
|
||||
"time"
|
||||
|
||||
"github.com/golang/glog"
|
||||
|
||||
autoscaling "k8s.io/api/autoscaling/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
|
||||
"k8s.io/apimachinery/pkg/util/wait"
|
||||
"k8s.io/apimachinery/pkg/version"
|
||||
"k8s.io/apiserver/pkg/endpoints/discovery"
|
||||
"k8s.io/client-go/tools/cache"
|
||||
"k8s.io/client-go/util/workqueue"
|
||||
|
||||
"k8s.io/apiextensions-apiserver/pkg/apis/apiextensions"
|
||||
informers "k8s.io/apiextensions-apiserver/pkg/client/informers/internalversion/apiextensions/internalversion"
|
||||
listers "k8s.io/apiextensions-apiserver/pkg/client/listers/apiextensions/internalversion"
|
||||
)
|
||||
|
||||
type DiscoveryController struct {
|
||||
versionHandler *versionDiscoveryHandler
|
||||
groupHandler *groupDiscoveryHandler
|
||||
|
||||
crdLister listers.CustomResourceDefinitionLister
|
||||
crdsSynced cache.InformerSynced
|
||||
|
||||
// To allow injection for testing.
|
||||
syncFn func(version schema.GroupVersion) error
|
||||
|
||||
queue workqueue.RateLimitingInterface
|
||||
}
|
||||
|
||||
func NewDiscoveryController(crdInformer informers.CustomResourceDefinitionInformer, versionHandler *versionDiscoveryHandler, groupHandler *groupDiscoveryHandler) *DiscoveryController {
|
||||
c := &DiscoveryController{
|
||||
versionHandler: versionHandler,
|
||||
groupHandler: groupHandler,
|
||||
crdLister: crdInformer.Lister(),
|
||||
crdsSynced: crdInformer.Informer().HasSynced,
|
||||
|
||||
queue: workqueue.NewNamedRateLimitingQueue(workqueue.DefaultControllerRateLimiter(), "DiscoveryController"),
|
||||
}
|
||||
|
||||
crdInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{
|
||||
AddFunc: c.addCustomResourceDefinition,
|
||||
UpdateFunc: c.updateCustomResourceDefinition,
|
||||
DeleteFunc: c.deleteCustomResourceDefinition,
|
||||
})
|
||||
|
||||
c.syncFn = c.sync
|
||||
|
||||
return c
|
||||
}
|
||||
|
||||
func (c *DiscoveryController) sync(version schema.GroupVersion) error {
|
||||
|
||||
apiVersionsForDiscovery := []metav1.GroupVersionForDiscovery{}
|
||||
apiResourcesForDiscovery := []metav1.APIResource{}
|
||||
versionsForDiscoveryMap := map[metav1.GroupVersion]bool{}
|
||||
|
||||
crds, err := c.crdLister.List(labels.Everything())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
foundVersion := false
|
||||
foundGroup := false
|
||||
for _, crd := range crds {
|
||||
if !apiextensions.IsCRDConditionTrue(crd, apiextensions.Established) {
|
||||
continue
|
||||
}
|
||||
|
||||
if crd.Spec.Group != version.Group {
|
||||
continue
|
||||
}
|
||||
|
||||
foundThisVersion := false
|
||||
for _, v := range crd.Spec.Versions {
|
||||
if !v.Served {
|
||||
continue
|
||||
}
|
||||
// If there is any Served version, that means the group should show up in discovery
|
||||
foundGroup = true
|
||||
|
||||
gv := metav1.GroupVersion{Group: crd.Spec.Group, Version: v.Name}
|
||||
if !versionsForDiscoveryMap[gv] {
|
||||
versionsForDiscoveryMap[gv] = true
|
||||
apiVersionsForDiscovery = append(apiVersionsForDiscovery, metav1.GroupVersionForDiscovery{
|
||||
GroupVersion: crd.Spec.Group + "/" + v.Name,
|
||||
Version: v.Name,
|
||||
})
|
||||
}
|
||||
if v.Name == version.Version {
|
||||
foundThisVersion = true
|
||||
}
|
||||
}
|
||||
|
||||
if !foundThisVersion {
|
||||
continue
|
||||
}
|
||||
foundVersion = true
|
||||
|
||||
verbs := metav1.Verbs([]string{"delete", "deletecollection", "get", "list", "patch", "create", "update", "watch"})
|
||||
// if we're terminating we don't allow some verbs
|
||||
if apiextensions.IsCRDConditionTrue(crd, apiextensions.Terminating) {
|
||||
verbs = metav1.Verbs([]string{"delete", "deletecollection", "get", "list", "watch"})
|
||||
}
|
||||
|
||||
apiResourcesForDiscovery = append(apiResourcesForDiscovery, metav1.APIResource{
|
||||
Name: crd.Status.AcceptedNames.Plural,
|
||||
SingularName: crd.Status.AcceptedNames.Singular,
|
||||
Namespaced: crd.Spec.Scope == apiextensions.NamespaceScoped,
|
||||
Kind: crd.Status.AcceptedNames.Kind,
|
||||
Verbs: verbs,
|
||||
ShortNames: crd.Status.AcceptedNames.ShortNames,
|
||||
Categories: crd.Status.AcceptedNames.Categories,
|
||||
})
|
||||
|
||||
if crd.Spec.Subresources != nil && crd.Spec.Subresources.Status != nil {
|
||||
apiResourcesForDiscovery = append(apiResourcesForDiscovery, metav1.APIResource{
|
||||
Name: crd.Status.AcceptedNames.Plural + "/status",
|
||||
Namespaced: crd.Spec.Scope == apiextensions.NamespaceScoped,
|
||||
Kind: crd.Status.AcceptedNames.Kind,
|
||||
Verbs: metav1.Verbs([]string{"get", "patch", "update"}),
|
||||
})
|
||||
}
|
||||
|
||||
if crd.Spec.Subresources != nil && crd.Spec.Subresources.Scale != nil {
|
||||
apiResourcesForDiscovery = append(apiResourcesForDiscovery, metav1.APIResource{
|
||||
Group: autoscaling.GroupName,
|
||||
Version: "v1",
|
||||
Kind: "Scale",
|
||||
Name: crd.Status.AcceptedNames.Plural + "/scale",
|
||||
Namespaced: crd.Spec.Scope == apiextensions.NamespaceScoped,
|
||||
Verbs: metav1.Verbs([]string{"get", "patch", "update"}),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
if !foundGroup {
|
||||
c.groupHandler.unsetDiscovery(version.Group)
|
||||
c.versionHandler.unsetDiscovery(version)
|
||||
return nil
|
||||
}
|
||||
|
||||
sortGroupDiscoveryByKubeAwareVersion(apiVersionsForDiscovery)
|
||||
|
||||
apiGroup := metav1.APIGroup{
|
||||
Name: version.Group,
|
||||
Versions: apiVersionsForDiscovery,
|
||||
// the preferred versions for a group is the first item in
|
||||
// apiVersionsForDiscovery after it put in the right ordered
|
||||
PreferredVersion: apiVersionsForDiscovery[0],
|
||||
}
|
||||
c.groupHandler.setDiscovery(version.Group, discovery.NewAPIGroupHandler(Codecs, apiGroup))
|
||||
|
||||
if !foundVersion {
|
||||
c.versionHandler.unsetDiscovery(version)
|
||||
return nil
|
||||
}
|
||||
c.versionHandler.setDiscovery(version, discovery.NewAPIVersionHandler(Codecs, version, discovery.APIResourceListerFunc(func() []metav1.APIResource {
|
||||
return apiResourcesForDiscovery
|
||||
})))
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func sortGroupDiscoveryByKubeAwareVersion(gd []metav1.GroupVersionForDiscovery) {
|
||||
sort.Slice(gd, func(i, j int) bool {
|
||||
return version.CompareKubeAwareVersionStrings(gd[i].Version, gd[j].Version) > 0
|
||||
})
|
||||
}
|
||||
|
||||
func (c *DiscoveryController) Run(stopCh <-chan struct{}) {
|
||||
defer utilruntime.HandleCrash()
|
||||
defer c.queue.ShutDown()
|
||||
defer glog.Infof("Shutting down DiscoveryController")
|
||||
|
||||
glog.Infof("Starting DiscoveryController")
|
||||
|
||||
if !cache.WaitForCacheSync(stopCh, c.crdsSynced) {
|
||||
utilruntime.HandleError(fmt.Errorf("timed out waiting for caches to sync"))
|
||||
return
|
||||
}
|
||||
|
||||
// only start one worker thread since its a slow moving API
|
||||
go wait.Until(c.runWorker, time.Second, stopCh)
|
||||
|
||||
<-stopCh
|
||||
}
|
||||
|
||||
func (c *DiscoveryController) runWorker() {
|
||||
for c.processNextWorkItem() {
|
||||
}
|
||||
}
|
||||
|
||||
// processNextWorkItem deals with one key off the queue. It returns false when it's time to quit.
|
||||
func (c *DiscoveryController) processNextWorkItem() bool {
|
||||
key, quit := c.queue.Get()
|
||||
if quit {
|
||||
return false
|
||||
}
|
||||
defer c.queue.Done(key)
|
||||
|
||||
err := c.syncFn(key.(schema.GroupVersion))
|
||||
if err == nil {
|
||||
c.queue.Forget(key)
|
||||
return true
|
||||
}
|
||||
|
||||
utilruntime.HandleError(fmt.Errorf("%v failed with: %v", key, err))
|
||||
c.queue.AddRateLimited(key)
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
func (c *DiscoveryController) enqueue(obj *apiextensions.CustomResourceDefinition) {
|
||||
for _, v := range obj.Spec.Versions {
|
||||
c.queue.Add(schema.GroupVersion{Group: obj.Spec.Group, Version: v.Name})
|
||||
}
|
||||
}
|
||||
|
||||
func (c *DiscoveryController) addCustomResourceDefinition(obj interface{}) {
|
||||
castObj := obj.(*apiextensions.CustomResourceDefinition)
|
||||
glog.V(4).Infof("Adding customresourcedefinition %s", castObj.Name)
|
||||
c.enqueue(castObj)
|
||||
}
|
||||
|
||||
func (c *DiscoveryController) updateCustomResourceDefinition(oldObj, newObj interface{}) {
|
||||
castNewObj := newObj.(*apiextensions.CustomResourceDefinition)
|
||||
castOldObj := oldObj.(*apiextensions.CustomResourceDefinition)
|
||||
glog.V(4).Infof("Updating customresourcedefinition %s", castOldObj.Name)
|
||||
// Enqueue both old and new object to make sure we remove and add appropriate Versions.
|
||||
// The working queue will resolve any duplicates and only changes will stay in the queue.
|
||||
c.enqueue(castNewObj)
|
||||
c.enqueue(castOldObj)
|
||||
}
|
||||
|
||||
func (c *DiscoveryController) deleteCustomResourceDefinition(obj interface{}) {
|
||||
castObj, ok := obj.(*apiextensions.CustomResourceDefinition)
|
||||
if !ok {
|
||||
tombstone, ok := obj.(cache.DeletedFinalStateUnknown)
|
||||
if !ok {
|
||||
glog.Errorf("Couldn't get object from tombstone %#v", obj)
|
||||
return
|
||||
}
|
||||
castObj, ok = tombstone.Obj.(*apiextensions.CustomResourceDefinition)
|
||||
if !ok {
|
||||
glog.Errorf("Tombstone contained object that is not expected %#v", obj)
|
||||
return
|
||||
}
|
||||
}
|
||||
glog.V(4).Infof("Deleting customresourcedefinition %q", castObj.Name)
|
||||
c.enqueue(castObj)
|
||||
}
|
||||
893
vendor/k8s.io/apiextensions-apiserver/pkg/apiserver/customresource_handler.go
generated
vendored
Normal file
893
vendor/k8s.io/apiextensions-apiserver/pkg/apiserver/customresource_handler.go
generated
vendored
Normal file
@@ -0,0 +1,893 @@
|
||||
/*
|
||||
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 apiserver
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"path"
|
||||
"strings"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
"github.com/go-openapi/spec"
|
||||
"github.com/go-openapi/strfmt"
|
||||
"github.com/go-openapi/validate"
|
||||
"github.com/golang/glog"
|
||||
|
||||
apiequality "k8s.io/apimachinery/pkg/api/equality"
|
||||
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
||||
"k8s.io/apimachinery/pkg/api/meta"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"k8s.io/apimachinery/pkg/runtime/serializer"
|
||||
"k8s.io/apimachinery/pkg/runtime/serializer/json"
|
||||
"k8s.io/apimachinery/pkg/runtime/serializer/versioning"
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
|
||||
"k8s.io/apiserver/pkg/admission"
|
||||
"k8s.io/apiserver/pkg/endpoints/handlers"
|
||||
"k8s.io/apiserver/pkg/endpoints/handlers/responsewriters"
|
||||
"k8s.io/apiserver/pkg/endpoints/metrics"
|
||||
apirequest "k8s.io/apiserver/pkg/endpoints/request"
|
||||
"k8s.io/apiserver/pkg/registry/generic"
|
||||
genericregistry "k8s.io/apiserver/pkg/registry/generic/registry"
|
||||
"k8s.io/apiserver/pkg/storage/storagebackend"
|
||||
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||
"k8s.io/client-go/scale"
|
||||
"k8s.io/client-go/scale/scheme/autoscalingv1"
|
||||
"k8s.io/client-go/tools/cache"
|
||||
|
||||
"k8s.io/apiextensions-apiserver/pkg/apis/apiextensions"
|
||||
"k8s.io/apiextensions-apiserver/pkg/apiserver/conversion"
|
||||
apiservervalidation "k8s.io/apiextensions-apiserver/pkg/apiserver/validation"
|
||||
informers "k8s.io/apiextensions-apiserver/pkg/client/informers/internalversion/apiextensions/internalversion"
|
||||
listers "k8s.io/apiextensions-apiserver/pkg/client/listers/apiextensions/internalversion"
|
||||
"k8s.io/apiextensions-apiserver/pkg/controller/establish"
|
||||
"k8s.io/apiextensions-apiserver/pkg/controller/finalizer"
|
||||
"k8s.io/apiextensions-apiserver/pkg/crdserverscheme"
|
||||
apiextensionsfeatures "k8s.io/apiextensions-apiserver/pkg/features"
|
||||
"k8s.io/apiextensions-apiserver/pkg/registry/customresource"
|
||||
"k8s.io/apiextensions-apiserver/pkg/registry/customresource/tableconvertor"
|
||||
)
|
||||
|
||||
// crdHandler serves the `/apis` endpoint.
|
||||
// This is registered as a filter so that it never collides with any explicitly registered endpoints
|
||||
type crdHandler struct {
|
||||
versionDiscoveryHandler *versionDiscoveryHandler
|
||||
groupDiscoveryHandler *groupDiscoveryHandler
|
||||
|
||||
customStorageLock sync.Mutex
|
||||
// customStorage contains a crdStorageMap
|
||||
// atomic.Value has a very good read performance compared to sync.RWMutex
|
||||
// see https://gist.github.com/dim/152e6bf80e1384ea72e17ac717a5000a
|
||||
// which is suited for most read and rarely write cases
|
||||
customStorage atomic.Value
|
||||
|
||||
crdLister listers.CustomResourceDefinitionLister
|
||||
|
||||
delegate http.Handler
|
||||
restOptionsGetter generic.RESTOptionsGetter
|
||||
admission admission.Interface
|
||||
|
||||
establishingController *establish.EstablishingController
|
||||
|
||||
// MasterCount is used to implement sleep to improve
|
||||
// CRD establishing process for HA clusters.
|
||||
masterCount int
|
||||
}
|
||||
|
||||
// crdInfo stores enough information to serve the storage for the custom resource
|
||||
type crdInfo struct {
|
||||
// spec and acceptedNames are used to compare against if a change is made on a CRD. We only update
|
||||
// the storage if one of these changes.
|
||||
spec *apiextensions.CustomResourceDefinitionSpec
|
||||
acceptedNames *apiextensions.CustomResourceDefinitionNames
|
||||
|
||||
// Storage per version
|
||||
storages map[string]customresource.CustomResourceStorage
|
||||
|
||||
// Request scope per version
|
||||
requestScopes map[string]handlers.RequestScope
|
||||
|
||||
// Scale scope per version
|
||||
scaleRequestScopes map[string]handlers.RequestScope
|
||||
|
||||
// Status scope per version
|
||||
statusRequestScopes map[string]handlers.RequestScope
|
||||
|
||||
// storageVersion is the CRD version used when storing the object in etcd.
|
||||
storageVersion string
|
||||
}
|
||||
|
||||
// crdStorageMap goes from customresourcedefinition to its storage
|
||||
type crdStorageMap map[types.UID]*crdInfo
|
||||
|
||||
func NewCustomResourceDefinitionHandler(
|
||||
versionDiscoveryHandler *versionDiscoveryHandler,
|
||||
groupDiscoveryHandler *groupDiscoveryHandler,
|
||||
crdInformer informers.CustomResourceDefinitionInformer,
|
||||
delegate http.Handler,
|
||||
restOptionsGetter generic.RESTOptionsGetter,
|
||||
admission admission.Interface,
|
||||
establishingController *establish.EstablishingController,
|
||||
masterCount int) *crdHandler {
|
||||
ret := &crdHandler{
|
||||
versionDiscoveryHandler: versionDiscoveryHandler,
|
||||
groupDiscoveryHandler: groupDiscoveryHandler,
|
||||
customStorage: atomic.Value{},
|
||||
crdLister: crdInformer.Lister(),
|
||||
delegate: delegate,
|
||||
restOptionsGetter: restOptionsGetter,
|
||||
admission: admission,
|
||||
establishingController: establishingController,
|
||||
masterCount: masterCount,
|
||||
}
|
||||
crdInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{
|
||||
UpdateFunc: ret.updateCustomResourceDefinition,
|
||||
DeleteFunc: func(obj interface{}) {
|
||||
ret.removeDeadStorage()
|
||||
},
|
||||
})
|
||||
|
||||
ret.customStorage.Store(crdStorageMap{})
|
||||
|
||||
return ret
|
||||
}
|
||||
|
||||
func (r *crdHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
||||
ctx := req.Context()
|
||||
requestInfo, ok := apirequest.RequestInfoFrom(ctx)
|
||||
if !ok {
|
||||
responsewriters.InternalError(w, req, fmt.Errorf("no RequestInfo found in the context"))
|
||||
return
|
||||
}
|
||||
if !requestInfo.IsResourceRequest {
|
||||
pathParts := splitPath(requestInfo.Path)
|
||||
// only match /apis/<group>/<version>
|
||||
// only registered under /apis
|
||||
if len(pathParts) == 3 {
|
||||
r.versionDiscoveryHandler.ServeHTTP(w, req)
|
||||
return
|
||||
}
|
||||
// only match /apis/<group>
|
||||
if len(pathParts) == 2 {
|
||||
r.groupDiscoveryHandler.ServeHTTP(w, req)
|
||||
return
|
||||
}
|
||||
|
||||
r.delegate.ServeHTTP(w, req)
|
||||
return
|
||||
}
|
||||
|
||||
crdName := requestInfo.Resource + "." + requestInfo.APIGroup
|
||||
crd, err := r.crdLister.Get(crdName)
|
||||
if apierrors.IsNotFound(err) {
|
||||
r.delegate.ServeHTTP(w, req)
|
||||
return
|
||||
}
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
if !apiextensions.HasServedCRDVersion(crd, requestInfo.APIVersion) {
|
||||
r.delegate.ServeHTTP(w, req)
|
||||
return
|
||||
}
|
||||
// There is a small chance that a CRD is being served because NamesAccepted condition is true,
|
||||
// but it becomes "unserved" because another names update leads to a conflict
|
||||
// and EstablishingController wasn't fast enough to put the CRD into the Established condition.
|
||||
// We accept this as the problem is small and self-healing.
|
||||
if !apiextensions.IsCRDConditionTrue(crd, apiextensions.NamesAccepted) &&
|
||||
!apiextensions.IsCRDConditionTrue(crd, apiextensions.Established) {
|
||||
r.delegate.ServeHTTP(w, req)
|
||||
return
|
||||
}
|
||||
|
||||
terminating := apiextensions.IsCRDConditionTrue(crd, apiextensions.Terminating)
|
||||
|
||||
crdInfo, err := r.getOrCreateServingInfoFor(crd)
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
verb := strings.ToUpper(requestInfo.Verb)
|
||||
resource := requestInfo.Resource
|
||||
subresource := requestInfo.Subresource
|
||||
scope := metrics.CleanScope(requestInfo)
|
||||
supportedTypes := []string{
|
||||
string(types.JSONPatchType),
|
||||
string(types.MergePatchType),
|
||||
}
|
||||
|
||||
var handler http.HandlerFunc
|
||||
switch {
|
||||
case subresource == "status" && crd.Spec.Subresources != nil && crd.Spec.Subresources.Status != nil:
|
||||
handler = r.serveStatus(w, req, requestInfo, crdInfo, terminating, supportedTypes)
|
||||
case subresource == "scale" && crd.Spec.Subresources != nil && crd.Spec.Subresources.Scale != nil:
|
||||
handler = r.serveScale(w, req, requestInfo, crdInfo, terminating, supportedTypes)
|
||||
case len(subresource) == 0:
|
||||
handler = r.serveResource(w, req, requestInfo, crdInfo, terminating, supportedTypes)
|
||||
default:
|
||||
http.Error(w, "the server could not find the requested resource", http.StatusNotFound)
|
||||
}
|
||||
|
||||
if handler != nil {
|
||||
handler = metrics.InstrumentHandlerFunc(verb, resource, subresource, scope, handler)
|
||||
handler(w, req)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func (r *crdHandler) serveResource(w http.ResponseWriter, req *http.Request, requestInfo *apirequest.RequestInfo, crdInfo *crdInfo, terminating bool, supportedTypes []string) http.HandlerFunc {
|
||||
requestScope := crdInfo.requestScopes[requestInfo.APIVersion]
|
||||
storage := crdInfo.storages[requestInfo.APIVersion].CustomResource
|
||||
minRequestTimeout := 1 * time.Minute
|
||||
|
||||
switch requestInfo.Verb {
|
||||
case "get":
|
||||
return handlers.GetResource(storage, storage, requestScope)
|
||||
case "list":
|
||||
forceWatch := false
|
||||
return handlers.ListResource(storage, storage, requestScope, forceWatch, minRequestTimeout)
|
||||
case "watch":
|
||||
forceWatch := true
|
||||
return handlers.ListResource(storage, storage, requestScope, forceWatch, minRequestTimeout)
|
||||
case "create":
|
||||
if terminating {
|
||||
http.Error(w, fmt.Sprintf("%v not allowed while CustomResourceDefinition is terminating", requestInfo.Verb), http.StatusMethodNotAllowed)
|
||||
return nil
|
||||
}
|
||||
return handlers.CreateResource(storage, requestScope, r.admission)
|
||||
case "update":
|
||||
return handlers.UpdateResource(storage, requestScope, r.admission)
|
||||
case "patch":
|
||||
return handlers.PatchResource(storage, requestScope, r.admission, supportedTypes)
|
||||
case "delete":
|
||||
allowsOptions := true
|
||||
return handlers.DeleteResource(storage, allowsOptions, requestScope, r.admission)
|
||||
case "deletecollection":
|
||||
checkBody := true
|
||||
return handlers.DeleteCollection(storage, checkBody, requestScope, r.admission)
|
||||
default:
|
||||
http.Error(w, fmt.Sprintf("unhandled verb %q", requestInfo.Verb), http.StatusMethodNotAllowed)
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func (r *crdHandler) serveStatus(w http.ResponseWriter, req *http.Request, requestInfo *apirequest.RequestInfo, crdInfo *crdInfo, terminating bool, supportedTypes []string) http.HandlerFunc {
|
||||
requestScope := crdInfo.statusRequestScopes[requestInfo.APIVersion]
|
||||
storage := crdInfo.storages[requestInfo.APIVersion].Status
|
||||
|
||||
switch requestInfo.Verb {
|
||||
case "get":
|
||||
return handlers.GetResource(storage, nil, requestScope)
|
||||
case "update":
|
||||
return handlers.UpdateResource(storage, requestScope, r.admission)
|
||||
case "patch":
|
||||
return handlers.PatchResource(storage, requestScope, r.admission, supportedTypes)
|
||||
default:
|
||||
http.Error(w, fmt.Sprintf("unhandled verb %q", requestInfo.Verb), http.StatusMethodNotAllowed)
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func (r *crdHandler) serveScale(w http.ResponseWriter, req *http.Request, requestInfo *apirequest.RequestInfo, crdInfo *crdInfo, terminating bool, supportedTypes []string) http.HandlerFunc {
|
||||
requestScope := crdInfo.scaleRequestScopes[requestInfo.APIVersion]
|
||||
storage := crdInfo.storages[requestInfo.APIVersion].Scale
|
||||
|
||||
switch requestInfo.Verb {
|
||||
case "get":
|
||||
return handlers.GetResource(storage, nil, requestScope)
|
||||
case "update":
|
||||
return handlers.UpdateResource(storage, requestScope, r.admission)
|
||||
case "patch":
|
||||
return handlers.PatchResource(storage, requestScope, r.admission, supportedTypes)
|
||||
default:
|
||||
http.Error(w, fmt.Sprintf("unhandled verb %q", requestInfo.Verb), http.StatusMethodNotAllowed)
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func (r *crdHandler) updateCustomResourceDefinition(oldObj, newObj interface{}) {
|
||||
oldCRD := oldObj.(*apiextensions.CustomResourceDefinition)
|
||||
newCRD := newObj.(*apiextensions.CustomResourceDefinition)
|
||||
|
||||
r.customStorageLock.Lock()
|
||||
defer r.customStorageLock.Unlock()
|
||||
|
||||
// Add CRD to the establishing controller queue.
|
||||
// For HA clusters, we want to prevent race conditions when changing status to Established,
|
||||
// so we want to be sure that CRD is Installing at least for 5 seconds before Establishing it.
|
||||
// TODO: find a real HA safe checkpointing mechanism instead of an arbitrary wait.
|
||||
if !apiextensions.IsCRDConditionTrue(newCRD, apiextensions.Established) &&
|
||||
apiextensions.IsCRDConditionTrue(newCRD, apiextensions.NamesAccepted) {
|
||||
if r.masterCount > 1 {
|
||||
r.establishingController.QueueCRD(newCRD.Name, 5*time.Second)
|
||||
} else {
|
||||
r.establishingController.QueueCRD(newCRD.Name, 0)
|
||||
}
|
||||
}
|
||||
|
||||
storageMap := r.customStorage.Load().(crdStorageMap)
|
||||
oldInfo, found := storageMap[newCRD.UID]
|
||||
if !found {
|
||||
return
|
||||
}
|
||||
if apiequality.Semantic.DeepEqual(&newCRD.Spec, oldInfo.spec) && apiequality.Semantic.DeepEqual(&newCRD.Status.AcceptedNames, oldInfo.acceptedNames) {
|
||||
glog.V(6).Infof("Ignoring customresourcedefinition %s update because neither spec, nor accepted names changed", oldCRD.Name)
|
||||
return
|
||||
}
|
||||
|
||||
glog.V(4).Infof("Updating customresourcedefinition %s", oldCRD.Name)
|
||||
|
||||
// Copy because we cannot write to storageMap without a race
|
||||
// as it is used without locking elsewhere.
|
||||
storageMap2 := storageMap.clone()
|
||||
if oldInfo, ok := storageMap2[types.UID(oldCRD.UID)]; ok {
|
||||
for _, storage := range oldInfo.storages {
|
||||
// destroy only the main storage. Those for the subresources share cacher and etcd clients.
|
||||
storage.CustomResource.DestroyFunc()
|
||||
}
|
||||
delete(storageMap2, types.UID(oldCRD.UID))
|
||||
}
|
||||
|
||||
r.customStorage.Store(storageMap2)
|
||||
}
|
||||
|
||||
// removeDeadStorage removes REST storage that isn't being used
|
||||
func (r *crdHandler) removeDeadStorage() {
|
||||
allCustomResourceDefinitions, err := r.crdLister.List(labels.Everything())
|
||||
if err != nil {
|
||||
utilruntime.HandleError(err)
|
||||
return
|
||||
}
|
||||
|
||||
r.customStorageLock.Lock()
|
||||
defer r.customStorageLock.Unlock()
|
||||
|
||||
storageMap := r.customStorage.Load().(crdStorageMap)
|
||||
// Copy because we cannot write to storageMap without a race
|
||||
// as it is used without locking elsewhere
|
||||
storageMap2 := storageMap.clone()
|
||||
for uid, s := range storageMap2 {
|
||||
found := false
|
||||
for _, crd := range allCustomResourceDefinitions {
|
||||
if crd.UID == uid {
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
glog.V(4).Infof("Removing dead CRD storage for %s/%s", s.spec.Group, s.spec.Names.Kind)
|
||||
for _, storage := range s.storages {
|
||||
// destroy only the main storage. Those for the subresources share cacher and etcd clients.
|
||||
storage.CustomResource.DestroyFunc()
|
||||
}
|
||||
delete(storageMap2, uid)
|
||||
}
|
||||
}
|
||||
r.customStorage.Store(storageMap2)
|
||||
}
|
||||
|
||||
// GetCustomResourceListerCollectionDeleter returns the ListerCollectionDeleter of
|
||||
// the given crd.
|
||||
func (r *crdHandler) GetCustomResourceListerCollectionDeleter(crd *apiextensions.CustomResourceDefinition) (finalizer.ListerCollectionDeleter, error) {
|
||||
info, err := r.getOrCreateServingInfoFor(crd)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return info.storages[info.storageVersion].CustomResource, nil
|
||||
}
|
||||
|
||||
var swaggerMetadataDescriptions = metav1.ObjectMeta{}.SwaggerDoc()
|
||||
|
||||
func (r *crdHandler) getOrCreateServingInfoFor(crd *apiextensions.CustomResourceDefinition) (*crdInfo, error) {
|
||||
storageMap := r.customStorage.Load().(crdStorageMap)
|
||||
if ret, ok := storageMap[crd.UID]; ok {
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
r.customStorageLock.Lock()
|
||||
defer r.customStorageLock.Unlock()
|
||||
|
||||
storageMap = r.customStorage.Load().(crdStorageMap)
|
||||
if ret, ok := storageMap[crd.UID]; ok {
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
storageVersion, err := apiextensions.GetCRDStorageVersion(crd)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Scope/Storages per version.
|
||||
requestScopes := map[string]handlers.RequestScope{}
|
||||
storages := map[string]customresource.CustomResourceStorage{}
|
||||
statusScopes := map[string]handlers.RequestScope{}
|
||||
scaleScopes := map[string]handlers.RequestScope{}
|
||||
|
||||
for _, v := range crd.Spec.Versions {
|
||||
safeConverter, unsafeConverter := conversion.NewCRDConverter(crd)
|
||||
// In addition to Unstructured objects (Custom Resources), we also may sometimes need to
|
||||
// decode unversioned Options objects, so we delegate to parameterScheme for such types.
|
||||
parameterScheme := runtime.NewScheme()
|
||||
parameterScheme.AddUnversionedTypes(schema.GroupVersion{Group: crd.Spec.Group, Version: v.Name},
|
||||
&metav1.ListOptions{},
|
||||
&metav1.ExportOptions{},
|
||||
&metav1.GetOptions{},
|
||||
&metav1.DeleteOptions{},
|
||||
)
|
||||
parameterCodec := runtime.NewParameterCodec(parameterScheme)
|
||||
|
||||
kind := schema.GroupVersionKind{Group: crd.Spec.Group, Version: v.Name, Kind: crd.Status.AcceptedNames.Kind}
|
||||
typer := newUnstructuredObjectTyper(parameterScheme)
|
||||
creator := unstructuredCreator{}
|
||||
|
||||
validator, _, err := apiservervalidation.NewSchemaValidator(crd.Spec.Validation)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var statusSpec *apiextensions.CustomResourceSubresourceStatus
|
||||
var statusValidator *validate.SchemaValidator
|
||||
if utilfeature.DefaultFeatureGate.Enabled(apiextensionsfeatures.CustomResourceSubresources) && crd.Spec.Subresources != nil && crd.Spec.Subresources.Status != nil {
|
||||
statusSpec = crd.Spec.Subresources.Status
|
||||
|
||||
// for the status subresource, validate only against the status schema
|
||||
if crd.Spec.Validation != nil && crd.Spec.Validation.OpenAPIV3Schema != nil && crd.Spec.Validation.OpenAPIV3Schema.Properties != nil {
|
||||
if statusSchema, ok := crd.Spec.Validation.OpenAPIV3Schema.Properties["status"]; ok {
|
||||
openapiSchema := &spec.Schema{}
|
||||
if err := apiservervalidation.ConvertJSONSchemaProps(&statusSchema, openapiSchema); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
statusValidator = validate.NewSchemaValidator(openapiSchema, nil, "", strfmt.Default)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var scaleSpec *apiextensions.CustomResourceSubresourceScale
|
||||
if utilfeature.DefaultFeatureGate.Enabled(apiextensionsfeatures.CustomResourceSubresources) && crd.Spec.Subresources != nil && crd.Spec.Subresources.Scale != nil {
|
||||
scaleSpec = crd.Spec.Subresources.Scale
|
||||
}
|
||||
|
||||
table, err := tableconvertor.New(crd.Spec.AdditionalPrinterColumns)
|
||||
if err != nil {
|
||||
glog.V(2).Infof("The CRD for %v has an invalid printer specification, falling back to default printing: %v", kind, err)
|
||||
}
|
||||
|
||||
storages[v.Name] = customresource.NewStorage(
|
||||
schema.GroupResource{Group: crd.Spec.Group, Resource: crd.Status.AcceptedNames.Plural},
|
||||
schema.GroupVersionKind{Group: crd.Spec.Group, Version: v.Name, Kind: crd.Status.AcceptedNames.ListKind},
|
||||
customresource.NewStrategy(
|
||||
typer,
|
||||
crd.Spec.Scope == apiextensions.NamespaceScoped,
|
||||
kind,
|
||||
validator,
|
||||
statusValidator,
|
||||
statusSpec,
|
||||
scaleSpec,
|
||||
),
|
||||
crdConversionRESTOptionsGetter{
|
||||
RESTOptionsGetter: r.restOptionsGetter,
|
||||
converter: safeConverter,
|
||||
decoderVersion: schema.GroupVersion{Group: crd.Spec.Group, Version: v.Name},
|
||||
encoderVersion: schema.GroupVersion{Group: crd.Spec.Group, Version: storageVersion},
|
||||
},
|
||||
crd.Status.AcceptedNames.Categories,
|
||||
table,
|
||||
)
|
||||
|
||||
selfLinkPrefix := ""
|
||||
switch crd.Spec.Scope {
|
||||
case apiextensions.ClusterScoped:
|
||||
selfLinkPrefix = "/" + path.Join("apis", crd.Spec.Group, v.Name) + "/" + crd.Status.AcceptedNames.Plural + "/"
|
||||
case apiextensions.NamespaceScoped:
|
||||
selfLinkPrefix = "/" + path.Join("apis", crd.Spec.Group, v.Name, "namespaces") + "/"
|
||||
}
|
||||
|
||||
clusterScoped := crd.Spec.Scope == apiextensions.ClusterScoped
|
||||
|
||||
requestScopes[v.Name] = handlers.RequestScope{
|
||||
Namer: handlers.ContextBasedNaming{
|
||||
SelfLinker: meta.NewAccessor(),
|
||||
ClusterScoped: clusterScoped,
|
||||
SelfLinkPathPrefix: selfLinkPrefix,
|
||||
},
|
||||
Serializer: unstructuredNegotiatedSerializer{typer: typer, creator: creator, converter: safeConverter},
|
||||
ParameterCodec: parameterCodec,
|
||||
|
||||
Creater: creator,
|
||||
Convertor: safeConverter,
|
||||
Defaulter: unstructuredDefaulter{parameterScheme},
|
||||
Typer: typer,
|
||||
UnsafeConvertor: unsafeConverter,
|
||||
|
||||
Resource: schema.GroupVersionResource{Group: crd.Spec.Group, Version: v.Name, Resource: crd.Status.AcceptedNames.Plural},
|
||||
Kind: kind,
|
||||
|
||||
MetaGroupVersion: metav1.SchemeGroupVersion,
|
||||
|
||||
TableConvertor: storages[v.Name].CustomResource,
|
||||
}
|
||||
|
||||
// override scaleSpec subresource values
|
||||
// shallow copy
|
||||
scaleScope := requestScopes[v.Name]
|
||||
scaleConverter := scale.NewScaleConverter()
|
||||
scaleScope.Subresource = "scale"
|
||||
scaleScope.Serializer = serializer.NewCodecFactory(scaleConverter.Scheme())
|
||||
scaleScope.Kind = autoscalingv1.SchemeGroupVersion.WithKind("Scale")
|
||||
scaleScope.Namer = handlers.ContextBasedNaming{
|
||||
SelfLinker: meta.NewAccessor(),
|
||||
ClusterScoped: clusterScoped,
|
||||
SelfLinkPathPrefix: selfLinkPrefix,
|
||||
SelfLinkPathSuffix: "/scale",
|
||||
}
|
||||
scaleScopes[v.Name] = scaleScope
|
||||
|
||||
// override status subresource values
|
||||
// shallow copy
|
||||
statusScope := requestScopes[v.Name]
|
||||
statusScope.Subresource = "status"
|
||||
statusScope.Namer = handlers.ContextBasedNaming{
|
||||
SelfLinker: meta.NewAccessor(),
|
||||
ClusterScoped: clusterScoped,
|
||||
SelfLinkPathPrefix: selfLinkPrefix,
|
||||
SelfLinkPathSuffix: "/status",
|
||||
}
|
||||
statusScopes[v.Name] = statusScope
|
||||
}
|
||||
|
||||
ret := &crdInfo{
|
||||
spec: &crd.Spec,
|
||||
acceptedNames: &crd.Status.AcceptedNames,
|
||||
storages: storages,
|
||||
requestScopes: requestScopes,
|
||||
scaleRequestScopes: scaleScopes,
|
||||
statusRequestScopes: statusScopes,
|
||||
storageVersion: storageVersion,
|
||||
}
|
||||
|
||||
// Copy because we cannot write to storageMap without a race
|
||||
// as it is used without locking elsewhere.
|
||||
storageMap2 := storageMap.clone()
|
||||
|
||||
storageMap2[crd.UID] = ret
|
||||
r.customStorage.Store(storageMap2)
|
||||
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
type unstructuredNegotiatedSerializer struct {
|
||||
typer runtime.ObjectTyper
|
||||
creator runtime.ObjectCreater
|
||||
converter runtime.ObjectConvertor
|
||||
}
|
||||
|
||||
func (s unstructuredNegotiatedSerializer) SupportedMediaTypes() []runtime.SerializerInfo {
|
||||
return []runtime.SerializerInfo{
|
||||
{
|
||||
MediaType: "application/json",
|
||||
EncodesAsText: true,
|
||||
Serializer: json.NewSerializer(json.DefaultMetaFactory, s.creator, s.typer, false),
|
||||
PrettySerializer: json.NewSerializer(json.DefaultMetaFactory, s.creator, s.typer, true),
|
||||
StreamSerializer: &runtime.StreamSerializerInfo{
|
||||
EncodesAsText: true,
|
||||
Serializer: json.NewSerializer(json.DefaultMetaFactory, s.creator, s.typer, false),
|
||||
Framer: json.Framer,
|
||||
},
|
||||
},
|
||||
{
|
||||
MediaType: "application/yaml",
|
||||
EncodesAsText: true,
|
||||
Serializer: json.NewYAMLSerializer(json.DefaultMetaFactory, s.creator, s.typer),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (s unstructuredNegotiatedSerializer) EncoderForVersion(encoder runtime.Encoder, gv runtime.GroupVersioner) runtime.Encoder {
|
||||
return versioning.NewCodec(encoder, nil, s.converter, Scheme, Scheme, Scheme, gv, nil, "crdNegotiatedSerializer")
|
||||
}
|
||||
|
||||
func (s unstructuredNegotiatedSerializer) DecoderToVersion(decoder runtime.Decoder, gv runtime.GroupVersioner) runtime.Decoder {
|
||||
d := schemaCoercingDecoder{delegate: decoder, validator: unstructuredSchemaCoercer{}}
|
||||
return versioning.NewDefaultingCodecForScheme(Scheme, nil, d, nil, gv)
|
||||
}
|
||||
|
||||
type UnstructuredObjectTyper struct {
|
||||
Delegate runtime.ObjectTyper
|
||||
UnstructuredTyper runtime.ObjectTyper
|
||||
}
|
||||
|
||||
func newUnstructuredObjectTyper(Delegate runtime.ObjectTyper) UnstructuredObjectTyper {
|
||||
return UnstructuredObjectTyper{
|
||||
Delegate: Delegate,
|
||||
UnstructuredTyper: crdserverscheme.NewUnstructuredObjectTyper(),
|
||||
}
|
||||
}
|
||||
|
||||
func (t UnstructuredObjectTyper) ObjectKinds(obj runtime.Object) ([]schema.GroupVersionKind, bool, error) {
|
||||
// Delegate for things other than Unstructured.
|
||||
if _, ok := obj.(runtime.Unstructured); !ok {
|
||||
return t.Delegate.ObjectKinds(obj)
|
||||
}
|
||||
return t.UnstructuredTyper.ObjectKinds(obj)
|
||||
}
|
||||
|
||||
func (t UnstructuredObjectTyper) Recognizes(gvk schema.GroupVersionKind) bool {
|
||||
return t.Delegate.Recognizes(gvk) || t.UnstructuredTyper.Recognizes(gvk)
|
||||
}
|
||||
|
||||
type unstructuredCreator struct{}
|
||||
|
||||
func (c unstructuredCreator) New(kind schema.GroupVersionKind) (runtime.Object, error) {
|
||||
ret := &unstructured.Unstructured{}
|
||||
ret.SetGroupVersionKind(kind)
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
type unstructuredDefaulter struct {
|
||||
delegate runtime.ObjectDefaulter
|
||||
}
|
||||
|
||||
func (d unstructuredDefaulter) Default(in runtime.Object) {
|
||||
// Delegate for things other than Unstructured.
|
||||
if _, ok := in.(runtime.Unstructured); !ok {
|
||||
d.delegate.Default(in)
|
||||
}
|
||||
}
|
||||
|
||||
type CRDRESTOptionsGetter struct {
|
||||
StorageConfig storagebackend.Config
|
||||
StoragePrefix string
|
||||
EnableWatchCache bool
|
||||
DefaultWatchCacheSize int
|
||||
EnableGarbageCollection bool
|
||||
DeleteCollectionWorkers int
|
||||
}
|
||||
|
||||
func (t CRDRESTOptionsGetter) GetRESTOptions(resource schema.GroupResource) (generic.RESTOptions, error) {
|
||||
ret := generic.RESTOptions{
|
||||
StorageConfig: &t.StorageConfig,
|
||||
Decorator: generic.UndecoratedStorage,
|
||||
EnableGarbageCollection: t.EnableGarbageCollection,
|
||||
DeleteCollectionWorkers: t.DeleteCollectionWorkers,
|
||||
ResourcePrefix: resource.Group + "/" + resource.Resource,
|
||||
}
|
||||
if t.EnableWatchCache {
|
||||
ret.Decorator = genericregistry.StorageWithCacher(t.DefaultWatchCacheSize)
|
||||
}
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
// clone returns a clone of the provided crdStorageMap.
|
||||
// The clone is a shallow copy of the map.
|
||||
func (in crdStorageMap) clone() crdStorageMap {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := make(crdStorageMap, len(in))
|
||||
for key, value := range in {
|
||||
out[key] = value
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
// crdConversionRESTOptionsGetter overrides the codec with one using the
|
||||
// provided custom converter and custom encoder and decoder version.
|
||||
type crdConversionRESTOptionsGetter struct {
|
||||
generic.RESTOptionsGetter
|
||||
converter runtime.ObjectConvertor
|
||||
encoderVersion schema.GroupVersion
|
||||
decoderVersion schema.GroupVersion
|
||||
}
|
||||
|
||||
func (t crdConversionRESTOptionsGetter) GetRESTOptions(resource schema.GroupResource) (generic.RESTOptions, error) {
|
||||
ret, err := t.RESTOptionsGetter.GetRESTOptions(resource)
|
||||
if err == nil {
|
||||
d := schemaCoercingDecoder{delegate: ret.StorageConfig.Codec, validator: unstructuredSchemaCoercer{
|
||||
// drop invalid fields while decoding old CRs (before we had any ObjectMeta validation)
|
||||
dropInvalidMetadata: true,
|
||||
}}
|
||||
c := schemaCoercingConverter{delegate: t.converter, validator: unstructuredSchemaCoercer{}}
|
||||
ret.StorageConfig.Codec = versioning.NewCodec(
|
||||
ret.StorageConfig.Codec,
|
||||
d,
|
||||
c,
|
||||
&unstructuredCreator{},
|
||||
crdserverscheme.NewUnstructuredObjectTyper(),
|
||||
&unstructuredDefaulter{delegate: Scheme},
|
||||
t.encoderVersion,
|
||||
t.decoderVersion,
|
||||
"crdRESTOptions",
|
||||
)
|
||||
}
|
||||
return ret, err
|
||||
}
|
||||
|
||||
// schemaCoercingDecoder calls the delegate decoder, and then applies the Unstructured schema validator
|
||||
// to coerce the schema.
|
||||
type schemaCoercingDecoder struct {
|
||||
delegate runtime.Decoder
|
||||
validator unstructuredSchemaCoercer
|
||||
}
|
||||
|
||||
var _ runtime.Decoder = schemaCoercingDecoder{}
|
||||
|
||||
func (d schemaCoercingDecoder) Decode(data []byte, defaults *schema.GroupVersionKind, into runtime.Object) (runtime.Object, *schema.GroupVersionKind, error) {
|
||||
obj, gvk, err := d.delegate.Decode(data, defaults, into)
|
||||
if err != nil {
|
||||
return nil, gvk, err
|
||||
}
|
||||
if u, ok := obj.(*unstructured.Unstructured); ok {
|
||||
if err := d.validator.apply(u); err != nil {
|
||||
return nil, gvk, err
|
||||
}
|
||||
}
|
||||
|
||||
return obj, gvk, nil
|
||||
}
|
||||
|
||||
// schemaCoercingConverter calls the delegate converter and applies the Unstructured validator to
|
||||
// coerce the schema.
|
||||
type schemaCoercingConverter struct {
|
||||
delegate runtime.ObjectConvertor
|
||||
validator unstructuredSchemaCoercer
|
||||
}
|
||||
|
||||
var _ runtime.ObjectConvertor = schemaCoercingConverter{}
|
||||
|
||||
func (v schemaCoercingConverter) Convert(in, out, context interface{}) error {
|
||||
if err := v.delegate.Convert(in, out, context); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if u, ok := out.(*unstructured.Unstructured); ok {
|
||||
if err := v.validator.apply(u); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (v schemaCoercingConverter) ConvertToVersion(in runtime.Object, gv runtime.GroupVersioner) (runtime.Object, error) {
|
||||
out, err := v.delegate.ConvertToVersion(in, gv)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if u, ok := out.(*unstructured.Unstructured); ok {
|
||||
if err := v.validator.apply(u); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (v schemaCoercingConverter) ConvertFieldLabel(gvk schema.GroupVersionKind, label, value string) (string, string, error) {
|
||||
return v.delegate.ConvertFieldLabel(gvk, label, value)
|
||||
}
|
||||
|
||||
// unstructuredSchemaCoercer does the validation for Unstructured that json.Unmarshal
|
||||
// does for native types. This includes:
|
||||
// - validating and pruning ObjectMeta (here with optional error instead of pruning)
|
||||
// - TODO: application of an OpenAPI validator (against the whole object or a top-level field of it).
|
||||
// - TODO: optionally application of post-validation algorithms like defaulting and/or OpenAPI based pruning.
|
||||
type unstructuredSchemaCoercer struct {
|
||||
dropInvalidMetadata bool
|
||||
}
|
||||
|
||||
func (v *unstructuredSchemaCoercer) apply(u *unstructured.Unstructured) error {
|
||||
// save implicit meta fields that don't have to be specified in the validation spec
|
||||
kind, foundKind, err := unstructured.NestedString(u.UnstructuredContent(), "kind")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
apiVersion, foundApiVersion, err := unstructured.NestedString(u.UnstructuredContent(), "apiVersion")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
objectMeta, foundObjectMeta, err := getObjectMeta(u, v.dropInvalidMetadata)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// restore meta fields, starting clean
|
||||
if foundKind {
|
||||
u.SetKind(kind)
|
||||
}
|
||||
if foundApiVersion {
|
||||
u.SetAPIVersion(apiVersion)
|
||||
}
|
||||
if foundObjectMeta {
|
||||
if err := setObjectMeta(u, objectMeta); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
var encodingjson = json.CaseSensitiveJsonIterator()
|
||||
|
||||
func getObjectMeta(u *unstructured.Unstructured, dropMalformedFields bool) (*metav1.ObjectMeta, bool, error) {
|
||||
metadata, found := u.UnstructuredContent()["metadata"]
|
||||
if !found {
|
||||
return nil, false, nil
|
||||
}
|
||||
|
||||
// round-trip through JSON first, hoping that unmarshaling just works
|
||||
objectMeta := &metav1.ObjectMeta{}
|
||||
metadataBytes, err := encodingjson.Marshal(metadata)
|
||||
if err != nil {
|
||||
return nil, false, err
|
||||
}
|
||||
if err = encodingjson.Unmarshal(metadataBytes, objectMeta); err == nil {
|
||||
// if successful, return
|
||||
return objectMeta, true, nil
|
||||
}
|
||||
if !dropMalformedFields {
|
||||
// if we're not trying to drop malformed fields, return the error
|
||||
return nil, true, err
|
||||
}
|
||||
|
||||
metadataMap, ok := metadata.(map[string]interface{})
|
||||
if !ok {
|
||||
return nil, false, fmt.Errorf("invalid metadata: expected object, got %T", metadata)
|
||||
}
|
||||
|
||||
// Go field by field accumulating into the metadata object.
|
||||
// This takes advantage of the fact that you can repeatedly unmarshal individual fields into a single struct,
|
||||
// each iteration preserving the old key-values.
|
||||
accumulatedObjectMeta := &metav1.ObjectMeta{}
|
||||
testObjectMeta := &metav1.ObjectMeta{}
|
||||
for k, v := range metadataMap {
|
||||
// serialize a single field
|
||||
if singleFieldBytes, err := encodingjson.Marshal(map[string]interface{}{k: v}); err == nil {
|
||||
// do a test unmarshal
|
||||
if encodingjson.Unmarshal(singleFieldBytes, testObjectMeta) == nil {
|
||||
// if that succeeds, unmarshal for real
|
||||
encodingjson.Unmarshal(singleFieldBytes, accumulatedObjectMeta)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return accumulatedObjectMeta, true, nil
|
||||
}
|
||||
|
||||
func setObjectMeta(u *unstructured.Unstructured, objectMeta *metav1.ObjectMeta) error {
|
||||
if objectMeta == nil {
|
||||
unstructured.RemoveNestedField(u.UnstructuredContent(), "metadata")
|
||||
return nil
|
||||
}
|
||||
|
||||
metadata, err := runtime.DefaultUnstructuredConverter.ToUnstructured(objectMeta)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
u.UnstructuredContent()["metadata"] = metadata
|
||||
return nil
|
||||
}
|
||||
309
vendor/k8s.io/apiextensions-apiserver/pkg/apiserver/customresource_handler_test.go
generated
vendored
Normal file
309
vendor/k8s.io/apiextensions-apiserver/pkg/apiserver/customresource_handler_test.go
generated
vendored
Normal file
@@ -0,0 +1,309 @@
|
||||
/*
|
||||
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 apiserver
|
||||
|
||||
import (
|
||||
"math/rand"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
"k8s.io/apiextensions-apiserver/pkg/apis/apiextensions"
|
||||
"k8s.io/apiextensions-apiserver/pkg/apiserver/conversion"
|
||||
"k8s.io/apimachinery/pkg/api/equality"
|
||||
"k8s.io/apimachinery/pkg/api/testing/fuzzer"
|
||||
metafuzzer "k8s.io/apimachinery/pkg/apis/meta/fuzzer"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"k8s.io/apimachinery/pkg/runtime/serializer"
|
||||
"k8s.io/apimachinery/pkg/runtime/serializer/json"
|
||||
"k8s.io/apimachinery/pkg/util/diff"
|
||||
clientgoscheme "k8s.io/client-go/kubernetes/scheme"
|
||||
)
|
||||
|
||||
func TestConvertFieldLabel(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
clusterScoped bool
|
||||
label string
|
||||
expectError bool
|
||||
}{
|
||||
{
|
||||
name: "cluster scoped - name is ok",
|
||||
clusterScoped: true,
|
||||
label: "metadata.name",
|
||||
},
|
||||
{
|
||||
name: "cluster scoped - namespace is not ok",
|
||||
clusterScoped: true,
|
||||
label: "metadata.namespace",
|
||||
expectError: true,
|
||||
},
|
||||
{
|
||||
name: "cluster scoped - other field is not ok",
|
||||
clusterScoped: true,
|
||||
label: "some.other.field",
|
||||
expectError: true,
|
||||
},
|
||||
{
|
||||
name: "namespace scoped - name is ok",
|
||||
label: "metadata.name",
|
||||
},
|
||||
{
|
||||
name: "namespace scoped - namespace is ok",
|
||||
label: "metadata.namespace",
|
||||
},
|
||||
{
|
||||
name: "namespace scoped - other field is not ok",
|
||||
label: "some.other.field",
|
||||
expectError: true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
|
||||
crd := apiextensions.CustomResourceDefinition{}
|
||||
|
||||
if test.clusterScoped {
|
||||
crd.Spec.Scope = apiextensions.ClusterScoped
|
||||
} else {
|
||||
crd.Spec.Scope = apiextensions.NamespaceScoped
|
||||
}
|
||||
_, c := conversion.NewCRDConverter(&crd)
|
||||
|
||||
label, value, err := c.ConvertFieldLabel(schema.GroupVersionKind{}, test.label, "value")
|
||||
if e, a := test.expectError, err != nil; e != a {
|
||||
t.Fatalf("err: expected %t, got %t", e, a)
|
||||
}
|
||||
if test.expectError {
|
||||
if e, a := "field label not supported: "+test.label, err.Error(); e != a {
|
||||
t.Errorf("err: expected %s, got %s", e, a)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
if e, a := test.label, label; e != a {
|
||||
t.Errorf("label: expected %s, got %s", e, a)
|
||||
}
|
||||
if e, a := "value", value; e != a {
|
||||
t.Errorf("value: expected %s, got %s", e, a)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestRoundtripObjectMeta(t *testing.T) {
|
||||
scheme := runtime.NewScheme()
|
||||
codecs := serializer.NewCodecFactory(scheme)
|
||||
codec := json.NewSerializer(json.DefaultMetaFactory, scheme, scheme, false)
|
||||
seed := rand.Int63()
|
||||
fuzzer := fuzzer.FuzzerFor(metafuzzer.Funcs, rand.NewSource(seed), codecs)
|
||||
|
||||
N := 1000
|
||||
for i := 0; i < N; i++ {
|
||||
u := &unstructured.Unstructured{Object: map[string]interface{}{}}
|
||||
original := &metav1.ObjectMeta{}
|
||||
fuzzer.Fuzz(original)
|
||||
if err := setObjectMeta(u, original); err != nil {
|
||||
t.Fatalf("unexpected error setting ObjectMeta: %v", err)
|
||||
}
|
||||
o, _, err := getObjectMeta(u, false)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error getting the Objectmeta: %v", err)
|
||||
}
|
||||
|
||||
if !equality.Semantic.DeepEqual(original, o) {
|
||||
t.Errorf("diff: %v\nCodec: %#v", diff.ObjectReflectDiff(original, o), codec)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TestMalformedObjectMetaFields sets a number of different random values and types for all
|
||||
// metadata fields. If json.Unmarshal accepts them, compare that getObjectMeta
|
||||
// gives the same result. Otherwise, drop malformed fields.
|
||||
func TestMalformedObjectMetaFields(t *testing.T) {
|
||||
fuzzer := fuzzer.FuzzerFor(metafuzzer.Funcs, rand.NewSource(rand.Int63()), serializer.NewCodecFactory(runtime.NewScheme()))
|
||||
spuriousValues := func() []interface{} {
|
||||
return []interface{}{
|
||||
// primitives
|
||||
nil,
|
||||
int64(1),
|
||||
float64(1.5),
|
||||
true,
|
||||
"a",
|
||||
// well-formed complex values
|
||||
[]interface{}{"a", "b"},
|
||||
map[string]interface{}{"a": "1", "b": "2"},
|
||||
[]interface{}{int64(1), int64(2)},
|
||||
[]interface{}{float64(1.5), float64(2.5)},
|
||||
// known things json decoding tolerates
|
||||
map[string]interface{}{"a": "1", "b": nil},
|
||||
// malformed things
|
||||
map[string]interface{}{"a": "1", "b": []interface{}{"nested"}},
|
||||
[]interface{}{"a", int64(1), float64(1.5), true, []interface{}{"nested"}},
|
||||
}
|
||||
}
|
||||
N := 100
|
||||
for i := 0; i < N; i++ {
|
||||
fuzzedObjectMeta := &metav1.ObjectMeta{}
|
||||
fuzzer.Fuzz(fuzzedObjectMeta)
|
||||
goodMetaMap, err := runtime.DefaultUnstructuredConverter.ToUnstructured(fuzzedObjectMeta.DeepCopy())
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
for _, pth := range jsonPaths(nil, goodMetaMap) {
|
||||
for _, v := range spuriousValues() {
|
||||
// skip values of same type, because they can only cause decoding errors further insides
|
||||
orig, err := JsonPathValue(goodMetaMap, pth, 0)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected to not find something at %v: %v", pth, err)
|
||||
}
|
||||
if reflect.TypeOf(v) == reflect.TypeOf(orig) {
|
||||
continue
|
||||
}
|
||||
|
||||
// make a spurious map
|
||||
spuriousMetaMap, err := runtime.DefaultUnstructuredConverter.ToUnstructured(fuzzedObjectMeta.DeepCopy())
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := SetJsonPath(spuriousMetaMap, pth, 0, v); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// See if it can unmarshal to object meta
|
||||
spuriousJSON, err := encodingjson.Marshal(spuriousMetaMap)
|
||||
if err != nil {
|
||||
t.Fatalf("error on %v=%#v: %v", pth, v, err)
|
||||
}
|
||||
expectedObjectMeta := &metav1.ObjectMeta{}
|
||||
if err := encodingjson.Unmarshal(spuriousJSON, expectedObjectMeta); err != nil {
|
||||
// if standard json unmarshal would fail decoding this field, drop the field entirely
|
||||
truncatedMetaMap, err := runtime.DefaultUnstructuredConverter.ToUnstructured(fuzzedObjectMeta.DeepCopy())
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// we expect this logic for the different fields:
|
||||
switch {
|
||||
default:
|
||||
// delete complete top-level field by default
|
||||
DeleteJsonPath(truncatedMetaMap, pth[:1], 0)
|
||||
}
|
||||
|
||||
truncatedJSON, err := encodingjson.Marshal(truncatedMetaMap)
|
||||
if err != nil {
|
||||
t.Fatalf("error on %v=%#v: %v", pth, v, err)
|
||||
}
|
||||
expectedObjectMeta = &metav1.ObjectMeta{}
|
||||
if err := encodingjson.Unmarshal(truncatedJSON, expectedObjectMeta); err != nil {
|
||||
t.Fatalf("error on %v=%#v: %v", pth, v, err)
|
||||
}
|
||||
}
|
||||
|
||||
// make sure dropInvalidTypedFields+getObjectMeta matches what we expect
|
||||
u := &unstructured.Unstructured{Object: map[string]interface{}{"metadata": spuriousMetaMap}}
|
||||
actualObjectMeta, _, err := getObjectMeta(u, true)
|
||||
if err != nil {
|
||||
t.Errorf("got unexpected error after dropping invalid typed fields on %v=%#v: %v", pth, v, err)
|
||||
continue
|
||||
}
|
||||
|
||||
if !equality.Semantic.DeepEqual(expectedObjectMeta, actualObjectMeta) {
|
||||
t.Errorf("%v=%#v, diff: %v\n", pth, v, diff.ObjectReflectDiff(expectedObjectMeta, actualObjectMeta))
|
||||
t.Errorf("expectedObjectMeta %#v", expectedObjectMeta)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetObjectMetaNils(t *testing.T) {
|
||||
u := &unstructured.Unstructured{
|
||||
Object: map[string]interface{}{
|
||||
"kind": "Pod",
|
||||
"apiVersion": "v1",
|
||||
"metadata": map[string]interface{}{
|
||||
"generateName": nil,
|
||||
"labels": map[string]interface{}{
|
||||
"foo": nil,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
o, _, err := getObjectMeta(u, true)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if o.GenerateName != "" {
|
||||
t.Errorf("expected null json value to be read as \"\" string, but got: %q", o.GenerateName)
|
||||
}
|
||||
if got, expected := o.Labels, map[string]string{"foo": ""}; !reflect.DeepEqual(got, expected) {
|
||||
t.Errorf("unexpected labels, expected=%#v, got=%#v", expected, got)
|
||||
}
|
||||
|
||||
// double check this what the kube JSON decode is doing
|
||||
bs, _ := encodingjson.Marshal(u.UnstructuredContent())
|
||||
kubeObj, _, err := clientgoscheme.Codecs.UniversalDecoder(corev1.SchemeGroupVersion).Decode(bs, nil, nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
pod, ok := kubeObj.(*corev1.Pod)
|
||||
if !ok {
|
||||
t.Fatalf("expected v1 Pod, got: %T", pod)
|
||||
}
|
||||
if got, expected := o.GenerateName, pod.ObjectMeta.GenerateName; got != expected {
|
||||
t.Errorf("expected generatedName to be %q, got %q", expected, got)
|
||||
}
|
||||
if got, expected := o.Labels, pod.ObjectMeta.Labels; !reflect.DeepEqual(got, expected) {
|
||||
t.Errorf("expected labels to be %v, got %v", expected, got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetObjectMeta(t *testing.T) {
|
||||
for i := 0; i < 100; i++ {
|
||||
u := &unstructured.Unstructured{Object: map[string]interface{}{
|
||||
"metadata": map[string]interface{}{
|
||||
"name": "good",
|
||||
"Name": "bad1",
|
||||
"nAme": "bad2",
|
||||
"naMe": "bad3",
|
||||
"namE": "bad4",
|
||||
|
||||
"namespace": "good",
|
||||
"Namespace": "bad1",
|
||||
"nAmespace": "bad2",
|
||||
"naMespace": "bad3",
|
||||
"namEspace": "bad4",
|
||||
|
||||
"creationTimestamp": "a",
|
||||
},
|
||||
}}
|
||||
|
||||
meta, _, err := getObjectMeta(u, true)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if meta.Name != "good" || meta.Namespace != "good" {
|
||||
t.Fatalf("got %#v", meta)
|
||||
}
|
||||
}
|
||||
}
|
||||
235
vendor/k8s.io/apiextensions-apiserver/pkg/apiserver/jsonpath_test.go
generated
vendored
Normal file
235
vendor/k8s.io/apiextensions-apiserver/pkg/apiserver/jsonpath_test.go
generated
vendored
Normal file
@@ -0,0 +1,235 @@
|
||||
/*
|
||||
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 apiserver
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
)
|
||||
|
||||
type (
|
||||
jsonPathNode struct {
|
||||
index *int
|
||||
field string
|
||||
}
|
||||
JsonPath []jsonPathNode
|
||||
)
|
||||
|
||||
func (p JsonPath) String() string {
|
||||
var buf bytes.Buffer
|
||||
for _, n := range p {
|
||||
if n.index == nil {
|
||||
buf.WriteString("." + n.field)
|
||||
} else {
|
||||
buf.WriteString(fmt.Sprintf("[%d]", *n.index))
|
||||
}
|
||||
}
|
||||
return buf.String()
|
||||
}
|
||||
|
||||
func jsonPaths(base JsonPath, j map[string]interface{}) []JsonPath {
|
||||
res := make([]JsonPath, 0, len(j))
|
||||
for k, old := range j {
|
||||
kPth := append(append([]jsonPathNode(nil), base...), jsonPathNode{field: k})
|
||||
res = append(res, kPth)
|
||||
|
||||
switch old := old.(type) {
|
||||
case map[string]interface{}:
|
||||
res = append(res, jsonPaths(kPth, old)...)
|
||||
case []interface{}:
|
||||
res = append(res, jsonIterSlice(kPth, old)...)
|
||||
}
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
func jsonIterSlice(base JsonPath, j []interface{}) []JsonPath {
|
||||
res := make([]JsonPath, 0, len(j))
|
||||
for i, old := range j {
|
||||
index := i
|
||||
iPth := append(append([]jsonPathNode(nil), base...), jsonPathNode{index: &index})
|
||||
res = append(res, iPth)
|
||||
|
||||
switch old := old.(type) {
|
||||
case map[string]interface{}:
|
||||
res = append(res, jsonPaths(iPth, old)...)
|
||||
case []interface{}:
|
||||
res = append(res, jsonIterSlice(iPth, old)...)
|
||||
}
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
func JsonPathValue(j map[string]interface{}, pth JsonPath, base int) (interface{}, error) {
|
||||
if len(pth) == base {
|
||||
return nil, fmt.Errorf("empty json path is invalid for object")
|
||||
}
|
||||
if pth[base].index != nil {
|
||||
return nil, fmt.Errorf("index json path is invalid for object")
|
||||
}
|
||||
field, ok := j[pth[base].field]
|
||||
if !ok || len(pth) == base+1 {
|
||||
if len(pth) > base+1 {
|
||||
return nil, fmt.Errorf("invalid non-terminal json path %q for non-existing field", pth)
|
||||
}
|
||||
return j[pth[base].field], nil
|
||||
}
|
||||
switch field := field.(type) {
|
||||
case map[string]interface{}:
|
||||
return JsonPathValue(field, pth, base+1)
|
||||
case []interface{}:
|
||||
return jsonPathValueSlice(field, pth, base+1)
|
||||
default:
|
||||
return nil, fmt.Errorf("invalid non-terminal json path %q for field", pth[:base+1])
|
||||
}
|
||||
}
|
||||
|
||||
func jsonPathValueSlice(j []interface{}, pth JsonPath, base int) (interface{}, error) {
|
||||
if len(pth) == base {
|
||||
return nil, fmt.Errorf("empty json path %q is invalid for object", pth)
|
||||
}
|
||||
if pth[base].index == nil {
|
||||
return nil, fmt.Errorf("field json path %q is invalid for object", pth[:base+1])
|
||||
}
|
||||
if *pth[base].index >= len(j) {
|
||||
return nil, fmt.Errorf("invalid index %q for array of size %d", pth[:base+1], len(j))
|
||||
}
|
||||
if len(pth) == base+1 {
|
||||
return j[*pth[base].index], nil
|
||||
}
|
||||
switch item := j[*pth[base].index].(type) {
|
||||
case map[string]interface{}:
|
||||
return JsonPathValue(item, pth, base+1)
|
||||
case []interface{}:
|
||||
return jsonPathValueSlice(item, pth, base+1)
|
||||
default:
|
||||
return nil, fmt.Errorf("invalid non-terminal json path %q for index", pth[:base+1])
|
||||
}
|
||||
}
|
||||
|
||||
func SetJsonPath(j map[string]interface{}, pth JsonPath, base int, value interface{}) error {
|
||||
if len(pth) == base {
|
||||
return fmt.Errorf("empty json path is invalid for object")
|
||||
}
|
||||
if pth[base].index != nil {
|
||||
return fmt.Errorf("index json path is invalid for object")
|
||||
}
|
||||
field, ok := j[pth[base].field]
|
||||
if !ok || len(pth) == base+1 {
|
||||
if len(pth) > base+1 {
|
||||
return fmt.Errorf("invalid non-terminal json path %q for non-existing field", pth)
|
||||
}
|
||||
j[pth[base].field] = runtime.DeepCopyJSONValue(value)
|
||||
return nil
|
||||
}
|
||||
switch field := field.(type) {
|
||||
case map[string]interface{}:
|
||||
return SetJsonPath(field, pth, base+1, value)
|
||||
case []interface{}:
|
||||
return setJsonPathSlice(field, pth, base+1, value)
|
||||
default:
|
||||
return fmt.Errorf("invalid non-terminal json path %q for field", pth[:base+1])
|
||||
}
|
||||
}
|
||||
|
||||
func setJsonPathSlice(j []interface{}, pth JsonPath, base int, value interface{}) error {
|
||||
if len(pth) == base {
|
||||
return fmt.Errorf("empty json path %q is invalid for object", pth)
|
||||
}
|
||||
if pth[base].index == nil {
|
||||
return fmt.Errorf("field json path %q is invalid for object", pth[:base+1])
|
||||
}
|
||||
if *pth[base].index >= len(j) {
|
||||
return fmt.Errorf("invalid index %q for array of size %d", pth[:base+1], len(j))
|
||||
}
|
||||
if len(pth) == base+1 {
|
||||
j[*pth[base].index] = runtime.DeepCopyJSONValue(value)
|
||||
return nil
|
||||
}
|
||||
switch item := j[*pth[base].index].(type) {
|
||||
case map[string]interface{}:
|
||||
return SetJsonPath(item, pth, base+1, value)
|
||||
case []interface{}:
|
||||
return setJsonPathSlice(item, pth, base+1, value)
|
||||
default:
|
||||
return fmt.Errorf("invalid non-terminal json path %q for index", pth[:base+1])
|
||||
}
|
||||
}
|
||||
|
||||
func DeleteJsonPath(j map[string]interface{}, pth JsonPath, base int) error {
|
||||
if len(pth) == base {
|
||||
return fmt.Errorf("empty json path is invalid for object")
|
||||
}
|
||||
if pth[base].index != nil {
|
||||
return fmt.Errorf("index json path is invalid for object")
|
||||
}
|
||||
field, ok := j[pth[base].field]
|
||||
if !ok || len(pth) == base+1 {
|
||||
if len(pth) > base+1 {
|
||||
return fmt.Errorf("invalid non-terminal json path %q for non-existing field", pth)
|
||||
}
|
||||
delete(j, pth[base].field)
|
||||
return nil
|
||||
}
|
||||
switch field := field.(type) {
|
||||
case map[string]interface{}:
|
||||
return DeleteJsonPath(field, pth, base+1)
|
||||
case []interface{}:
|
||||
if len(pth) == base+2 {
|
||||
if pth[base+1].index == nil {
|
||||
return fmt.Errorf("field json path %q is invalid for object", pth)
|
||||
}
|
||||
j[pth[base].field] = append(field[:*pth[base+1].index], field[*pth[base+1].index+1:]...)
|
||||
return nil
|
||||
}
|
||||
return deleteJsonPathSlice(field, pth, base+1)
|
||||
default:
|
||||
return fmt.Errorf("invalid non-terminal json path %q for field", pth[:base+1])
|
||||
}
|
||||
}
|
||||
|
||||
func deleteJsonPathSlice(j []interface{}, pth JsonPath, base int) error {
|
||||
if len(pth) == base {
|
||||
return fmt.Errorf("empty json path %q is invalid for object", pth)
|
||||
}
|
||||
if pth[base].index == nil {
|
||||
return fmt.Errorf("field json path %q is invalid for object", pth[:base+1])
|
||||
}
|
||||
if *pth[base].index >= len(j) {
|
||||
return fmt.Errorf("invalid index %q for array of size %d", pth[:base+1], len(j))
|
||||
}
|
||||
if len(pth) == base+1 {
|
||||
return fmt.Errorf("cannot delete item at index %q in-place", pth[:base])
|
||||
}
|
||||
switch item := j[*pth[base].index].(type) {
|
||||
case map[string]interface{}:
|
||||
return DeleteJsonPath(item, pth, base+1)
|
||||
case []interface{}:
|
||||
if len(pth) == base+2 {
|
||||
if pth[base+1].index == nil {
|
||||
return fmt.Errorf("field json path %q is invalid for object", pth)
|
||||
}
|
||||
j[*pth[base].index] = append(item[:*pth[base+1].index], item[*pth[base+1].index+1:])
|
||||
return nil
|
||||
}
|
||||
return deleteJsonPathSlice(item, pth, base+1)
|
||||
default:
|
||||
return fmt.Errorf("invalid non-terminal json path %q for index", pth[:base+1])
|
||||
}
|
||||
}
|
||||
249
vendor/k8s.io/apiextensions-apiserver/pkg/apiserver/validation/validation.go
generated
vendored
Normal file
249
vendor/k8s.io/apiextensions-apiserver/pkg/apiserver/validation/validation.go
generated
vendored
Normal file
@@ -0,0 +1,249 @@
|
||||
/*
|
||||
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 validation
|
||||
|
||||
import (
|
||||
"github.com/go-openapi/spec"
|
||||
"github.com/go-openapi/strfmt"
|
||||
"github.com/go-openapi/validate"
|
||||
|
||||
"k8s.io/apiextensions-apiserver/pkg/apis/apiextensions"
|
||||
)
|
||||
|
||||
// NewSchemaValidator creates an openapi schema validator for the given CRD validation.
|
||||
func NewSchemaValidator(customResourceValidation *apiextensions.CustomResourceValidation) (*validate.SchemaValidator, *spec.Schema, error) {
|
||||
// Convert CRD schema to openapi schema
|
||||
openapiSchema := &spec.Schema{}
|
||||
if customResourceValidation != nil {
|
||||
if err := ConvertJSONSchemaProps(customResourceValidation.OpenAPIV3Schema, openapiSchema); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
}
|
||||
return validate.NewSchemaValidator(openapiSchema, nil, "", strfmt.Default), openapiSchema, nil
|
||||
}
|
||||
|
||||
// ValidateCustomResource validates the Custom Resource against the schema in the CustomResourceDefinition.
|
||||
// CustomResource is a JSON data structure.
|
||||
func ValidateCustomResource(customResource interface{}, validator *validate.SchemaValidator) error {
|
||||
if validator == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
result := validator.Validate(customResource)
|
||||
if result.AsError() != nil {
|
||||
return result.AsError()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// ConvertJSONSchemaProps converts the schema from apiextensions.JSONSchemaPropos to go-openapi/spec.Schema
|
||||
func ConvertJSONSchemaProps(in *apiextensions.JSONSchemaProps, out *spec.Schema) error {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
out.ID = in.ID
|
||||
out.Schema = spec.SchemaURL(in.Schema)
|
||||
out.Description = in.Description
|
||||
if in.Type != "" {
|
||||
out.Type = spec.StringOrArray([]string{in.Type})
|
||||
}
|
||||
out.Format = in.Format
|
||||
out.Title = in.Title
|
||||
out.Maximum = in.Maximum
|
||||
out.ExclusiveMaximum = in.ExclusiveMaximum
|
||||
out.Minimum = in.Minimum
|
||||
out.ExclusiveMinimum = in.ExclusiveMinimum
|
||||
out.MaxLength = in.MaxLength
|
||||
out.MinLength = in.MinLength
|
||||
out.Pattern = in.Pattern
|
||||
out.MaxItems = in.MaxItems
|
||||
out.MinItems = in.MinItems
|
||||
out.UniqueItems = in.UniqueItems
|
||||
out.MultipleOf = in.MultipleOf
|
||||
out.MaxProperties = in.MaxProperties
|
||||
out.MinProperties = in.MinProperties
|
||||
out.Required = in.Required
|
||||
|
||||
if in.Default != nil {
|
||||
out.Default = *(in.Default)
|
||||
}
|
||||
if in.Example != nil {
|
||||
out.Example = *(in.Example)
|
||||
}
|
||||
|
||||
out.Enum = make([]interface{}, len(in.Enum))
|
||||
for k, v := range in.Enum {
|
||||
out.Enum[k] = v
|
||||
}
|
||||
|
||||
if err := convertSliceOfJSONSchemaProps(&in.AllOf, &out.AllOf); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := convertSliceOfJSONSchemaProps(&in.OneOf, &out.OneOf); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := convertSliceOfJSONSchemaProps(&in.AnyOf, &out.AnyOf); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if in.Not != nil {
|
||||
in, out := &in.Not, &out.Not
|
||||
*out = new(spec.Schema)
|
||||
if err := ConvertJSONSchemaProps(*in, *out); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
var err error
|
||||
out.Properties, err = convertMapOfJSONSchemaProps(in.Properties)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
out.PatternProperties, err = convertMapOfJSONSchemaProps(in.PatternProperties)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
out.Definitions, err = convertMapOfJSONSchemaProps(in.Definitions)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if in.Ref != nil {
|
||||
out.Ref, err = spec.NewRef(*in.Ref)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if in.AdditionalProperties != nil {
|
||||
in, out := &in.AdditionalProperties, &out.AdditionalProperties
|
||||
*out = new(spec.SchemaOrBool)
|
||||
if err := convertJSONSchemaPropsorBool(*in, *out); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if in.AdditionalItems != nil {
|
||||
in, out := &in.AdditionalItems, &out.AdditionalItems
|
||||
*out = new(spec.SchemaOrBool)
|
||||
if err := convertJSONSchemaPropsorBool(*in, *out); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if in.Items != nil {
|
||||
in, out := &in.Items, &out.Items
|
||||
*out = new(spec.SchemaOrArray)
|
||||
if err := convertJSONSchemaPropsOrArray(*in, *out); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if in.Dependencies != nil {
|
||||
in, out := &in.Dependencies, &out.Dependencies
|
||||
*out = make(spec.Dependencies, len(*in))
|
||||
for key, val := range *in {
|
||||
newVal := new(spec.SchemaOrStringArray)
|
||||
if err := convertJSONSchemaPropsOrStringArray(&val, newVal); err != nil {
|
||||
return err
|
||||
}
|
||||
(*out)[key] = *newVal
|
||||
}
|
||||
}
|
||||
|
||||
if in.ExternalDocs != nil {
|
||||
out.ExternalDocs = &spec.ExternalDocumentation{}
|
||||
out.ExternalDocs.Description = in.ExternalDocs.Description
|
||||
out.ExternalDocs.URL = in.ExternalDocs.URL
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func convertSliceOfJSONSchemaProps(in *[]apiextensions.JSONSchemaProps, out *[]spec.Schema) error {
|
||||
if in != nil {
|
||||
for _, jsonSchemaProps := range *in {
|
||||
schema := spec.Schema{}
|
||||
if err := ConvertJSONSchemaProps(&jsonSchemaProps, &schema); err != nil {
|
||||
return err
|
||||
}
|
||||
*out = append(*out, schema)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func convertMapOfJSONSchemaProps(in map[string]apiextensions.JSONSchemaProps) (map[string]spec.Schema, error) {
|
||||
out := make(map[string]spec.Schema)
|
||||
if len(in) != 0 {
|
||||
for k, jsonSchemaProps := range in {
|
||||
schema := spec.Schema{}
|
||||
if err := ConvertJSONSchemaProps(&jsonSchemaProps, &schema); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
out[k] = schema
|
||||
}
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func convertJSONSchemaPropsOrArray(in *apiextensions.JSONSchemaPropsOrArray, out *spec.SchemaOrArray) error {
|
||||
if in.Schema != nil {
|
||||
in, out := &in.Schema, &out.Schema
|
||||
*out = new(spec.Schema)
|
||||
if err := ConvertJSONSchemaProps(*in, *out); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if in.JSONSchemas != nil {
|
||||
in, out := &in.JSONSchemas, &out.Schemas
|
||||
*out = make([]spec.Schema, len(*in))
|
||||
for i := range *in {
|
||||
if err := ConvertJSONSchemaProps(&(*in)[i], &(*out)[i]); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func convertJSONSchemaPropsorBool(in *apiextensions.JSONSchemaPropsOrBool, out *spec.SchemaOrBool) error {
|
||||
out.Allows = in.Allows
|
||||
if in.Schema != nil {
|
||||
in, out := &in.Schema, &out.Schema
|
||||
*out = new(spec.Schema)
|
||||
if err := ConvertJSONSchemaProps(*in, *out); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func convertJSONSchemaPropsOrStringArray(in *apiextensions.JSONSchemaPropsOrStringArray, out *spec.SchemaOrStringArray) error {
|
||||
out.Property = in.Property
|
||||
if in.Schema != nil {
|
||||
in, out := &in.Schema, &out.Schema
|
||||
*out = new(spec.Schema)
|
||||
if err := ConvertJSONSchemaProps(*in, *out); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
87
vendor/k8s.io/apiextensions-apiserver/pkg/apiserver/validation/validation_test.go
generated
vendored
Normal file
87
vendor/k8s.io/apiextensions-apiserver/pkg/apiserver/validation/validation_test.go
generated
vendored
Normal file
@@ -0,0 +1,87 @@
|
||||
/*
|
||||
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 validation
|
||||
|
||||
import (
|
||||
"math/rand"
|
||||
"testing"
|
||||
|
||||
"github.com/go-openapi/spec"
|
||||
|
||||
apiequality "k8s.io/apimachinery/pkg/api/equality"
|
||||
"k8s.io/apimachinery/pkg/api/testing/fuzzer"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/runtime/serializer"
|
||||
"k8s.io/apimachinery/pkg/util/json"
|
||||
|
||||
"k8s.io/apiextensions-apiserver/pkg/apis/apiextensions"
|
||||
apiextensionsfuzzer "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/fuzzer"
|
||||
apiextensionsv1beta1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1"
|
||||
)
|
||||
|
||||
// TestRoundTrip checks the conversion to go-openapi types.
|
||||
// internal -> go-openapi -> JSON -> external -> internal
|
||||
func TestRoundTrip(t *testing.T) {
|
||||
scheme := runtime.NewScheme()
|
||||
codecs := serializer.NewCodecFactory(scheme)
|
||||
|
||||
// add internal and external types to scheme
|
||||
if err := apiextensions.AddToScheme(scheme); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := apiextensionsv1beta1.AddToScheme(scheme); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
seed := rand.Int63()
|
||||
fuzzerFuncs := fuzzer.MergeFuzzerFuncs(apiextensionsfuzzer.Funcs)
|
||||
f := fuzzer.FuzzerFor(fuzzerFuncs, rand.NewSource(seed), codecs)
|
||||
|
||||
for i := 0; i < 20; i++ {
|
||||
// fuzz internal types
|
||||
internal := &apiextensions.JSONSchemaProps{}
|
||||
f.Fuzz(internal)
|
||||
|
||||
// internal -> go-openapi
|
||||
openAPITypes := &spec.Schema{}
|
||||
if err := ConvertJSONSchemaProps(internal, openAPITypes); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// go-openapi -> JSON
|
||||
openAPIJSON, err := json.Marshal(openAPITypes)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// JSON -> external
|
||||
external := &apiextensionsv1beta1.JSONSchemaProps{}
|
||||
if err := json.Unmarshal(openAPIJSON, external); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// external -> internal
|
||||
internalRoundTripped := &apiextensions.JSONSchemaProps{}
|
||||
if err := scheme.Convert(external, internalRoundTripped, nil); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if !apiequality.Semantic.DeepEqual(internal, internalRoundTripped) {
|
||||
t.Fatalf("expected\n\t%#v, got \n\t%#v", internal, internalRoundTripped)
|
||||
}
|
||||
}
|
||||
}
|
||||
98
vendor/k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/clientset.go
generated
vendored
Normal file
98
vendor/k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/clientset.go
generated
vendored
Normal file
@@ -0,0 +1,98 @@
|
||||
/*
|
||||
Copyright 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.
|
||||
*/
|
||||
|
||||
// Code generated by client-gen. DO NOT EDIT.
|
||||
|
||||
package clientset
|
||||
|
||||
import (
|
||||
apiextensionsv1beta1 "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/typed/apiextensions/v1beta1"
|
||||
discovery "k8s.io/client-go/discovery"
|
||||
rest "k8s.io/client-go/rest"
|
||||
flowcontrol "k8s.io/client-go/util/flowcontrol"
|
||||
)
|
||||
|
||||
type Interface interface {
|
||||
Discovery() discovery.DiscoveryInterface
|
||||
ApiextensionsV1beta1() apiextensionsv1beta1.ApiextensionsV1beta1Interface
|
||||
// Deprecated: please explicitly pick a version if possible.
|
||||
Apiextensions() apiextensionsv1beta1.ApiextensionsV1beta1Interface
|
||||
}
|
||||
|
||||
// Clientset contains the clients for groups. Each group has exactly one
|
||||
// version included in a Clientset.
|
||||
type Clientset struct {
|
||||
*discovery.DiscoveryClient
|
||||
apiextensionsV1beta1 *apiextensionsv1beta1.ApiextensionsV1beta1Client
|
||||
}
|
||||
|
||||
// ApiextensionsV1beta1 retrieves the ApiextensionsV1beta1Client
|
||||
func (c *Clientset) ApiextensionsV1beta1() apiextensionsv1beta1.ApiextensionsV1beta1Interface {
|
||||
return c.apiextensionsV1beta1
|
||||
}
|
||||
|
||||
// Deprecated: Apiextensions retrieves the default version of ApiextensionsClient.
|
||||
// Please explicitly pick a version.
|
||||
func (c *Clientset) Apiextensions() apiextensionsv1beta1.ApiextensionsV1beta1Interface {
|
||||
return c.apiextensionsV1beta1
|
||||
}
|
||||
|
||||
// Discovery retrieves the DiscoveryClient
|
||||
func (c *Clientset) Discovery() discovery.DiscoveryInterface {
|
||||
if c == nil {
|
||||
return nil
|
||||
}
|
||||
return c.DiscoveryClient
|
||||
}
|
||||
|
||||
// NewForConfig creates a new Clientset for the given config.
|
||||
func NewForConfig(c *rest.Config) (*Clientset, error) {
|
||||
configShallowCopy := *c
|
||||
if configShallowCopy.RateLimiter == nil && configShallowCopy.QPS > 0 {
|
||||
configShallowCopy.RateLimiter = flowcontrol.NewTokenBucketRateLimiter(configShallowCopy.QPS, configShallowCopy.Burst)
|
||||
}
|
||||
var cs Clientset
|
||||
var err error
|
||||
cs.apiextensionsV1beta1, err = apiextensionsv1beta1.NewForConfig(&configShallowCopy)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
cs.DiscoveryClient, err = discovery.NewDiscoveryClientForConfig(&configShallowCopy)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &cs, nil
|
||||
}
|
||||
|
||||
// NewForConfigOrDie creates a new Clientset for the given config and
|
||||
// panics if there is an error in the config.
|
||||
func NewForConfigOrDie(c *rest.Config) *Clientset {
|
||||
var cs Clientset
|
||||
cs.apiextensionsV1beta1 = apiextensionsv1beta1.NewForConfigOrDie(c)
|
||||
|
||||
cs.DiscoveryClient = discovery.NewDiscoveryClientForConfigOrDie(c)
|
||||
return &cs
|
||||
}
|
||||
|
||||
// New creates a new Clientset for the given RESTClient.
|
||||
func New(c rest.Interface) *Clientset {
|
||||
var cs Clientset
|
||||
cs.apiextensionsV1beta1 = apiextensionsv1beta1.New(c)
|
||||
|
||||
cs.DiscoveryClient = discovery.NewDiscoveryClient(c)
|
||||
return &cs
|
||||
}
|
||||
20
vendor/k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/doc.go
generated
vendored
Normal file
20
vendor/k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/doc.go
generated
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
Copyright 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.
|
||||
*/
|
||||
|
||||
// Code generated by client-gen. DO NOT EDIT.
|
||||
|
||||
// This package has the automatically generated clientset.
|
||||
package clientset
|
||||
82
vendor/k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/fake/clientset_generated.go
generated
vendored
Normal file
82
vendor/k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/fake/clientset_generated.go
generated
vendored
Normal file
@@ -0,0 +1,82 @@
|
||||
/*
|
||||
Copyright 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.
|
||||
*/
|
||||
|
||||
// Code generated by client-gen. DO NOT EDIT.
|
||||
|
||||
package fake
|
||||
|
||||
import (
|
||||
clientset "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset"
|
||||
apiextensionsv1beta1 "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/typed/apiextensions/v1beta1"
|
||||
fakeapiextensionsv1beta1 "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/typed/apiextensions/v1beta1/fake"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/watch"
|
||||
"k8s.io/client-go/discovery"
|
||||
fakediscovery "k8s.io/client-go/discovery/fake"
|
||||
"k8s.io/client-go/testing"
|
||||
)
|
||||
|
||||
// NewSimpleClientset returns a clientset that will respond with the provided objects.
|
||||
// It's backed by a very simple object tracker that processes creates, updates and deletions as-is,
|
||||
// without applying any validations and/or defaults. It shouldn't be considered a replacement
|
||||
// for a real clientset and is mostly useful in simple unit tests.
|
||||
func NewSimpleClientset(objects ...runtime.Object) *Clientset {
|
||||
o := testing.NewObjectTracker(scheme, codecs.UniversalDecoder())
|
||||
for _, obj := range objects {
|
||||
if err := o.Add(obj); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
cs := &Clientset{}
|
||||
cs.discovery = &fakediscovery.FakeDiscovery{Fake: &cs.Fake}
|
||||
cs.AddReactor("*", "*", testing.ObjectReaction(o))
|
||||
cs.AddWatchReactor("*", func(action testing.Action) (handled bool, ret watch.Interface, err error) {
|
||||
gvr := action.GetResource()
|
||||
ns := action.GetNamespace()
|
||||
watch, err := o.Watch(gvr, ns)
|
||||
if err != nil {
|
||||
return false, nil, err
|
||||
}
|
||||
return true, watch, nil
|
||||
})
|
||||
|
||||
return cs
|
||||
}
|
||||
|
||||
// Clientset implements clientset.Interface. Meant to be embedded into a
|
||||
// struct to get a default implementation. This makes faking out just the method
|
||||
// you want to test easier.
|
||||
type Clientset struct {
|
||||
testing.Fake
|
||||
discovery *fakediscovery.FakeDiscovery
|
||||
}
|
||||
|
||||
func (c *Clientset) Discovery() discovery.DiscoveryInterface {
|
||||
return c.discovery
|
||||
}
|
||||
|
||||
var _ clientset.Interface = &Clientset{}
|
||||
|
||||
// ApiextensionsV1beta1 retrieves the ApiextensionsV1beta1Client
|
||||
func (c *Clientset) ApiextensionsV1beta1() apiextensionsv1beta1.ApiextensionsV1beta1Interface {
|
||||
return &fakeapiextensionsv1beta1.FakeApiextensionsV1beta1{Fake: &c.Fake}
|
||||
}
|
||||
|
||||
// Apiextensions retrieves the ApiextensionsV1beta1Client
|
||||
func (c *Clientset) Apiextensions() apiextensionsv1beta1.ApiextensionsV1beta1Interface {
|
||||
return &fakeapiextensionsv1beta1.FakeApiextensionsV1beta1{Fake: &c.Fake}
|
||||
}
|
||||
20
vendor/k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/fake/doc.go
generated
vendored
Normal file
20
vendor/k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/fake/doc.go
generated
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
Copyright 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.
|
||||
*/
|
||||
|
||||
// Code generated by client-gen. DO NOT EDIT.
|
||||
|
||||
// This package has the automatically generated fake clientset.
|
||||
package fake
|
||||
56
vendor/k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/fake/register.go
generated
vendored
Normal file
56
vendor/k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/fake/register.go
generated
vendored
Normal file
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
Copyright 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.
|
||||
*/
|
||||
|
||||
// Code generated by client-gen. DO NOT EDIT.
|
||||
|
||||
package fake
|
||||
|
||||
import (
|
||||
apiextensionsv1beta1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1"
|
||||
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
runtime "k8s.io/apimachinery/pkg/runtime"
|
||||
schema "k8s.io/apimachinery/pkg/runtime/schema"
|
||||
serializer "k8s.io/apimachinery/pkg/runtime/serializer"
|
||||
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
|
||||
)
|
||||
|
||||
var scheme = runtime.NewScheme()
|
||||
var codecs = serializer.NewCodecFactory(scheme)
|
||||
var parameterCodec = runtime.NewParameterCodec(scheme)
|
||||
var localSchemeBuilder = runtime.SchemeBuilder{
|
||||
apiextensionsv1beta1.AddToScheme,
|
||||
}
|
||||
|
||||
// AddToScheme adds all types of this clientset into the given scheme. This allows composition
|
||||
// of clientsets, like in:
|
||||
//
|
||||
// import (
|
||||
// "k8s.io/client-go/kubernetes"
|
||||
// clientsetscheme "k8s.io/client-go/kubernetes/scheme"
|
||||
// aggregatorclientsetscheme "k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/scheme"
|
||||
// )
|
||||
//
|
||||
// kclientset, _ := kubernetes.NewForConfig(c)
|
||||
// _ = aggregatorclientsetscheme.AddToScheme(clientsetscheme.Scheme)
|
||||
//
|
||||
// After this, RawExtensions in Kubernetes types will serialize kube-aggregator types
|
||||
// correctly.
|
||||
var AddToScheme = localSchemeBuilder.AddToScheme
|
||||
|
||||
func init() {
|
||||
v1.AddToGroupVersion(scheme, schema.GroupVersion{Version: "v1"})
|
||||
utilruntime.Must(AddToScheme(scheme))
|
||||
}
|
||||
20
vendor/k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/scheme/doc.go
generated
vendored
Normal file
20
vendor/k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/scheme/doc.go
generated
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
Copyright 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.
|
||||
*/
|
||||
|
||||
// Code generated by client-gen. DO NOT EDIT.
|
||||
|
||||
// This package contains the scheme of the automatically generated clientset.
|
||||
package scheme
|
||||
56
vendor/k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/scheme/register.go
generated
vendored
Normal file
56
vendor/k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/scheme/register.go
generated
vendored
Normal file
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
Copyright 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.
|
||||
*/
|
||||
|
||||
// Code generated by client-gen. DO NOT EDIT.
|
||||
|
||||
package scheme
|
||||
|
||||
import (
|
||||
apiextensionsv1beta1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1"
|
||||
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
runtime "k8s.io/apimachinery/pkg/runtime"
|
||||
schema "k8s.io/apimachinery/pkg/runtime/schema"
|
||||
serializer "k8s.io/apimachinery/pkg/runtime/serializer"
|
||||
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
|
||||
)
|
||||
|
||||
var Scheme = runtime.NewScheme()
|
||||
var Codecs = serializer.NewCodecFactory(Scheme)
|
||||
var ParameterCodec = runtime.NewParameterCodec(Scheme)
|
||||
var localSchemeBuilder = runtime.SchemeBuilder{
|
||||
apiextensionsv1beta1.AddToScheme,
|
||||
}
|
||||
|
||||
// AddToScheme adds all types of this clientset into the given scheme. This allows composition
|
||||
// of clientsets, like in:
|
||||
//
|
||||
// import (
|
||||
// "k8s.io/client-go/kubernetes"
|
||||
// clientsetscheme "k8s.io/client-go/kubernetes/scheme"
|
||||
// aggregatorclientsetscheme "k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/scheme"
|
||||
// )
|
||||
//
|
||||
// kclientset, _ := kubernetes.NewForConfig(c)
|
||||
// _ = aggregatorclientsetscheme.AddToScheme(clientsetscheme.Scheme)
|
||||
//
|
||||
// After this, RawExtensions in Kubernetes types will serialize kube-aggregator types
|
||||
// correctly.
|
||||
var AddToScheme = localSchemeBuilder.AddToScheme
|
||||
|
||||
func init() {
|
||||
v1.AddToGroupVersion(Scheme, schema.GroupVersion{Version: "v1"})
|
||||
utilruntime.Must(AddToScheme(Scheme))
|
||||
}
|
||||
90
vendor/k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/typed/apiextensions/v1beta1/apiextensions_client.go
generated
vendored
Normal file
90
vendor/k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/typed/apiextensions/v1beta1/apiextensions_client.go
generated
vendored
Normal file
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
Copyright 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.
|
||||
*/
|
||||
|
||||
// Code generated by client-gen. DO NOT EDIT.
|
||||
|
||||
package v1beta1
|
||||
|
||||
import (
|
||||
v1beta1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1"
|
||||
"k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/scheme"
|
||||
serializer "k8s.io/apimachinery/pkg/runtime/serializer"
|
||||
rest "k8s.io/client-go/rest"
|
||||
)
|
||||
|
||||
type ApiextensionsV1beta1Interface interface {
|
||||
RESTClient() rest.Interface
|
||||
CustomResourceDefinitionsGetter
|
||||
}
|
||||
|
||||
// ApiextensionsV1beta1Client is used to interact with features provided by the apiextensions.k8s.io group.
|
||||
type ApiextensionsV1beta1Client struct {
|
||||
restClient rest.Interface
|
||||
}
|
||||
|
||||
func (c *ApiextensionsV1beta1Client) CustomResourceDefinitions() CustomResourceDefinitionInterface {
|
||||
return newCustomResourceDefinitions(c)
|
||||
}
|
||||
|
||||
// NewForConfig creates a new ApiextensionsV1beta1Client for the given config.
|
||||
func NewForConfig(c *rest.Config) (*ApiextensionsV1beta1Client, error) {
|
||||
config := *c
|
||||
if err := setConfigDefaults(&config); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
client, err := rest.RESTClientFor(&config)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &ApiextensionsV1beta1Client{client}, nil
|
||||
}
|
||||
|
||||
// NewForConfigOrDie creates a new ApiextensionsV1beta1Client for the given config and
|
||||
// panics if there is an error in the config.
|
||||
func NewForConfigOrDie(c *rest.Config) *ApiextensionsV1beta1Client {
|
||||
client, err := NewForConfig(c)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return client
|
||||
}
|
||||
|
||||
// New creates a new ApiextensionsV1beta1Client for the given RESTClient.
|
||||
func New(c rest.Interface) *ApiextensionsV1beta1Client {
|
||||
return &ApiextensionsV1beta1Client{c}
|
||||
}
|
||||
|
||||
func setConfigDefaults(config *rest.Config) error {
|
||||
gv := v1beta1.SchemeGroupVersion
|
||||
config.GroupVersion = &gv
|
||||
config.APIPath = "/apis"
|
||||
config.NegotiatedSerializer = serializer.DirectCodecFactory{CodecFactory: scheme.Codecs}
|
||||
|
||||
if config.UserAgent == "" {
|
||||
config.UserAgent = rest.DefaultKubernetesUserAgent()
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// RESTClient returns a RESTClient that is used to communicate
|
||||
// with API server by this client implementation.
|
||||
func (c *ApiextensionsV1beta1Client) RESTClient() rest.Interface {
|
||||
if c == nil {
|
||||
return nil
|
||||
}
|
||||
return c.restClient
|
||||
}
|
||||
163
vendor/k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/typed/apiextensions/v1beta1/customresourcedefinition.go
generated
vendored
Normal file
163
vendor/k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/typed/apiextensions/v1beta1/customresourcedefinition.go
generated
vendored
Normal file
@@ -0,0 +1,163 @@
|
||||
/*
|
||||
Copyright 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.
|
||||
*/
|
||||
|
||||
// Code generated by client-gen. DO NOT EDIT.
|
||||
|
||||
package v1beta1
|
||||
|
||||
import (
|
||||
v1beta1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1"
|
||||
scheme "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/scheme"
|
||||
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
types "k8s.io/apimachinery/pkg/types"
|
||||
watch "k8s.io/apimachinery/pkg/watch"
|
||||
rest "k8s.io/client-go/rest"
|
||||
)
|
||||
|
||||
// CustomResourceDefinitionsGetter has a method to return a CustomResourceDefinitionInterface.
|
||||
// A group's client should implement this interface.
|
||||
type CustomResourceDefinitionsGetter interface {
|
||||
CustomResourceDefinitions() CustomResourceDefinitionInterface
|
||||
}
|
||||
|
||||
// CustomResourceDefinitionInterface has methods to work with CustomResourceDefinition resources.
|
||||
type CustomResourceDefinitionInterface interface {
|
||||
Create(*v1beta1.CustomResourceDefinition) (*v1beta1.CustomResourceDefinition, error)
|
||||
Update(*v1beta1.CustomResourceDefinition) (*v1beta1.CustomResourceDefinition, error)
|
||||
UpdateStatus(*v1beta1.CustomResourceDefinition) (*v1beta1.CustomResourceDefinition, error)
|
||||
Delete(name string, options *v1.DeleteOptions) error
|
||||
DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error
|
||||
Get(name string, options v1.GetOptions) (*v1beta1.CustomResourceDefinition, error)
|
||||
List(opts v1.ListOptions) (*v1beta1.CustomResourceDefinitionList, error)
|
||||
Watch(opts v1.ListOptions) (watch.Interface, error)
|
||||
Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1beta1.CustomResourceDefinition, err error)
|
||||
CustomResourceDefinitionExpansion
|
||||
}
|
||||
|
||||
// customResourceDefinitions implements CustomResourceDefinitionInterface
|
||||
type customResourceDefinitions struct {
|
||||
client rest.Interface
|
||||
}
|
||||
|
||||
// newCustomResourceDefinitions returns a CustomResourceDefinitions
|
||||
func newCustomResourceDefinitions(c *ApiextensionsV1beta1Client) *customResourceDefinitions {
|
||||
return &customResourceDefinitions{
|
||||
client: c.RESTClient(),
|
||||
}
|
||||
}
|
||||
|
||||
// Get takes name of the customResourceDefinition, and returns the corresponding customResourceDefinition object, and an error if there is any.
|
||||
func (c *customResourceDefinitions) Get(name string, options v1.GetOptions) (result *v1beta1.CustomResourceDefinition, err error) {
|
||||
result = &v1beta1.CustomResourceDefinition{}
|
||||
err = c.client.Get().
|
||||
Resource("customresourcedefinitions").
|
||||
Name(name).
|
||||
VersionedParams(&options, scheme.ParameterCodec).
|
||||
Do().
|
||||
Into(result)
|
||||
return
|
||||
}
|
||||
|
||||
// List takes label and field selectors, and returns the list of CustomResourceDefinitions that match those selectors.
|
||||
func (c *customResourceDefinitions) List(opts v1.ListOptions) (result *v1beta1.CustomResourceDefinitionList, err error) {
|
||||
result = &v1beta1.CustomResourceDefinitionList{}
|
||||
err = c.client.Get().
|
||||
Resource("customresourcedefinitions").
|
||||
VersionedParams(&opts, scheme.ParameterCodec).
|
||||
Do().
|
||||
Into(result)
|
||||
return
|
||||
}
|
||||
|
||||
// Watch returns a watch.Interface that watches the requested customResourceDefinitions.
|
||||
func (c *customResourceDefinitions) Watch(opts v1.ListOptions) (watch.Interface, error) {
|
||||
opts.Watch = true
|
||||
return c.client.Get().
|
||||
Resource("customresourcedefinitions").
|
||||
VersionedParams(&opts, scheme.ParameterCodec).
|
||||
Watch()
|
||||
}
|
||||
|
||||
// Create takes the representation of a customResourceDefinition and creates it. Returns the server's representation of the customResourceDefinition, and an error, if there is any.
|
||||
func (c *customResourceDefinitions) Create(customResourceDefinition *v1beta1.CustomResourceDefinition) (result *v1beta1.CustomResourceDefinition, err error) {
|
||||
result = &v1beta1.CustomResourceDefinition{}
|
||||
err = c.client.Post().
|
||||
Resource("customresourcedefinitions").
|
||||
Body(customResourceDefinition).
|
||||
Do().
|
||||
Into(result)
|
||||
return
|
||||
}
|
||||
|
||||
// Update takes the representation of a customResourceDefinition and updates it. Returns the server's representation of the customResourceDefinition, and an error, if there is any.
|
||||
func (c *customResourceDefinitions) Update(customResourceDefinition *v1beta1.CustomResourceDefinition) (result *v1beta1.CustomResourceDefinition, err error) {
|
||||
result = &v1beta1.CustomResourceDefinition{}
|
||||
err = c.client.Put().
|
||||
Resource("customresourcedefinitions").
|
||||
Name(customResourceDefinition.Name).
|
||||
Body(customResourceDefinition).
|
||||
Do().
|
||||
Into(result)
|
||||
return
|
||||
}
|
||||
|
||||
// UpdateStatus was generated because the type contains a Status member.
|
||||
// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus().
|
||||
|
||||
func (c *customResourceDefinitions) UpdateStatus(customResourceDefinition *v1beta1.CustomResourceDefinition) (result *v1beta1.CustomResourceDefinition, err error) {
|
||||
result = &v1beta1.CustomResourceDefinition{}
|
||||
err = c.client.Put().
|
||||
Resource("customresourcedefinitions").
|
||||
Name(customResourceDefinition.Name).
|
||||
SubResource("status").
|
||||
Body(customResourceDefinition).
|
||||
Do().
|
||||
Into(result)
|
||||
return
|
||||
}
|
||||
|
||||
// Delete takes name of the customResourceDefinition and deletes it. Returns an error if one occurs.
|
||||
func (c *customResourceDefinitions) Delete(name string, options *v1.DeleteOptions) error {
|
||||
return c.client.Delete().
|
||||
Resource("customresourcedefinitions").
|
||||
Name(name).
|
||||
Body(options).
|
||||
Do().
|
||||
Error()
|
||||
}
|
||||
|
||||
// DeleteCollection deletes a collection of objects.
|
||||
func (c *customResourceDefinitions) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error {
|
||||
return c.client.Delete().
|
||||
Resource("customresourcedefinitions").
|
||||
VersionedParams(&listOptions, scheme.ParameterCodec).
|
||||
Body(options).
|
||||
Do().
|
||||
Error()
|
||||
}
|
||||
|
||||
// Patch applies the patch and returns the patched customResourceDefinition.
|
||||
func (c *customResourceDefinitions) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1beta1.CustomResourceDefinition, err error) {
|
||||
result = &v1beta1.CustomResourceDefinition{}
|
||||
err = c.client.Patch(pt).
|
||||
Resource("customresourcedefinitions").
|
||||
SubResource(subresources...).
|
||||
Name(name).
|
||||
Body(data).
|
||||
Do().
|
||||
Into(result)
|
||||
return
|
||||
}
|
||||
20
vendor/k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/typed/apiextensions/v1beta1/doc.go
generated
vendored
Normal file
20
vendor/k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/typed/apiextensions/v1beta1/doc.go
generated
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
Copyright 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.
|
||||
*/
|
||||
|
||||
// Code generated by client-gen. DO NOT EDIT.
|
||||
|
||||
// This package has the automatically generated typed clients.
|
||||
package v1beta1
|
||||
20
vendor/k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/typed/apiextensions/v1beta1/fake/doc.go
generated
vendored
Normal file
20
vendor/k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/typed/apiextensions/v1beta1/fake/doc.go
generated
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
Copyright 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.
|
||||
*/
|
||||
|
||||
// Code generated by client-gen. DO NOT EDIT.
|
||||
|
||||
// Package fake has the automatically generated clients.
|
||||
package fake
|
||||
40
vendor/k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/typed/apiextensions/v1beta1/fake/fake_apiextensions_client.go
generated
vendored
Normal file
40
vendor/k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/typed/apiextensions/v1beta1/fake/fake_apiextensions_client.go
generated
vendored
Normal file
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
Copyright 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.
|
||||
*/
|
||||
|
||||
// Code generated by client-gen. DO NOT EDIT.
|
||||
|
||||
package fake
|
||||
|
||||
import (
|
||||
v1beta1 "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/typed/apiextensions/v1beta1"
|
||||
rest "k8s.io/client-go/rest"
|
||||
testing "k8s.io/client-go/testing"
|
||||
)
|
||||
|
||||
type FakeApiextensionsV1beta1 struct {
|
||||
*testing.Fake
|
||||
}
|
||||
|
||||
func (c *FakeApiextensionsV1beta1) CustomResourceDefinitions() v1beta1.CustomResourceDefinitionInterface {
|
||||
return &FakeCustomResourceDefinitions{c}
|
||||
}
|
||||
|
||||
// RESTClient returns a RESTClient that is used to communicate
|
||||
// with API server by this client implementation.
|
||||
func (c *FakeApiextensionsV1beta1) RESTClient() rest.Interface {
|
||||
var ret *rest.RESTClient
|
||||
return ret
|
||||
}
|
||||
131
vendor/k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/typed/apiextensions/v1beta1/fake/fake_customresourcedefinition.go
generated
vendored
Normal file
131
vendor/k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/typed/apiextensions/v1beta1/fake/fake_customresourcedefinition.go
generated
vendored
Normal file
@@ -0,0 +1,131 @@
|
||||
/*
|
||||
Copyright 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.
|
||||
*/
|
||||
|
||||
// Code generated by client-gen. DO NOT EDIT.
|
||||
|
||||
package fake
|
||||
|
||||
import (
|
||||
v1beta1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1"
|
||||
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
labels "k8s.io/apimachinery/pkg/labels"
|
||||
schema "k8s.io/apimachinery/pkg/runtime/schema"
|
||||
types "k8s.io/apimachinery/pkg/types"
|
||||
watch "k8s.io/apimachinery/pkg/watch"
|
||||
testing "k8s.io/client-go/testing"
|
||||
)
|
||||
|
||||
// FakeCustomResourceDefinitions implements CustomResourceDefinitionInterface
|
||||
type FakeCustomResourceDefinitions struct {
|
||||
Fake *FakeApiextensionsV1beta1
|
||||
}
|
||||
|
||||
var customresourcedefinitionsResource = schema.GroupVersionResource{Group: "apiextensions.k8s.io", Version: "v1beta1", Resource: "customresourcedefinitions"}
|
||||
|
||||
var customresourcedefinitionsKind = schema.GroupVersionKind{Group: "apiextensions.k8s.io", Version: "v1beta1", Kind: "CustomResourceDefinition"}
|
||||
|
||||
// Get takes name of the customResourceDefinition, and returns the corresponding customResourceDefinition object, and an error if there is any.
|
||||
func (c *FakeCustomResourceDefinitions) Get(name string, options v1.GetOptions) (result *v1beta1.CustomResourceDefinition, err error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewRootGetAction(customresourcedefinitionsResource, name), &v1beta1.CustomResourceDefinition{})
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*v1beta1.CustomResourceDefinition), err
|
||||
}
|
||||
|
||||
// List takes label and field selectors, and returns the list of CustomResourceDefinitions that match those selectors.
|
||||
func (c *FakeCustomResourceDefinitions) List(opts v1.ListOptions) (result *v1beta1.CustomResourceDefinitionList, err error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewRootListAction(customresourcedefinitionsResource, customresourcedefinitionsKind, opts), &v1beta1.CustomResourceDefinitionList{})
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
label, _, _ := testing.ExtractFromListOptions(opts)
|
||||
if label == nil {
|
||||
label = labels.Everything()
|
||||
}
|
||||
list := &v1beta1.CustomResourceDefinitionList{ListMeta: obj.(*v1beta1.CustomResourceDefinitionList).ListMeta}
|
||||
for _, item := range obj.(*v1beta1.CustomResourceDefinitionList).Items {
|
||||
if label.Matches(labels.Set(item.Labels)) {
|
||||
list.Items = append(list.Items, item)
|
||||
}
|
||||
}
|
||||
return list, err
|
||||
}
|
||||
|
||||
// Watch returns a watch.Interface that watches the requested customResourceDefinitions.
|
||||
func (c *FakeCustomResourceDefinitions) Watch(opts v1.ListOptions) (watch.Interface, error) {
|
||||
return c.Fake.
|
||||
InvokesWatch(testing.NewRootWatchAction(customresourcedefinitionsResource, opts))
|
||||
}
|
||||
|
||||
// Create takes the representation of a customResourceDefinition and creates it. Returns the server's representation of the customResourceDefinition, and an error, if there is any.
|
||||
func (c *FakeCustomResourceDefinitions) Create(customResourceDefinition *v1beta1.CustomResourceDefinition) (result *v1beta1.CustomResourceDefinition, err error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewRootCreateAction(customresourcedefinitionsResource, customResourceDefinition), &v1beta1.CustomResourceDefinition{})
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*v1beta1.CustomResourceDefinition), err
|
||||
}
|
||||
|
||||
// Update takes the representation of a customResourceDefinition and updates it. Returns the server's representation of the customResourceDefinition, and an error, if there is any.
|
||||
func (c *FakeCustomResourceDefinitions) Update(customResourceDefinition *v1beta1.CustomResourceDefinition) (result *v1beta1.CustomResourceDefinition, err error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewRootUpdateAction(customresourcedefinitionsResource, customResourceDefinition), &v1beta1.CustomResourceDefinition{})
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*v1beta1.CustomResourceDefinition), err
|
||||
}
|
||||
|
||||
// UpdateStatus was generated because the type contains a Status member.
|
||||
// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus().
|
||||
func (c *FakeCustomResourceDefinitions) UpdateStatus(customResourceDefinition *v1beta1.CustomResourceDefinition) (*v1beta1.CustomResourceDefinition, error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewRootUpdateSubresourceAction(customresourcedefinitionsResource, "status", customResourceDefinition), &v1beta1.CustomResourceDefinition{})
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*v1beta1.CustomResourceDefinition), err
|
||||
}
|
||||
|
||||
// Delete takes name of the customResourceDefinition and deletes it. Returns an error if one occurs.
|
||||
func (c *FakeCustomResourceDefinitions) Delete(name string, options *v1.DeleteOptions) error {
|
||||
_, err := c.Fake.
|
||||
Invokes(testing.NewRootDeleteAction(customresourcedefinitionsResource, name), &v1beta1.CustomResourceDefinition{})
|
||||
return err
|
||||
}
|
||||
|
||||
// DeleteCollection deletes a collection of objects.
|
||||
func (c *FakeCustomResourceDefinitions) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error {
|
||||
action := testing.NewRootDeleteCollectionAction(customresourcedefinitionsResource, listOptions)
|
||||
|
||||
_, err := c.Fake.Invokes(action, &v1beta1.CustomResourceDefinitionList{})
|
||||
return err
|
||||
}
|
||||
|
||||
// Patch applies the patch and returns the patched customResourceDefinition.
|
||||
func (c *FakeCustomResourceDefinitions) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1beta1.CustomResourceDefinition, err error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewRootPatchSubresourceAction(customresourcedefinitionsResource, name, data, subresources...), &v1beta1.CustomResourceDefinition{})
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*v1beta1.CustomResourceDefinition), err
|
||||
}
|
||||
21
vendor/k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/typed/apiextensions/v1beta1/generated_expansion.go
generated
vendored
Normal file
21
vendor/k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/typed/apiextensions/v1beta1/generated_expansion.go
generated
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
Copyright 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.
|
||||
*/
|
||||
|
||||
// Code generated by client-gen. DO NOT EDIT.
|
||||
|
||||
package v1beta1
|
||||
|
||||
type CustomResourceDefinitionExpansion interface{}
|
||||
90
vendor/k8s.io/apiextensions-apiserver/pkg/client/clientset/internalclientset/clientset.go
generated
vendored
Normal file
90
vendor/k8s.io/apiextensions-apiserver/pkg/client/clientset/internalclientset/clientset.go
generated
vendored
Normal file
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
Copyright 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.
|
||||
*/
|
||||
|
||||
// Code generated by client-gen. DO NOT EDIT.
|
||||
|
||||
package internalclientset
|
||||
|
||||
import (
|
||||
apiextensionsinternalversion "k8s.io/apiextensions-apiserver/pkg/client/clientset/internalclientset/typed/apiextensions/internalversion"
|
||||
discovery "k8s.io/client-go/discovery"
|
||||
rest "k8s.io/client-go/rest"
|
||||
flowcontrol "k8s.io/client-go/util/flowcontrol"
|
||||
)
|
||||
|
||||
type Interface interface {
|
||||
Discovery() discovery.DiscoveryInterface
|
||||
Apiextensions() apiextensionsinternalversion.ApiextensionsInterface
|
||||
}
|
||||
|
||||
// Clientset contains the clients for groups. Each group has exactly one
|
||||
// version included in a Clientset.
|
||||
type Clientset struct {
|
||||
*discovery.DiscoveryClient
|
||||
apiextensions *apiextensionsinternalversion.ApiextensionsClient
|
||||
}
|
||||
|
||||
// Apiextensions retrieves the ApiextensionsClient
|
||||
func (c *Clientset) Apiextensions() apiextensionsinternalversion.ApiextensionsInterface {
|
||||
return c.apiextensions
|
||||
}
|
||||
|
||||
// Discovery retrieves the DiscoveryClient
|
||||
func (c *Clientset) Discovery() discovery.DiscoveryInterface {
|
||||
if c == nil {
|
||||
return nil
|
||||
}
|
||||
return c.DiscoveryClient
|
||||
}
|
||||
|
||||
// NewForConfig creates a new Clientset for the given config.
|
||||
func NewForConfig(c *rest.Config) (*Clientset, error) {
|
||||
configShallowCopy := *c
|
||||
if configShallowCopy.RateLimiter == nil && configShallowCopy.QPS > 0 {
|
||||
configShallowCopy.RateLimiter = flowcontrol.NewTokenBucketRateLimiter(configShallowCopy.QPS, configShallowCopy.Burst)
|
||||
}
|
||||
var cs Clientset
|
||||
var err error
|
||||
cs.apiextensions, err = apiextensionsinternalversion.NewForConfig(&configShallowCopy)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
cs.DiscoveryClient, err = discovery.NewDiscoveryClientForConfig(&configShallowCopy)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &cs, nil
|
||||
}
|
||||
|
||||
// NewForConfigOrDie creates a new Clientset for the given config and
|
||||
// panics if there is an error in the config.
|
||||
func NewForConfigOrDie(c *rest.Config) *Clientset {
|
||||
var cs Clientset
|
||||
cs.apiextensions = apiextensionsinternalversion.NewForConfigOrDie(c)
|
||||
|
||||
cs.DiscoveryClient = discovery.NewDiscoveryClientForConfigOrDie(c)
|
||||
return &cs
|
||||
}
|
||||
|
||||
// New creates a new Clientset for the given RESTClient.
|
||||
func New(c rest.Interface) *Clientset {
|
||||
var cs Clientset
|
||||
cs.apiextensions = apiextensionsinternalversion.New(c)
|
||||
|
||||
cs.DiscoveryClient = discovery.NewDiscoveryClient(c)
|
||||
return &cs
|
||||
}
|
||||
20
vendor/k8s.io/apiextensions-apiserver/pkg/client/clientset/internalclientset/doc.go
generated
vendored
Normal file
20
vendor/k8s.io/apiextensions-apiserver/pkg/client/clientset/internalclientset/doc.go
generated
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
Copyright 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.
|
||||
*/
|
||||
|
||||
// Code generated by client-gen. DO NOT EDIT.
|
||||
|
||||
// This package has the automatically generated clientset.
|
||||
package internalclientset
|
||||
77
vendor/k8s.io/apiextensions-apiserver/pkg/client/clientset/internalclientset/fake/clientset_generated.go
generated
vendored
Normal file
77
vendor/k8s.io/apiextensions-apiserver/pkg/client/clientset/internalclientset/fake/clientset_generated.go
generated
vendored
Normal file
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
Copyright 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.
|
||||
*/
|
||||
|
||||
// Code generated by client-gen. DO NOT EDIT.
|
||||
|
||||
package fake
|
||||
|
||||
import (
|
||||
clientset "k8s.io/apiextensions-apiserver/pkg/client/clientset/internalclientset"
|
||||
apiextensionsinternalversion "k8s.io/apiextensions-apiserver/pkg/client/clientset/internalclientset/typed/apiextensions/internalversion"
|
||||
fakeapiextensionsinternalversion "k8s.io/apiextensions-apiserver/pkg/client/clientset/internalclientset/typed/apiextensions/internalversion/fake"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/watch"
|
||||
"k8s.io/client-go/discovery"
|
||||
fakediscovery "k8s.io/client-go/discovery/fake"
|
||||
"k8s.io/client-go/testing"
|
||||
)
|
||||
|
||||
// NewSimpleClientset returns a clientset that will respond with the provided objects.
|
||||
// It's backed by a very simple object tracker that processes creates, updates and deletions as-is,
|
||||
// without applying any validations and/or defaults. It shouldn't be considered a replacement
|
||||
// for a real clientset and is mostly useful in simple unit tests.
|
||||
func NewSimpleClientset(objects ...runtime.Object) *Clientset {
|
||||
o := testing.NewObjectTracker(scheme, codecs.UniversalDecoder())
|
||||
for _, obj := range objects {
|
||||
if err := o.Add(obj); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
cs := &Clientset{}
|
||||
cs.discovery = &fakediscovery.FakeDiscovery{Fake: &cs.Fake}
|
||||
cs.AddReactor("*", "*", testing.ObjectReaction(o))
|
||||
cs.AddWatchReactor("*", func(action testing.Action) (handled bool, ret watch.Interface, err error) {
|
||||
gvr := action.GetResource()
|
||||
ns := action.GetNamespace()
|
||||
watch, err := o.Watch(gvr, ns)
|
||||
if err != nil {
|
||||
return false, nil, err
|
||||
}
|
||||
return true, watch, nil
|
||||
})
|
||||
|
||||
return cs
|
||||
}
|
||||
|
||||
// Clientset implements clientset.Interface. Meant to be embedded into a
|
||||
// struct to get a default implementation. This makes faking out just the method
|
||||
// you want to test easier.
|
||||
type Clientset struct {
|
||||
testing.Fake
|
||||
discovery *fakediscovery.FakeDiscovery
|
||||
}
|
||||
|
||||
func (c *Clientset) Discovery() discovery.DiscoveryInterface {
|
||||
return c.discovery
|
||||
}
|
||||
|
||||
var _ clientset.Interface = &Clientset{}
|
||||
|
||||
// Apiextensions retrieves the ApiextensionsClient
|
||||
func (c *Clientset) Apiextensions() apiextensionsinternalversion.ApiextensionsInterface {
|
||||
return &fakeapiextensionsinternalversion.FakeApiextensions{Fake: &c.Fake}
|
||||
}
|
||||
20
vendor/k8s.io/apiextensions-apiserver/pkg/client/clientset/internalclientset/fake/doc.go
generated
vendored
Normal file
20
vendor/k8s.io/apiextensions-apiserver/pkg/client/clientset/internalclientset/fake/doc.go
generated
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
Copyright 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.
|
||||
*/
|
||||
|
||||
// Code generated by client-gen. DO NOT EDIT.
|
||||
|
||||
// This package has the automatically generated fake clientset.
|
||||
package fake
|
||||
56
vendor/k8s.io/apiextensions-apiserver/pkg/client/clientset/internalclientset/fake/register.go
generated
vendored
Normal file
56
vendor/k8s.io/apiextensions-apiserver/pkg/client/clientset/internalclientset/fake/register.go
generated
vendored
Normal file
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
Copyright 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.
|
||||
*/
|
||||
|
||||
// Code generated by client-gen. DO NOT EDIT.
|
||||
|
||||
package fake
|
||||
|
||||
import (
|
||||
apiextensionsinternalversion "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions"
|
||||
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
runtime "k8s.io/apimachinery/pkg/runtime"
|
||||
schema "k8s.io/apimachinery/pkg/runtime/schema"
|
||||
serializer "k8s.io/apimachinery/pkg/runtime/serializer"
|
||||
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
|
||||
)
|
||||
|
||||
var scheme = runtime.NewScheme()
|
||||
var codecs = serializer.NewCodecFactory(scheme)
|
||||
var parameterCodec = runtime.NewParameterCodec(scheme)
|
||||
var localSchemeBuilder = runtime.SchemeBuilder{
|
||||
apiextensionsinternalversion.AddToScheme,
|
||||
}
|
||||
|
||||
// AddToScheme adds all types of this clientset into the given scheme. This allows composition
|
||||
// of clientsets, like in:
|
||||
//
|
||||
// import (
|
||||
// "k8s.io/client-go/kubernetes"
|
||||
// clientsetscheme "k8s.io/client-go/kubernetes/scheme"
|
||||
// aggregatorclientsetscheme "k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/scheme"
|
||||
// )
|
||||
//
|
||||
// kclientset, _ := kubernetes.NewForConfig(c)
|
||||
// _ = aggregatorclientsetscheme.AddToScheme(clientsetscheme.Scheme)
|
||||
//
|
||||
// After this, RawExtensions in Kubernetes types will serialize kube-aggregator types
|
||||
// correctly.
|
||||
var AddToScheme = localSchemeBuilder.AddToScheme
|
||||
|
||||
func init() {
|
||||
v1.AddToGroupVersion(scheme, schema.GroupVersion{Version: "v1"})
|
||||
utilruntime.Must(AddToScheme(scheme))
|
||||
}
|
||||
20
vendor/k8s.io/apiextensions-apiserver/pkg/client/clientset/internalclientset/scheme/doc.go
generated
vendored
Normal file
20
vendor/k8s.io/apiextensions-apiserver/pkg/client/clientset/internalclientset/scheme/doc.go
generated
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
Copyright 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.
|
||||
*/
|
||||
|
||||
// Code generated by client-gen. DO NOT EDIT.
|
||||
|
||||
// This package contains the scheme of the automatically generated clientset.
|
||||
package scheme
|
||||
41
vendor/k8s.io/apiextensions-apiserver/pkg/client/clientset/internalclientset/scheme/register.go
generated
vendored
Normal file
41
vendor/k8s.io/apiextensions-apiserver/pkg/client/clientset/internalclientset/scheme/register.go
generated
vendored
Normal file
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
Copyright 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.
|
||||
*/
|
||||
|
||||
// Code generated by client-gen. DO NOT EDIT.
|
||||
|
||||
package scheme
|
||||
|
||||
import (
|
||||
apiextensions "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/install"
|
||||
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
runtime "k8s.io/apimachinery/pkg/runtime"
|
||||
schema "k8s.io/apimachinery/pkg/runtime/schema"
|
||||
serializer "k8s.io/apimachinery/pkg/runtime/serializer"
|
||||
)
|
||||
|
||||
var Scheme = runtime.NewScheme()
|
||||
var Codecs = serializer.NewCodecFactory(Scheme)
|
||||
var ParameterCodec = runtime.NewParameterCodec(Scheme)
|
||||
|
||||
func init() {
|
||||
v1.AddToGroupVersion(Scheme, schema.GroupVersion{Version: "v1"})
|
||||
Install(Scheme)
|
||||
}
|
||||
|
||||
// Install registers the API group and adds types to a scheme
|
||||
func Install(scheme *runtime.Scheme) {
|
||||
apiextensions.Install(scheme)
|
||||
}
|
||||
96
vendor/k8s.io/apiextensions-apiserver/pkg/client/clientset/internalclientset/typed/apiextensions/internalversion/apiextensions_client.go
generated
vendored
Normal file
96
vendor/k8s.io/apiextensions-apiserver/pkg/client/clientset/internalclientset/typed/apiextensions/internalversion/apiextensions_client.go
generated
vendored
Normal file
@@ -0,0 +1,96 @@
|
||||
/*
|
||||
Copyright 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.
|
||||
*/
|
||||
|
||||
// Code generated by client-gen. DO NOT EDIT.
|
||||
|
||||
package internalversion
|
||||
|
||||
import (
|
||||
"k8s.io/apiextensions-apiserver/pkg/client/clientset/internalclientset/scheme"
|
||||
rest "k8s.io/client-go/rest"
|
||||
)
|
||||
|
||||
type ApiextensionsInterface interface {
|
||||
RESTClient() rest.Interface
|
||||
CustomResourceDefinitionsGetter
|
||||
}
|
||||
|
||||
// ApiextensionsClient is used to interact with features provided by the apiextensions.k8s.io group.
|
||||
type ApiextensionsClient struct {
|
||||
restClient rest.Interface
|
||||
}
|
||||
|
||||
func (c *ApiextensionsClient) CustomResourceDefinitions() CustomResourceDefinitionInterface {
|
||||
return newCustomResourceDefinitions(c)
|
||||
}
|
||||
|
||||
// NewForConfig creates a new ApiextensionsClient for the given config.
|
||||
func NewForConfig(c *rest.Config) (*ApiextensionsClient, error) {
|
||||
config := *c
|
||||
if err := setConfigDefaults(&config); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
client, err := rest.RESTClientFor(&config)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &ApiextensionsClient{client}, nil
|
||||
}
|
||||
|
||||
// NewForConfigOrDie creates a new ApiextensionsClient for the given config and
|
||||
// panics if there is an error in the config.
|
||||
func NewForConfigOrDie(c *rest.Config) *ApiextensionsClient {
|
||||
client, err := NewForConfig(c)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return client
|
||||
}
|
||||
|
||||
// New creates a new ApiextensionsClient for the given RESTClient.
|
||||
func New(c rest.Interface) *ApiextensionsClient {
|
||||
return &ApiextensionsClient{c}
|
||||
}
|
||||
|
||||
func setConfigDefaults(config *rest.Config) error {
|
||||
config.APIPath = "/apis"
|
||||
if config.UserAgent == "" {
|
||||
config.UserAgent = rest.DefaultKubernetesUserAgent()
|
||||
}
|
||||
if config.GroupVersion == nil || config.GroupVersion.Group != scheme.Scheme.PrioritizedVersionsForGroup("apiextensions.k8s.io")[0].Group {
|
||||
gv := scheme.Scheme.PrioritizedVersionsForGroup("apiextensions.k8s.io")[0]
|
||||
config.GroupVersion = &gv
|
||||
}
|
||||
config.NegotiatedSerializer = scheme.Codecs
|
||||
|
||||
if config.QPS == 0 {
|
||||
config.QPS = 5
|
||||
}
|
||||
if config.Burst == 0 {
|
||||
config.Burst = 10
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// RESTClient returns a RESTClient that is used to communicate
|
||||
// with API server by this client implementation.
|
||||
func (c *ApiextensionsClient) RESTClient() rest.Interface {
|
||||
if c == nil {
|
||||
return nil
|
||||
}
|
||||
return c.restClient
|
||||
}
|
||||
163
vendor/k8s.io/apiextensions-apiserver/pkg/client/clientset/internalclientset/typed/apiextensions/internalversion/customresourcedefinition.go
generated
vendored
Normal file
163
vendor/k8s.io/apiextensions-apiserver/pkg/client/clientset/internalclientset/typed/apiextensions/internalversion/customresourcedefinition.go
generated
vendored
Normal file
@@ -0,0 +1,163 @@
|
||||
/*
|
||||
Copyright 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.
|
||||
*/
|
||||
|
||||
// Code generated by client-gen. DO NOT EDIT.
|
||||
|
||||
package internalversion
|
||||
|
||||
import (
|
||||
apiextensions "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions"
|
||||
scheme "k8s.io/apiextensions-apiserver/pkg/client/clientset/internalclientset/scheme"
|
||||
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
types "k8s.io/apimachinery/pkg/types"
|
||||
watch "k8s.io/apimachinery/pkg/watch"
|
||||
rest "k8s.io/client-go/rest"
|
||||
)
|
||||
|
||||
// CustomResourceDefinitionsGetter has a method to return a CustomResourceDefinitionInterface.
|
||||
// A group's client should implement this interface.
|
||||
type CustomResourceDefinitionsGetter interface {
|
||||
CustomResourceDefinitions() CustomResourceDefinitionInterface
|
||||
}
|
||||
|
||||
// CustomResourceDefinitionInterface has methods to work with CustomResourceDefinition resources.
|
||||
type CustomResourceDefinitionInterface interface {
|
||||
Create(*apiextensions.CustomResourceDefinition) (*apiextensions.CustomResourceDefinition, error)
|
||||
Update(*apiextensions.CustomResourceDefinition) (*apiextensions.CustomResourceDefinition, error)
|
||||
UpdateStatus(*apiextensions.CustomResourceDefinition) (*apiextensions.CustomResourceDefinition, error)
|
||||
Delete(name string, options *v1.DeleteOptions) error
|
||||
DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error
|
||||
Get(name string, options v1.GetOptions) (*apiextensions.CustomResourceDefinition, error)
|
||||
List(opts v1.ListOptions) (*apiextensions.CustomResourceDefinitionList, error)
|
||||
Watch(opts v1.ListOptions) (watch.Interface, error)
|
||||
Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *apiextensions.CustomResourceDefinition, err error)
|
||||
CustomResourceDefinitionExpansion
|
||||
}
|
||||
|
||||
// customResourceDefinitions implements CustomResourceDefinitionInterface
|
||||
type customResourceDefinitions struct {
|
||||
client rest.Interface
|
||||
}
|
||||
|
||||
// newCustomResourceDefinitions returns a CustomResourceDefinitions
|
||||
func newCustomResourceDefinitions(c *ApiextensionsClient) *customResourceDefinitions {
|
||||
return &customResourceDefinitions{
|
||||
client: c.RESTClient(),
|
||||
}
|
||||
}
|
||||
|
||||
// Get takes name of the customResourceDefinition, and returns the corresponding customResourceDefinition object, and an error if there is any.
|
||||
func (c *customResourceDefinitions) Get(name string, options v1.GetOptions) (result *apiextensions.CustomResourceDefinition, err error) {
|
||||
result = &apiextensions.CustomResourceDefinition{}
|
||||
err = c.client.Get().
|
||||
Resource("customresourcedefinitions").
|
||||
Name(name).
|
||||
VersionedParams(&options, scheme.ParameterCodec).
|
||||
Do().
|
||||
Into(result)
|
||||
return
|
||||
}
|
||||
|
||||
// List takes label and field selectors, and returns the list of CustomResourceDefinitions that match those selectors.
|
||||
func (c *customResourceDefinitions) List(opts v1.ListOptions) (result *apiextensions.CustomResourceDefinitionList, err error) {
|
||||
result = &apiextensions.CustomResourceDefinitionList{}
|
||||
err = c.client.Get().
|
||||
Resource("customresourcedefinitions").
|
||||
VersionedParams(&opts, scheme.ParameterCodec).
|
||||
Do().
|
||||
Into(result)
|
||||
return
|
||||
}
|
||||
|
||||
// Watch returns a watch.Interface that watches the requested customResourceDefinitions.
|
||||
func (c *customResourceDefinitions) Watch(opts v1.ListOptions) (watch.Interface, error) {
|
||||
opts.Watch = true
|
||||
return c.client.Get().
|
||||
Resource("customresourcedefinitions").
|
||||
VersionedParams(&opts, scheme.ParameterCodec).
|
||||
Watch()
|
||||
}
|
||||
|
||||
// Create takes the representation of a customResourceDefinition and creates it. Returns the server's representation of the customResourceDefinition, and an error, if there is any.
|
||||
func (c *customResourceDefinitions) Create(customResourceDefinition *apiextensions.CustomResourceDefinition) (result *apiextensions.CustomResourceDefinition, err error) {
|
||||
result = &apiextensions.CustomResourceDefinition{}
|
||||
err = c.client.Post().
|
||||
Resource("customresourcedefinitions").
|
||||
Body(customResourceDefinition).
|
||||
Do().
|
||||
Into(result)
|
||||
return
|
||||
}
|
||||
|
||||
// Update takes the representation of a customResourceDefinition and updates it. Returns the server's representation of the customResourceDefinition, and an error, if there is any.
|
||||
func (c *customResourceDefinitions) Update(customResourceDefinition *apiextensions.CustomResourceDefinition) (result *apiextensions.CustomResourceDefinition, err error) {
|
||||
result = &apiextensions.CustomResourceDefinition{}
|
||||
err = c.client.Put().
|
||||
Resource("customresourcedefinitions").
|
||||
Name(customResourceDefinition.Name).
|
||||
Body(customResourceDefinition).
|
||||
Do().
|
||||
Into(result)
|
||||
return
|
||||
}
|
||||
|
||||
// UpdateStatus was generated because the type contains a Status member.
|
||||
// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus().
|
||||
|
||||
func (c *customResourceDefinitions) UpdateStatus(customResourceDefinition *apiextensions.CustomResourceDefinition) (result *apiextensions.CustomResourceDefinition, err error) {
|
||||
result = &apiextensions.CustomResourceDefinition{}
|
||||
err = c.client.Put().
|
||||
Resource("customresourcedefinitions").
|
||||
Name(customResourceDefinition.Name).
|
||||
SubResource("status").
|
||||
Body(customResourceDefinition).
|
||||
Do().
|
||||
Into(result)
|
||||
return
|
||||
}
|
||||
|
||||
// Delete takes name of the customResourceDefinition and deletes it. Returns an error if one occurs.
|
||||
func (c *customResourceDefinitions) Delete(name string, options *v1.DeleteOptions) error {
|
||||
return c.client.Delete().
|
||||
Resource("customresourcedefinitions").
|
||||
Name(name).
|
||||
Body(options).
|
||||
Do().
|
||||
Error()
|
||||
}
|
||||
|
||||
// DeleteCollection deletes a collection of objects.
|
||||
func (c *customResourceDefinitions) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error {
|
||||
return c.client.Delete().
|
||||
Resource("customresourcedefinitions").
|
||||
VersionedParams(&listOptions, scheme.ParameterCodec).
|
||||
Body(options).
|
||||
Do().
|
||||
Error()
|
||||
}
|
||||
|
||||
// Patch applies the patch and returns the patched customResourceDefinition.
|
||||
func (c *customResourceDefinitions) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *apiextensions.CustomResourceDefinition, err error) {
|
||||
result = &apiextensions.CustomResourceDefinition{}
|
||||
err = c.client.Patch(pt).
|
||||
Resource("customresourcedefinitions").
|
||||
SubResource(subresources...).
|
||||
Name(name).
|
||||
Body(data).
|
||||
Do().
|
||||
Into(result)
|
||||
return
|
||||
}
|
||||
20
vendor/k8s.io/apiextensions-apiserver/pkg/client/clientset/internalclientset/typed/apiextensions/internalversion/doc.go
generated
vendored
Normal file
20
vendor/k8s.io/apiextensions-apiserver/pkg/client/clientset/internalclientset/typed/apiextensions/internalversion/doc.go
generated
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
Copyright 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.
|
||||
*/
|
||||
|
||||
// Code generated by client-gen. DO NOT EDIT.
|
||||
|
||||
// This package has the automatically generated typed clients.
|
||||
package internalversion
|
||||
20
vendor/k8s.io/apiextensions-apiserver/pkg/client/clientset/internalclientset/typed/apiextensions/internalversion/fake/doc.go
generated
vendored
Normal file
20
vendor/k8s.io/apiextensions-apiserver/pkg/client/clientset/internalclientset/typed/apiextensions/internalversion/fake/doc.go
generated
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
Copyright 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.
|
||||
*/
|
||||
|
||||
// Code generated by client-gen. DO NOT EDIT.
|
||||
|
||||
// Package fake has the automatically generated clients.
|
||||
package fake
|
||||
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
Copyright 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.
|
||||
*/
|
||||
|
||||
// Code generated by client-gen. DO NOT EDIT.
|
||||
|
||||
package fake
|
||||
|
||||
import (
|
||||
internalversion "k8s.io/apiextensions-apiserver/pkg/client/clientset/internalclientset/typed/apiextensions/internalversion"
|
||||
rest "k8s.io/client-go/rest"
|
||||
testing "k8s.io/client-go/testing"
|
||||
)
|
||||
|
||||
type FakeApiextensions struct {
|
||||
*testing.Fake
|
||||
}
|
||||
|
||||
func (c *FakeApiextensions) CustomResourceDefinitions() internalversion.CustomResourceDefinitionInterface {
|
||||
return &FakeCustomResourceDefinitions{c}
|
||||
}
|
||||
|
||||
// RESTClient returns a RESTClient that is used to communicate
|
||||
// with API server by this client implementation.
|
||||
func (c *FakeApiextensions) RESTClient() rest.Interface {
|
||||
var ret *rest.RESTClient
|
||||
return ret
|
||||
}
|
||||
@@ -0,0 +1,131 @@
|
||||
/*
|
||||
Copyright 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.
|
||||
*/
|
||||
|
||||
// Code generated by client-gen. DO NOT EDIT.
|
||||
|
||||
package fake
|
||||
|
||||
import (
|
||||
apiextensions "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions"
|
||||
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
labels "k8s.io/apimachinery/pkg/labels"
|
||||
schema "k8s.io/apimachinery/pkg/runtime/schema"
|
||||
types "k8s.io/apimachinery/pkg/types"
|
||||
watch "k8s.io/apimachinery/pkg/watch"
|
||||
testing "k8s.io/client-go/testing"
|
||||
)
|
||||
|
||||
// FakeCustomResourceDefinitions implements CustomResourceDefinitionInterface
|
||||
type FakeCustomResourceDefinitions struct {
|
||||
Fake *FakeApiextensions
|
||||
}
|
||||
|
||||
var customresourcedefinitionsResource = schema.GroupVersionResource{Group: "apiextensions.k8s.io", Version: "", Resource: "customresourcedefinitions"}
|
||||
|
||||
var customresourcedefinitionsKind = schema.GroupVersionKind{Group: "apiextensions.k8s.io", Version: "", Kind: "CustomResourceDefinition"}
|
||||
|
||||
// Get takes name of the customResourceDefinition, and returns the corresponding customResourceDefinition object, and an error if there is any.
|
||||
func (c *FakeCustomResourceDefinitions) Get(name string, options v1.GetOptions) (result *apiextensions.CustomResourceDefinition, err error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewRootGetAction(customresourcedefinitionsResource, name), &apiextensions.CustomResourceDefinition{})
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*apiextensions.CustomResourceDefinition), err
|
||||
}
|
||||
|
||||
// List takes label and field selectors, and returns the list of CustomResourceDefinitions that match those selectors.
|
||||
func (c *FakeCustomResourceDefinitions) List(opts v1.ListOptions) (result *apiextensions.CustomResourceDefinitionList, err error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewRootListAction(customresourcedefinitionsResource, customresourcedefinitionsKind, opts), &apiextensions.CustomResourceDefinitionList{})
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
label, _, _ := testing.ExtractFromListOptions(opts)
|
||||
if label == nil {
|
||||
label = labels.Everything()
|
||||
}
|
||||
list := &apiextensions.CustomResourceDefinitionList{ListMeta: obj.(*apiextensions.CustomResourceDefinitionList).ListMeta}
|
||||
for _, item := range obj.(*apiextensions.CustomResourceDefinitionList).Items {
|
||||
if label.Matches(labels.Set(item.Labels)) {
|
||||
list.Items = append(list.Items, item)
|
||||
}
|
||||
}
|
||||
return list, err
|
||||
}
|
||||
|
||||
// Watch returns a watch.Interface that watches the requested customResourceDefinitions.
|
||||
func (c *FakeCustomResourceDefinitions) Watch(opts v1.ListOptions) (watch.Interface, error) {
|
||||
return c.Fake.
|
||||
InvokesWatch(testing.NewRootWatchAction(customresourcedefinitionsResource, opts))
|
||||
}
|
||||
|
||||
// Create takes the representation of a customResourceDefinition and creates it. Returns the server's representation of the customResourceDefinition, and an error, if there is any.
|
||||
func (c *FakeCustomResourceDefinitions) Create(customResourceDefinition *apiextensions.CustomResourceDefinition) (result *apiextensions.CustomResourceDefinition, err error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewRootCreateAction(customresourcedefinitionsResource, customResourceDefinition), &apiextensions.CustomResourceDefinition{})
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*apiextensions.CustomResourceDefinition), err
|
||||
}
|
||||
|
||||
// Update takes the representation of a customResourceDefinition and updates it. Returns the server's representation of the customResourceDefinition, and an error, if there is any.
|
||||
func (c *FakeCustomResourceDefinitions) Update(customResourceDefinition *apiextensions.CustomResourceDefinition) (result *apiextensions.CustomResourceDefinition, err error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewRootUpdateAction(customresourcedefinitionsResource, customResourceDefinition), &apiextensions.CustomResourceDefinition{})
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*apiextensions.CustomResourceDefinition), err
|
||||
}
|
||||
|
||||
// UpdateStatus was generated because the type contains a Status member.
|
||||
// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus().
|
||||
func (c *FakeCustomResourceDefinitions) UpdateStatus(customResourceDefinition *apiextensions.CustomResourceDefinition) (*apiextensions.CustomResourceDefinition, error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewRootUpdateSubresourceAction(customresourcedefinitionsResource, "status", customResourceDefinition), &apiextensions.CustomResourceDefinition{})
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*apiextensions.CustomResourceDefinition), err
|
||||
}
|
||||
|
||||
// Delete takes name of the customResourceDefinition and deletes it. Returns an error if one occurs.
|
||||
func (c *FakeCustomResourceDefinitions) Delete(name string, options *v1.DeleteOptions) error {
|
||||
_, err := c.Fake.
|
||||
Invokes(testing.NewRootDeleteAction(customresourcedefinitionsResource, name), &apiextensions.CustomResourceDefinition{})
|
||||
return err
|
||||
}
|
||||
|
||||
// DeleteCollection deletes a collection of objects.
|
||||
func (c *FakeCustomResourceDefinitions) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error {
|
||||
action := testing.NewRootDeleteCollectionAction(customresourcedefinitionsResource, listOptions)
|
||||
|
||||
_, err := c.Fake.Invokes(action, &apiextensions.CustomResourceDefinitionList{})
|
||||
return err
|
||||
}
|
||||
|
||||
// Patch applies the patch and returns the patched customResourceDefinition.
|
||||
func (c *FakeCustomResourceDefinitions) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *apiextensions.CustomResourceDefinition, err error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewRootPatchSubresourceAction(customresourcedefinitionsResource, name, data, subresources...), &apiextensions.CustomResourceDefinition{})
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*apiextensions.CustomResourceDefinition), err
|
||||
}
|
||||
21
vendor/k8s.io/apiextensions-apiserver/pkg/client/clientset/internalclientset/typed/apiextensions/internalversion/generated_expansion.go
generated
vendored
Normal file
21
vendor/k8s.io/apiextensions-apiserver/pkg/client/clientset/internalclientset/typed/apiextensions/internalversion/generated_expansion.go
generated
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
Copyright 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.
|
||||
*/
|
||||
|
||||
// Code generated by client-gen. DO NOT EDIT.
|
||||
|
||||
package internalversion
|
||||
|
||||
type CustomResourceDefinitionExpansion interface{}
|
||||
46
vendor/k8s.io/apiextensions-apiserver/pkg/client/informers/externalversions/apiextensions/interface.go
generated
vendored
Normal file
46
vendor/k8s.io/apiextensions-apiserver/pkg/client/informers/externalversions/apiextensions/interface.go
generated
vendored
Normal file
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
Copyright 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.
|
||||
*/
|
||||
|
||||
// Code generated by informer-gen. DO NOT EDIT.
|
||||
|
||||
package apiextensions
|
||||
|
||||
import (
|
||||
v1beta1 "k8s.io/apiextensions-apiserver/pkg/client/informers/externalversions/apiextensions/v1beta1"
|
||||
internalinterfaces "k8s.io/apiextensions-apiserver/pkg/client/informers/externalversions/internalinterfaces"
|
||||
)
|
||||
|
||||
// Interface provides access to each of this group's versions.
|
||||
type Interface interface {
|
||||
// V1beta1 provides access to shared informers for resources in V1beta1.
|
||||
V1beta1() v1beta1.Interface
|
||||
}
|
||||
|
||||
type group struct {
|
||||
factory internalinterfaces.SharedInformerFactory
|
||||
namespace string
|
||||
tweakListOptions internalinterfaces.TweakListOptionsFunc
|
||||
}
|
||||
|
||||
// New returns a new Interface.
|
||||
func New(f internalinterfaces.SharedInformerFactory, namespace string, tweakListOptions internalinterfaces.TweakListOptionsFunc) Interface {
|
||||
return &group{factory: f, namespace: namespace, tweakListOptions: tweakListOptions}
|
||||
}
|
||||
|
||||
// V1beta1 returns a new v1beta1.Interface.
|
||||
func (g *group) V1beta1() v1beta1.Interface {
|
||||
return v1beta1.New(g.factory, g.namespace, g.tweakListOptions)
|
||||
}
|
||||
88
vendor/k8s.io/apiextensions-apiserver/pkg/client/informers/externalversions/apiextensions/v1beta1/customresourcedefinition.go
generated
vendored
Normal file
88
vendor/k8s.io/apiextensions-apiserver/pkg/client/informers/externalversions/apiextensions/v1beta1/customresourcedefinition.go
generated
vendored
Normal file
@@ -0,0 +1,88 @@
|
||||
/*
|
||||
Copyright 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.
|
||||
*/
|
||||
|
||||
// Code generated by informer-gen. DO NOT EDIT.
|
||||
|
||||
package v1beta1
|
||||
|
||||
import (
|
||||
time "time"
|
||||
|
||||
apiextensionsv1beta1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1"
|
||||
clientset "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset"
|
||||
internalinterfaces "k8s.io/apiextensions-apiserver/pkg/client/informers/externalversions/internalinterfaces"
|
||||
v1beta1 "k8s.io/apiextensions-apiserver/pkg/client/listers/apiextensions/v1beta1"
|
||||
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
runtime "k8s.io/apimachinery/pkg/runtime"
|
||||
watch "k8s.io/apimachinery/pkg/watch"
|
||||
cache "k8s.io/client-go/tools/cache"
|
||||
)
|
||||
|
||||
// CustomResourceDefinitionInformer provides access to a shared informer and lister for
|
||||
// CustomResourceDefinitions.
|
||||
type CustomResourceDefinitionInformer interface {
|
||||
Informer() cache.SharedIndexInformer
|
||||
Lister() v1beta1.CustomResourceDefinitionLister
|
||||
}
|
||||
|
||||
type customResourceDefinitionInformer struct {
|
||||
factory internalinterfaces.SharedInformerFactory
|
||||
tweakListOptions internalinterfaces.TweakListOptionsFunc
|
||||
}
|
||||
|
||||
// NewCustomResourceDefinitionInformer constructs a new informer for CustomResourceDefinition type.
|
||||
// Always prefer using an informer factory to get a shared informer instead of getting an independent
|
||||
// one. This reduces memory footprint and number of connections to the server.
|
||||
func NewCustomResourceDefinitionInformer(client clientset.Interface, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer {
|
||||
return NewFilteredCustomResourceDefinitionInformer(client, resyncPeriod, indexers, nil)
|
||||
}
|
||||
|
||||
// NewFilteredCustomResourceDefinitionInformer constructs a new informer for CustomResourceDefinition type.
|
||||
// Always prefer using an informer factory to get a shared informer instead of getting an independent
|
||||
// one. This reduces memory footprint and number of connections to the server.
|
||||
func NewFilteredCustomResourceDefinitionInformer(client clientset.Interface, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer {
|
||||
return cache.NewSharedIndexInformer(
|
||||
&cache.ListWatch{
|
||||
ListFunc: func(options v1.ListOptions) (runtime.Object, error) {
|
||||
if tweakListOptions != nil {
|
||||
tweakListOptions(&options)
|
||||
}
|
||||
return client.ApiextensionsV1beta1().CustomResourceDefinitions().List(options)
|
||||
},
|
||||
WatchFunc: func(options v1.ListOptions) (watch.Interface, error) {
|
||||
if tweakListOptions != nil {
|
||||
tweakListOptions(&options)
|
||||
}
|
||||
return client.ApiextensionsV1beta1().CustomResourceDefinitions().Watch(options)
|
||||
},
|
||||
},
|
||||
&apiextensionsv1beta1.CustomResourceDefinition{},
|
||||
resyncPeriod,
|
||||
indexers,
|
||||
)
|
||||
}
|
||||
|
||||
func (f *customResourceDefinitionInformer) defaultInformer(client clientset.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer {
|
||||
return NewFilteredCustomResourceDefinitionInformer(client, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions)
|
||||
}
|
||||
|
||||
func (f *customResourceDefinitionInformer) Informer() cache.SharedIndexInformer {
|
||||
return f.factory.InformerFor(&apiextensionsv1beta1.CustomResourceDefinition{}, f.defaultInformer)
|
||||
}
|
||||
|
||||
func (f *customResourceDefinitionInformer) Lister() v1beta1.CustomResourceDefinitionLister {
|
||||
return v1beta1.NewCustomResourceDefinitionLister(f.Informer().GetIndexer())
|
||||
}
|
||||
45
vendor/k8s.io/apiextensions-apiserver/pkg/client/informers/externalversions/apiextensions/v1beta1/interface.go
generated
vendored
Normal file
45
vendor/k8s.io/apiextensions-apiserver/pkg/client/informers/externalversions/apiextensions/v1beta1/interface.go
generated
vendored
Normal file
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
Copyright 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.
|
||||
*/
|
||||
|
||||
// Code generated by informer-gen. DO NOT EDIT.
|
||||
|
||||
package v1beta1
|
||||
|
||||
import (
|
||||
internalinterfaces "k8s.io/apiextensions-apiserver/pkg/client/informers/externalversions/internalinterfaces"
|
||||
)
|
||||
|
||||
// Interface provides access to all the informers in this group version.
|
||||
type Interface interface {
|
||||
// CustomResourceDefinitions returns a CustomResourceDefinitionInformer.
|
||||
CustomResourceDefinitions() CustomResourceDefinitionInformer
|
||||
}
|
||||
|
||||
type version struct {
|
||||
factory internalinterfaces.SharedInformerFactory
|
||||
namespace string
|
||||
tweakListOptions internalinterfaces.TweakListOptionsFunc
|
||||
}
|
||||
|
||||
// New returns a new Interface.
|
||||
func New(f internalinterfaces.SharedInformerFactory, namespace string, tweakListOptions internalinterfaces.TweakListOptionsFunc) Interface {
|
||||
return &version{factory: f, namespace: namespace, tweakListOptions: tweakListOptions}
|
||||
}
|
||||
|
||||
// CustomResourceDefinitions returns a CustomResourceDefinitionInformer.
|
||||
func (v *version) CustomResourceDefinitions() CustomResourceDefinitionInformer {
|
||||
return &customResourceDefinitionInformer{factory: v.factory, tweakListOptions: v.tweakListOptions}
|
||||
}
|
||||
180
vendor/k8s.io/apiextensions-apiserver/pkg/client/informers/externalversions/factory.go
generated
vendored
Normal file
180
vendor/k8s.io/apiextensions-apiserver/pkg/client/informers/externalversions/factory.go
generated
vendored
Normal file
@@ -0,0 +1,180 @@
|
||||
/*
|
||||
Copyright 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.
|
||||
*/
|
||||
|
||||
// Code generated by informer-gen. DO NOT EDIT.
|
||||
|
||||
package externalversions
|
||||
|
||||
import (
|
||||
reflect "reflect"
|
||||
sync "sync"
|
||||
time "time"
|
||||
|
||||
clientset "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset"
|
||||
apiextensions "k8s.io/apiextensions-apiserver/pkg/client/informers/externalversions/apiextensions"
|
||||
internalinterfaces "k8s.io/apiextensions-apiserver/pkg/client/informers/externalversions/internalinterfaces"
|
||||
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
runtime "k8s.io/apimachinery/pkg/runtime"
|
||||
schema "k8s.io/apimachinery/pkg/runtime/schema"
|
||||
cache "k8s.io/client-go/tools/cache"
|
||||
)
|
||||
|
||||
// SharedInformerOption defines the functional option type for SharedInformerFactory.
|
||||
type SharedInformerOption func(*sharedInformerFactory) *sharedInformerFactory
|
||||
|
||||
type sharedInformerFactory struct {
|
||||
client clientset.Interface
|
||||
namespace string
|
||||
tweakListOptions internalinterfaces.TweakListOptionsFunc
|
||||
lock sync.Mutex
|
||||
defaultResync time.Duration
|
||||
customResync map[reflect.Type]time.Duration
|
||||
|
||||
informers map[reflect.Type]cache.SharedIndexInformer
|
||||
// startedInformers is used for tracking which informers have been started.
|
||||
// This allows Start() to be called multiple times safely.
|
||||
startedInformers map[reflect.Type]bool
|
||||
}
|
||||
|
||||
// WithCustomResyncConfig sets a custom resync period for the specified informer types.
|
||||
func WithCustomResyncConfig(resyncConfig map[v1.Object]time.Duration) SharedInformerOption {
|
||||
return func(factory *sharedInformerFactory) *sharedInformerFactory {
|
||||
for k, v := range resyncConfig {
|
||||
factory.customResync[reflect.TypeOf(k)] = v
|
||||
}
|
||||
return factory
|
||||
}
|
||||
}
|
||||
|
||||
// WithTweakListOptions sets a custom filter on all listers of the configured SharedInformerFactory.
|
||||
func WithTweakListOptions(tweakListOptions internalinterfaces.TweakListOptionsFunc) SharedInformerOption {
|
||||
return func(factory *sharedInformerFactory) *sharedInformerFactory {
|
||||
factory.tweakListOptions = tweakListOptions
|
||||
return factory
|
||||
}
|
||||
}
|
||||
|
||||
// WithNamespace limits the SharedInformerFactory to the specified namespace.
|
||||
func WithNamespace(namespace string) SharedInformerOption {
|
||||
return func(factory *sharedInformerFactory) *sharedInformerFactory {
|
||||
factory.namespace = namespace
|
||||
return factory
|
||||
}
|
||||
}
|
||||
|
||||
// NewSharedInformerFactory constructs a new instance of sharedInformerFactory for all namespaces.
|
||||
func NewSharedInformerFactory(client clientset.Interface, defaultResync time.Duration) SharedInformerFactory {
|
||||
return NewSharedInformerFactoryWithOptions(client, defaultResync)
|
||||
}
|
||||
|
||||
// NewFilteredSharedInformerFactory constructs a new instance of sharedInformerFactory.
|
||||
// Listers obtained via this SharedInformerFactory will be subject to the same filters
|
||||
// as specified here.
|
||||
// Deprecated: Please use NewSharedInformerFactoryWithOptions instead
|
||||
func NewFilteredSharedInformerFactory(client clientset.Interface, defaultResync time.Duration, namespace string, tweakListOptions internalinterfaces.TweakListOptionsFunc) SharedInformerFactory {
|
||||
return NewSharedInformerFactoryWithOptions(client, defaultResync, WithNamespace(namespace), WithTweakListOptions(tweakListOptions))
|
||||
}
|
||||
|
||||
// NewSharedInformerFactoryWithOptions constructs a new instance of a SharedInformerFactory with additional options.
|
||||
func NewSharedInformerFactoryWithOptions(client clientset.Interface, defaultResync time.Duration, options ...SharedInformerOption) SharedInformerFactory {
|
||||
factory := &sharedInformerFactory{
|
||||
client: client,
|
||||
namespace: v1.NamespaceAll,
|
||||
defaultResync: defaultResync,
|
||||
informers: make(map[reflect.Type]cache.SharedIndexInformer),
|
||||
startedInformers: make(map[reflect.Type]bool),
|
||||
customResync: make(map[reflect.Type]time.Duration),
|
||||
}
|
||||
|
||||
// Apply all options
|
||||
for _, opt := range options {
|
||||
factory = opt(factory)
|
||||
}
|
||||
|
||||
return factory
|
||||
}
|
||||
|
||||
// Start initializes all requested informers.
|
||||
func (f *sharedInformerFactory) Start(stopCh <-chan struct{}) {
|
||||
f.lock.Lock()
|
||||
defer f.lock.Unlock()
|
||||
|
||||
for informerType, informer := range f.informers {
|
||||
if !f.startedInformers[informerType] {
|
||||
go informer.Run(stopCh)
|
||||
f.startedInformers[informerType] = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// WaitForCacheSync waits for all started informers' cache were synced.
|
||||
func (f *sharedInformerFactory) WaitForCacheSync(stopCh <-chan struct{}) map[reflect.Type]bool {
|
||||
informers := func() map[reflect.Type]cache.SharedIndexInformer {
|
||||
f.lock.Lock()
|
||||
defer f.lock.Unlock()
|
||||
|
||||
informers := map[reflect.Type]cache.SharedIndexInformer{}
|
||||
for informerType, informer := range f.informers {
|
||||
if f.startedInformers[informerType] {
|
||||
informers[informerType] = informer
|
||||
}
|
||||
}
|
||||
return informers
|
||||
}()
|
||||
|
||||
res := map[reflect.Type]bool{}
|
||||
for informType, informer := range informers {
|
||||
res[informType] = cache.WaitForCacheSync(stopCh, informer.HasSynced)
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
// InternalInformerFor returns the SharedIndexInformer for obj using an internal
|
||||
// client.
|
||||
func (f *sharedInformerFactory) InformerFor(obj runtime.Object, newFunc internalinterfaces.NewInformerFunc) cache.SharedIndexInformer {
|
||||
f.lock.Lock()
|
||||
defer f.lock.Unlock()
|
||||
|
||||
informerType := reflect.TypeOf(obj)
|
||||
informer, exists := f.informers[informerType]
|
||||
if exists {
|
||||
return informer
|
||||
}
|
||||
|
||||
resyncPeriod, exists := f.customResync[informerType]
|
||||
if !exists {
|
||||
resyncPeriod = f.defaultResync
|
||||
}
|
||||
|
||||
informer = newFunc(f.client, resyncPeriod)
|
||||
f.informers[informerType] = informer
|
||||
|
||||
return informer
|
||||
}
|
||||
|
||||
// SharedInformerFactory provides shared informers for resources in all known
|
||||
// API group versions.
|
||||
type SharedInformerFactory interface {
|
||||
internalinterfaces.SharedInformerFactory
|
||||
ForResource(resource schema.GroupVersionResource) (GenericInformer, error)
|
||||
WaitForCacheSync(stopCh <-chan struct{}) map[reflect.Type]bool
|
||||
|
||||
Apiextensions() apiextensions.Interface
|
||||
}
|
||||
|
||||
func (f *sharedInformerFactory) Apiextensions() apiextensions.Interface {
|
||||
return apiextensions.New(f, f.namespace, f.tweakListOptions)
|
||||
}
|
||||
62
vendor/k8s.io/apiextensions-apiserver/pkg/client/informers/externalversions/generic.go
generated
vendored
Normal file
62
vendor/k8s.io/apiextensions-apiserver/pkg/client/informers/externalversions/generic.go
generated
vendored
Normal file
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
Copyright 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.
|
||||
*/
|
||||
|
||||
// Code generated by informer-gen. DO NOT EDIT.
|
||||
|
||||
package externalversions
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
v1beta1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1"
|
||||
schema "k8s.io/apimachinery/pkg/runtime/schema"
|
||||
cache "k8s.io/client-go/tools/cache"
|
||||
)
|
||||
|
||||
// GenericInformer is type of SharedIndexInformer which will locate and delegate to other
|
||||
// sharedInformers based on type
|
||||
type GenericInformer interface {
|
||||
Informer() cache.SharedIndexInformer
|
||||
Lister() cache.GenericLister
|
||||
}
|
||||
|
||||
type genericInformer struct {
|
||||
informer cache.SharedIndexInformer
|
||||
resource schema.GroupResource
|
||||
}
|
||||
|
||||
// Informer returns the SharedIndexInformer.
|
||||
func (f *genericInformer) Informer() cache.SharedIndexInformer {
|
||||
return f.informer
|
||||
}
|
||||
|
||||
// Lister returns the GenericLister.
|
||||
func (f *genericInformer) Lister() cache.GenericLister {
|
||||
return cache.NewGenericLister(f.Informer().GetIndexer(), f.resource)
|
||||
}
|
||||
|
||||
// ForResource gives generic access to a shared informer of the matching type
|
||||
// TODO extend this to unknown resources with a client pool
|
||||
func (f *sharedInformerFactory) ForResource(resource schema.GroupVersionResource) (GenericInformer, error) {
|
||||
switch resource {
|
||||
// Group=apiextensions.k8s.io, Version=v1beta1
|
||||
case v1beta1.SchemeGroupVersion.WithResource("customresourcedefinitions"):
|
||||
return &genericInformer{resource: resource.GroupResource(), informer: f.Apiextensions().V1beta1().CustomResourceDefinitions().Informer()}, nil
|
||||
|
||||
}
|
||||
|
||||
return nil, fmt.Errorf("no informer found for %v", resource)
|
||||
}
|
||||
38
vendor/k8s.io/apiextensions-apiserver/pkg/client/informers/externalversions/internalinterfaces/factory_interfaces.go
generated
vendored
Normal file
38
vendor/k8s.io/apiextensions-apiserver/pkg/client/informers/externalversions/internalinterfaces/factory_interfaces.go
generated
vendored
Normal file
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
Copyright 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.
|
||||
*/
|
||||
|
||||
// Code generated by informer-gen. DO NOT EDIT.
|
||||
|
||||
package internalinterfaces
|
||||
|
||||
import (
|
||||
time "time"
|
||||
|
||||
clientset "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset"
|
||||
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
runtime "k8s.io/apimachinery/pkg/runtime"
|
||||
cache "k8s.io/client-go/tools/cache"
|
||||
)
|
||||
|
||||
type NewInformerFunc func(clientset.Interface, time.Duration) cache.SharedIndexInformer
|
||||
|
||||
// SharedInformerFactory a small interface to allow for adding an informer without an import cycle
|
||||
type SharedInformerFactory interface {
|
||||
Start(stopCh <-chan struct{})
|
||||
InformerFor(obj runtime.Object, newFunc NewInformerFunc) cache.SharedIndexInformer
|
||||
}
|
||||
|
||||
type TweakListOptionsFunc func(*v1.ListOptions)
|
||||
46
vendor/k8s.io/apiextensions-apiserver/pkg/client/informers/internalversion/apiextensions/interface.go
generated
vendored
Normal file
46
vendor/k8s.io/apiextensions-apiserver/pkg/client/informers/internalversion/apiextensions/interface.go
generated
vendored
Normal file
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
Copyright 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.
|
||||
*/
|
||||
|
||||
// Code generated by informer-gen. DO NOT EDIT.
|
||||
|
||||
package apiextensions
|
||||
|
||||
import (
|
||||
internalversion "k8s.io/apiextensions-apiserver/pkg/client/informers/internalversion/apiextensions/internalversion"
|
||||
internalinterfaces "k8s.io/apiextensions-apiserver/pkg/client/informers/internalversion/internalinterfaces"
|
||||
)
|
||||
|
||||
// Interface provides access to each of this group's versions.
|
||||
type Interface interface {
|
||||
// InternalVersion provides access to shared informers for resources in InternalVersion.
|
||||
InternalVersion() internalversion.Interface
|
||||
}
|
||||
|
||||
type group struct {
|
||||
factory internalinterfaces.SharedInformerFactory
|
||||
namespace string
|
||||
tweakListOptions internalinterfaces.TweakListOptionsFunc
|
||||
}
|
||||
|
||||
// New returns a new Interface.
|
||||
func New(f internalinterfaces.SharedInformerFactory, namespace string, tweakListOptions internalinterfaces.TweakListOptionsFunc) Interface {
|
||||
return &group{factory: f, namespace: namespace, tweakListOptions: tweakListOptions}
|
||||
}
|
||||
|
||||
// InternalVersion returns a new internalversion.Interface.
|
||||
func (g *group) InternalVersion() internalversion.Interface {
|
||||
return internalversion.New(g.factory, g.namespace, g.tweakListOptions)
|
||||
}
|
||||
88
vendor/k8s.io/apiextensions-apiserver/pkg/client/informers/internalversion/apiextensions/internalversion/customresourcedefinition.go
generated
vendored
Normal file
88
vendor/k8s.io/apiextensions-apiserver/pkg/client/informers/internalversion/apiextensions/internalversion/customresourcedefinition.go
generated
vendored
Normal file
@@ -0,0 +1,88 @@
|
||||
/*
|
||||
Copyright 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.
|
||||
*/
|
||||
|
||||
// Code generated by informer-gen. DO NOT EDIT.
|
||||
|
||||
package internalversion
|
||||
|
||||
import (
|
||||
time "time"
|
||||
|
||||
apiextensions "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions"
|
||||
internalclientset "k8s.io/apiextensions-apiserver/pkg/client/clientset/internalclientset"
|
||||
internalinterfaces "k8s.io/apiextensions-apiserver/pkg/client/informers/internalversion/internalinterfaces"
|
||||
internalversion "k8s.io/apiextensions-apiserver/pkg/client/listers/apiextensions/internalversion"
|
||||
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
runtime "k8s.io/apimachinery/pkg/runtime"
|
||||
watch "k8s.io/apimachinery/pkg/watch"
|
||||
cache "k8s.io/client-go/tools/cache"
|
||||
)
|
||||
|
||||
// CustomResourceDefinitionInformer provides access to a shared informer and lister for
|
||||
// CustomResourceDefinitions.
|
||||
type CustomResourceDefinitionInformer interface {
|
||||
Informer() cache.SharedIndexInformer
|
||||
Lister() internalversion.CustomResourceDefinitionLister
|
||||
}
|
||||
|
||||
type customResourceDefinitionInformer struct {
|
||||
factory internalinterfaces.SharedInformerFactory
|
||||
tweakListOptions internalinterfaces.TweakListOptionsFunc
|
||||
}
|
||||
|
||||
// NewCustomResourceDefinitionInformer constructs a new informer for CustomResourceDefinition type.
|
||||
// Always prefer using an informer factory to get a shared informer instead of getting an independent
|
||||
// one. This reduces memory footprint and number of connections to the server.
|
||||
func NewCustomResourceDefinitionInformer(client internalclientset.Interface, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer {
|
||||
return NewFilteredCustomResourceDefinitionInformer(client, resyncPeriod, indexers, nil)
|
||||
}
|
||||
|
||||
// NewFilteredCustomResourceDefinitionInformer constructs a new informer for CustomResourceDefinition type.
|
||||
// Always prefer using an informer factory to get a shared informer instead of getting an independent
|
||||
// one. This reduces memory footprint and number of connections to the server.
|
||||
func NewFilteredCustomResourceDefinitionInformer(client internalclientset.Interface, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer {
|
||||
return cache.NewSharedIndexInformer(
|
||||
&cache.ListWatch{
|
||||
ListFunc: func(options v1.ListOptions) (runtime.Object, error) {
|
||||
if tweakListOptions != nil {
|
||||
tweakListOptions(&options)
|
||||
}
|
||||
return client.Apiextensions().CustomResourceDefinitions().List(options)
|
||||
},
|
||||
WatchFunc: func(options v1.ListOptions) (watch.Interface, error) {
|
||||
if tweakListOptions != nil {
|
||||
tweakListOptions(&options)
|
||||
}
|
||||
return client.Apiextensions().CustomResourceDefinitions().Watch(options)
|
||||
},
|
||||
},
|
||||
&apiextensions.CustomResourceDefinition{},
|
||||
resyncPeriod,
|
||||
indexers,
|
||||
)
|
||||
}
|
||||
|
||||
func (f *customResourceDefinitionInformer) defaultInformer(client internalclientset.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer {
|
||||
return NewFilteredCustomResourceDefinitionInformer(client, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions)
|
||||
}
|
||||
|
||||
func (f *customResourceDefinitionInformer) Informer() cache.SharedIndexInformer {
|
||||
return f.factory.InformerFor(&apiextensions.CustomResourceDefinition{}, f.defaultInformer)
|
||||
}
|
||||
|
||||
func (f *customResourceDefinitionInformer) Lister() internalversion.CustomResourceDefinitionLister {
|
||||
return internalversion.NewCustomResourceDefinitionLister(f.Informer().GetIndexer())
|
||||
}
|
||||
45
vendor/k8s.io/apiextensions-apiserver/pkg/client/informers/internalversion/apiextensions/internalversion/interface.go
generated
vendored
Normal file
45
vendor/k8s.io/apiextensions-apiserver/pkg/client/informers/internalversion/apiextensions/internalversion/interface.go
generated
vendored
Normal file
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
Copyright 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.
|
||||
*/
|
||||
|
||||
// Code generated by informer-gen. DO NOT EDIT.
|
||||
|
||||
package internalversion
|
||||
|
||||
import (
|
||||
internalinterfaces "k8s.io/apiextensions-apiserver/pkg/client/informers/internalversion/internalinterfaces"
|
||||
)
|
||||
|
||||
// Interface provides access to all the informers in this group version.
|
||||
type Interface interface {
|
||||
// CustomResourceDefinitions returns a CustomResourceDefinitionInformer.
|
||||
CustomResourceDefinitions() CustomResourceDefinitionInformer
|
||||
}
|
||||
|
||||
type version struct {
|
||||
factory internalinterfaces.SharedInformerFactory
|
||||
namespace string
|
||||
tweakListOptions internalinterfaces.TweakListOptionsFunc
|
||||
}
|
||||
|
||||
// New returns a new Interface.
|
||||
func New(f internalinterfaces.SharedInformerFactory, namespace string, tweakListOptions internalinterfaces.TweakListOptionsFunc) Interface {
|
||||
return &version{factory: f, namespace: namespace, tweakListOptions: tweakListOptions}
|
||||
}
|
||||
|
||||
// CustomResourceDefinitions returns a CustomResourceDefinitionInformer.
|
||||
func (v *version) CustomResourceDefinitions() CustomResourceDefinitionInformer {
|
||||
return &customResourceDefinitionInformer{factory: v.factory, tweakListOptions: v.tweakListOptions}
|
||||
}
|
||||
180
vendor/k8s.io/apiextensions-apiserver/pkg/client/informers/internalversion/factory.go
generated
vendored
Normal file
180
vendor/k8s.io/apiextensions-apiserver/pkg/client/informers/internalversion/factory.go
generated
vendored
Normal file
@@ -0,0 +1,180 @@
|
||||
/*
|
||||
Copyright 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.
|
||||
*/
|
||||
|
||||
// Code generated by informer-gen. DO NOT EDIT.
|
||||
|
||||
package internalversion
|
||||
|
||||
import (
|
||||
reflect "reflect"
|
||||
sync "sync"
|
||||
time "time"
|
||||
|
||||
internalclientset "k8s.io/apiextensions-apiserver/pkg/client/clientset/internalclientset"
|
||||
apiextensions "k8s.io/apiextensions-apiserver/pkg/client/informers/internalversion/apiextensions"
|
||||
internalinterfaces "k8s.io/apiextensions-apiserver/pkg/client/informers/internalversion/internalinterfaces"
|
||||
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
runtime "k8s.io/apimachinery/pkg/runtime"
|
||||
schema "k8s.io/apimachinery/pkg/runtime/schema"
|
||||
cache "k8s.io/client-go/tools/cache"
|
||||
)
|
||||
|
||||
// SharedInformerOption defines the functional option type for SharedInformerFactory.
|
||||
type SharedInformerOption func(*sharedInformerFactory) *sharedInformerFactory
|
||||
|
||||
type sharedInformerFactory struct {
|
||||
client internalclientset.Interface
|
||||
namespace string
|
||||
tweakListOptions internalinterfaces.TweakListOptionsFunc
|
||||
lock sync.Mutex
|
||||
defaultResync time.Duration
|
||||
customResync map[reflect.Type]time.Duration
|
||||
|
||||
informers map[reflect.Type]cache.SharedIndexInformer
|
||||
// startedInformers is used for tracking which informers have been started.
|
||||
// This allows Start() to be called multiple times safely.
|
||||
startedInformers map[reflect.Type]bool
|
||||
}
|
||||
|
||||
// WithCustomResyncConfig sets a custom resync period for the specified informer types.
|
||||
func WithCustomResyncConfig(resyncConfig map[v1.Object]time.Duration) SharedInformerOption {
|
||||
return func(factory *sharedInformerFactory) *sharedInformerFactory {
|
||||
for k, v := range resyncConfig {
|
||||
factory.customResync[reflect.TypeOf(k)] = v
|
||||
}
|
||||
return factory
|
||||
}
|
||||
}
|
||||
|
||||
// WithTweakListOptions sets a custom filter on all listers of the configured SharedInformerFactory.
|
||||
func WithTweakListOptions(tweakListOptions internalinterfaces.TweakListOptionsFunc) SharedInformerOption {
|
||||
return func(factory *sharedInformerFactory) *sharedInformerFactory {
|
||||
factory.tweakListOptions = tweakListOptions
|
||||
return factory
|
||||
}
|
||||
}
|
||||
|
||||
// WithNamespace limits the SharedInformerFactory to the specified namespace.
|
||||
func WithNamespace(namespace string) SharedInformerOption {
|
||||
return func(factory *sharedInformerFactory) *sharedInformerFactory {
|
||||
factory.namespace = namespace
|
||||
return factory
|
||||
}
|
||||
}
|
||||
|
||||
// NewSharedInformerFactory constructs a new instance of sharedInformerFactory for all namespaces.
|
||||
func NewSharedInformerFactory(client internalclientset.Interface, defaultResync time.Duration) SharedInformerFactory {
|
||||
return NewSharedInformerFactoryWithOptions(client, defaultResync)
|
||||
}
|
||||
|
||||
// NewFilteredSharedInformerFactory constructs a new instance of sharedInformerFactory.
|
||||
// Listers obtained via this SharedInformerFactory will be subject to the same filters
|
||||
// as specified here.
|
||||
// Deprecated: Please use NewSharedInformerFactoryWithOptions instead
|
||||
func NewFilteredSharedInformerFactory(client internalclientset.Interface, defaultResync time.Duration, namespace string, tweakListOptions internalinterfaces.TweakListOptionsFunc) SharedInformerFactory {
|
||||
return NewSharedInformerFactoryWithOptions(client, defaultResync, WithNamespace(namespace), WithTweakListOptions(tweakListOptions))
|
||||
}
|
||||
|
||||
// NewSharedInformerFactoryWithOptions constructs a new instance of a SharedInformerFactory with additional options.
|
||||
func NewSharedInformerFactoryWithOptions(client internalclientset.Interface, defaultResync time.Duration, options ...SharedInformerOption) SharedInformerFactory {
|
||||
factory := &sharedInformerFactory{
|
||||
client: client,
|
||||
namespace: v1.NamespaceAll,
|
||||
defaultResync: defaultResync,
|
||||
informers: make(map[reflect.Type]cache.SharedIndexInformer),
|
||||
startedInformers: make(map[reflect.Type]bool),
|
||||
customResync: make(map[reflect.Type]time.Duration),
|
||||
}
|
||||
|
||||
// Apply all options
|
||||
for _, opt := range options {
|
||||
factory = opt(factory)
|
||||
}
|
||||
|
||||
return factory
|
||||
}
|
||||
|
||||
// Start initializes all requested informers.
|
||||
func (f *sharedInformerFactory) Start(stopCh <-chan struct{}) {
|
||||
f.lock.Lock()
|
||||
defer f.lock.Unlock()
|
||||
|
||||
for informerType, informer := range f.informers {
|
||||
if !f.startedInformers[informerType] {
|
||||
go informer.Run(stopCh)
|
||||
f.startedInformers[informerType] = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// WaitForCacheSync waits for all started informers' cache were synced.
|
||||
func (f *sharedInformerFactory) WaitForCacheSync(stopCh <-chan struct{}) map[reflect.Type]bool {
|
||||
informers := func() map[reflect.Type]cache.SharedIndexInformer {
|
||||
f.lock.Lock()
|
||||
defer f.lock.Unlock()
|
||||
|
||||
informers := map[reflect.Type]cache.SharedIndexInformer{}
|
||||
for informerType, informer := range f.informers {
|
||||
if f.startedInformers[informerType] {
|
||||
informers[informerType] = informer
|
||||
}
|
||||
}
|
||||
return informers
|
||||
}()
|
||||
|
||||
res := map[reflect.Type]bool{}
|
||||
for informType, informer := range informers {
|
||||
res[informType] = cache.WaitForCacheSync(stopCh, informer.HasSynced)
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
// InternalInformerFor returns the SharedIndexInformer for obj using an internal
|
||||
// client.
|
||||
func (f *sharedInformerFactory) InformerFor(obj runtime.Object, newFunc internalinterfaces.NewInformerFunc) cache.SharedIndexInformer {
|
||||
f.lock.Lock()
|
||||
defer f.lock.Unlock()
|
||||
|
||||
informerType := reflect.TypeOf(obj)
|
||||
informer, exists := f.informers[informerType]
|
||||
if exists {
|
||||
return informer
|
||||
}
|
||||
|
||||
resyncPeriod, exists := f.customResync[informerType]
|
||||
if !exists {
|
||||
resyncPeriod = f.defaultResync
|
||||
}
|
||||
|
||||
informer = newFunc(f.client, resyncPeriod)
|
||||
f.informers[informerType] = informer
|
||||
|
||||
return informer
|
||||
}
|
||||
|
||||
// SharedInformerFactory provides shared informers for resources in all known
|
||||
// API group versions.
|
||||
type SharedInformerFactory interface {
|
||||
internalinterfaces.SharedInformerFactory
|
||||
ForResource(resource schema.GroupVersionResource) (GenericInformer, error)
|
||||
WaitForCacheSync(stopCh <-chan struct{}) map[reflect.Type]bool
|
||||
|
||||
Apiextensions() apiextensions.Interface
|
||||
}
|
||||
|
||||
func (f *sharedInformerFactory) Apiextensions() apiextensions.Interface {
|
||||
return apiextensions.New(f, f.namespace, f.tweakListOptions)
|
||||
}
|
||||
62
vendor/k8s.io/apiextensions-apiserver/pkg/client/informers/internalversion/generic.go
generated
vendored
Normal file
62
vendor/k8s.io/apiextensions-apiserver/pkg/client/informers/internalversion/generic.go
generated
vendored
Normal file
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
Copyright 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.
|
||||
*/
|
||||
|
||||
// Code generated by informer-gen. DO NOT EDIT.
|
||||
|
||||
package internalversion
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
apiextensions "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions"
|
||||
schema "k8s.io/apimachinery/pkg/runtime/schema"
|
||||
cache "k8s.io/client-go/tools/cache"
|
||||
)
|
||||
|
||||
// GenericInformer is type of SharedIndexInformer which will locate and delegate to other
|
||||
// sharedInformers based on type
|
||||
type GenericInformer interface {
|
||||
Informer() cache.SharedIndexInformer
|
||||
Lister() cache.GenericLister
|
||||
}
|
||||
|
||||
type genericInformer struct {
|
||||
informer cache.SharedIndexInformer
|
||||
resource schema.GroupResource
|
||||
}
|
||||
|
||||
// Informer returns the SharedIndexInformer.
|
||||
func (f *genericInformer) Informer() cache.SharedIndexInformer {
|
||||
return f.informer
|
||||
}
|
||||
|
||||
// Lister returns the GenericLister.
|
||||
func (f *genericInformer) Lister() cache.GenericLister {
|
||||
return cache.NewGenericLister(f.Informer().GetIndexer(), f.resource)
|
||||
}
|
||||
|
||||
// ForResource gives generic access to a shared informer of the matching type
|
||||
// TODO extend this to unknown resources with a client pool
|
||||
func (f *sharedInformerFactory) ForResource(resource schema.GroupVersionResource) (GenericInformer, error) {
|
||||
switch resource {
|
||||
// Group=apiextensions.k8s.io, Version=internalVersion
|
||||
case apiextensions.SchemeGroupVersion.WithResource("customresourcedefinitions"):
|
||||
return &genericInformer{resource: resource.GroupResource(), informer: f.Apiextensions().InternalVersion().CustomResourceDefinitions().Informer()}, nil
|
||||
|
||||
}
|
||||
|
||||
return nil, fmt.Errorf("no informer found for %v", resource)
|
||||
}
|
||||
38
vendor/k8s.io/apiextensions-apiserver/pkg/client/informers/internalversion/internalinterfaces/factory_interfaces.go
generated
vendored
Normal file
38
vendor/k8s.io/apiextensions-apiserver/pkg/client/informers/internalversion/internalinterfaces/factory_interfaces.go
generated
vendored
Normal file
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
Copyright 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.
|
||||
*/
|
||||
|
||||
// Code generated by informer-gen. DO NOT EDIT.
|
||||
|
||||
package internalinterfaces
|
||||
|
||||
import (
|
||||
time "time"
|
||||
|
||||
internalclientset "k8s.io/apiextensions-apiserver/pkg/client/clientset/internalclientset"
|
||||
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
runtime "k8s.io/apimachinery/pkg/runtime"
|
||||
cache "k8s.io/client-go/tools/cache"
|
||||
)
|
||||
|
||||
type NewInformerFunc func(internalclientset.Interface, time.Duration) cache.SharedIndexInformer
|
||||
|
||||
// SharedInformerFactory a small interface to allow for adding an informer without an import cycle
|
||||
type SharedInformerFactory interface {
|
||||
Start(stopCh <-chan struct{})
|
||||
InformerFor(obj runtime.Object, newFunc NewInformerFunc) cache.SharedIndexInformer
|
||||
}
|
||||
|
||||
type TweakListOptionsFunc func(*v1.ListOptions)
|
||||
65
vendor/k8s.io/apiextensions-apiserver/pkg/client/listers/apiextensions/internalversion/customresourcedefinition.go
generated
vendored
Normal file
65
vendor/k8s.io/apiextensions-apiserver/pkg/client/listers/apiextensions/internalversion/customresourcedefinition.go
generated
vendored
Normal file
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
Copyright 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.
|
||||
*/
|
||||
|
||||
// Code generated by lister-gen. DO NOT EDIT.
|
||||
|
||||
package internalversion
|
||||
|
||||
import (
|
||||
apiextensions "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions"
|
||||
"k8s.io/apimachinery/pkg/api/errors"
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
"k8s.io/client-go/tools/cache"
|
||||
)
|
||||
|
||||
// CustomResourceDefinitionLister helps list CustomResourceDefinitions.
|
||||
type CustomResourceDefinitionLister interface {
|
||||
// List lists all CustomResourceDefinitions in the indexer.
|
||||
List(selector labels.Selector) (ret []*apiextensions.CustomResourceDefinition, err error)
|
||||
// Get retrieves the CustomResourceDefinition from the index for a given name.
|
||||
Get(name string) (*apiextensions.CustomResourceDefinition, error)
|
||||
CustomResourceDefinitionListerExpansion
|
||||
}
|
||||
|
||||
// customResourceDefinitionLister implements the CustomResourceDefinitionLister interface.
|
||||
type customResourceDefinitionLister struct {
|
||||
indexer cache.Indexer
|
||||
}
|
||||
|
||||
// NewCustomResourceDefinitionLister returns a new CustomResourceDefinitionLister.
|
||||
func NewCustomResourceDefinitionLister(indexer cache.Indexer) CustomResourceDefinitionLister {
|
||||
return &customResourceDefinitionLister{indexer: indexer}
|
||||
}
|
||||
|
||||
// List lists all CustomResourceDefinitions in the indexer.
|
||||
func (s *customResourceDefinitionLister) List(selector labels.Selector) (ret []*apiextensions.CustomResourceDefinition, err error) {
|
||||
err = cache.ListAll(s.indexer, selector, func(m interface{}) {
|
||||
ret = append(ret, m.(*apiextensions.CustomResourceDefinition))
|
||||
})
|
||||
return ret, err
|
||||
}
|
||||
|
||||
// Get retrieves the CustomResourceDefinition from the index for a given name.
|
||||
func (s *customResourceDefinitionLister) Get(name string) (*apiextensions.CustomResourceDefinition, error) {
|
||||
obj, exists, err := s.indexer.GetByKey(name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !exists {
|
||||
return nil, errors.NewNotFound(apiextensions.Resource("customresourcedefinition"), name)
|
||||
}
|
||||
return obj.(*apiextensions.CustomResourceDefinition), nil
|
||||
}
|
||||
23
vendor/k8s.io/apiextensions-apiserver/pkg/client/listers/apiextensions/internalversion/expansion_generated.go
generated
vendored
Normal file
23
vendor/k8s.io/apiextensions-apiserver/pkg/client/listers/apiextensions/internalversion/expansion_generated.go
generated
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
Copyright 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.
|
||||
*/
|
||||
|
||||
// Code generated by lister-gen. DO NOT EDIT.
|
||||
|
||||
package internalversion
|
||||
|
||||
// CustomResourceDefinitionListerExpansion allows custom methods to be added to
|
||||
// CustomResourceDefinitionLister.
|
||||
type CustomResourceDefinitionListerExpansion interface{}
|
||||
65
vendor/k8s.io/apiextensions-apiserver/pkg/client/listers/apiextensions/v1beta1/customresourcedefinition.go
generated
vendored
Normal file
65
vendor/k8s.io/apiextensions-apiserver/pkg/client/listers/apiextensions/v1beta1/customresourcedefinition.go
generated
vendored
Normal file
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
Copyright 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.
|
||||
*/
|
||||
|
||||
// Code generated by lister-gen. DO NOT EDIT.
|
||||
|
||||
package v1beta1
|
||||
|
||||
import (
|
||||
v1beta1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1"
|
||||
"k8s.io/apimachinery/pkg/api/errors"
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
"k8s.io/client-go/tools/cache"
|
||||
)
|
||||
|
||||
// CustomResourceDefinitionLister helps list CustomResourceDefinitions.
|
||||
type CustomResourceDefinitionLister interface {
|
||||
// List lists all CustomResourceDefinitions in the indexer.
|
||||
List(selector labels.Selector) (ret []*v1beta1.CustomResourceDefinition, err error)
|
||||
// Get retrieves the CustomResourceDefinition from the index for a given name.
|
||||
Get(name string) (*v1beta1.CustomResourceDefinition, error)
|
||||
CustomResourceDefinitionListerExpansion
|
||||
}
|
||||
|
||||
// customResourceDefinitionLister implements the CustomResourceDefinitionLister interface.
|
||||
type customResourceDefinitionLister struct {
|
||||
indexer cache.Indexer
|
||||
}
|
||||
|
||||
// NewCustomResourceDefinitionLister returns a new CustomResourceDefinitionLister.
|
||||
func NewCustomResourceDefinitionLister(indexer cache.Indexer) CustomResourceDefinitionLister {
|
||||
return &customResourceDefinitionLister{indexer: indexer}
|
||||
}
|
||||
|
||||
// List lists all CustomResourceDefinitions in the indexer.
|
||||
func (s *customResourceDefinitionLister) List(selector labels.Selector) (ret []*v1beta1.CustomResourceDefinition, err error) {
|
||||
err = cache.ListAll(s.indexer, selector, func(m interface{}) {
|
||||
ret = append(ret, m.(*v1beta1.CustomResourceDefinition))
|
||||
})
|
||||
return ret, err
|
||||
}
|
||||
|
||||
// Get retrieves the CustomResourceDefinition from the index for a given name.
|
||||
func (s *customResourceDefinitionLister) Get(name string) (*v1beta1.CustomResourceDefinition, error) {
|
||||
obj, exists, err := s.indexer.GetByKey(name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !exists {
|
||||
return nil, errors.NewNotFound(v1beta1.Resource("customresourcedefinition"), name)
|
||||
}
|
||||
return obj.(*v1beta1.CustomResourceDefinition), nil
|
||||
}
|
||||
23
vendor/k8s.io/apiextensions-apiserver/pkg/client/listers/apiextensions/v1beta1/expansion_generated.go
generated
vendored
Normal file
23
vendor/k8s.io/apiextensions-apiserver/pkg/client/listers/apiextensions/v1beta1/expansion_generated.go
generated
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
Copyright 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.
|
||||
*/
|
||||
|
||||
// Code generated by lister-gen. DO NOT EDIT.
|
||||
|
||||
package v1beta1
|
||||
|
||||
// CustomResourceDefinitionListerExpansion allows custom methods to be added to
|
||||
// CustomResourceDefinitionLister.
|
||||
type CustomResourceDefinitionListerExpansion interface{}
|
||||
115
vendor/k8s.io/apiextensions-apiserver/pkg/cmd/server/options/options.go
generated
vendored
Normal file
115
vendor/k8s.io/apiextensions-apiserver/pkg/cmd/server/options/options.go
generated
vendored
Normal file
@@ -0,0 +1,115 @@
|
||||
/*
|
||||
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 options
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"net"
|
||||
|
||||
"github.com/spf13/pflag"
|
||||
|
||||
"k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1"
|
||||
"k8s.io/apiextensions-apiserver/pkg/apiserver"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
utilerrors "k8s.io/apimachinery/pkg/util/errors"
|
||||
genericregistry "k8s.io/apiserver/pkg/registry/generic"
|
||||
genericapiserver "k8s.io/apiserver/pkg/server"
|
||||
genericoptions "k8s.io/apiserver/pkg/server/options"
|
||||
)
|
||||
|
||||
const defaultEtcdPathPrefix = "/registry/apiextensions.kubernetes.io"
|
||||
|
||||
// CustomResourceDefinitionsServerOptions describes the runtime options of an apiextensions-apiserver.
|
||||
type CustomResourceDefinitionsServerOptions struct {
|
||||
RecommendedOptions *genericoptions.RecommendedOptions
|
||||
APIEnablement *genericoptions.APIEnablementOptions
|
||||
|
||||
StdOut io.Writer
|
||||
StdErr io.Writer
|
||||
}
|
||||
|
||||
// NewCustomResourceDefinitionsServerOptions creates default options of an apiextensions-apiserver.
|
||||
func NewCustomResourceDefinitionsServerOptions(out, errOut io.Writer) *CustomResourceDefinitionsServerOptions {
|
||||
o := &CustomResourceDefinitionsServerOptions{
|
||||
RecommendedOptions: genericoptions.NewRecommendedOptions(defaultEtcdPathPrefix, apiserver.Codecs.LegacyCodec(v1beta1.SchemeGroupVersion)),
|
||||
APIEnablement: genericoptions.NewAPIEnablementOptions(),
|
||||
|
||||
StdOut: out,
|
||||
StdErr: errOut,
|
||||
}
|
||||
|
||||
return o
|
||||
}
|
||||
|
||||
// AddFlags adds the apiextensions-apiserver flags to the flagset.
|
||||
func (o CustomResourceDefinitionsServerOptions) AddFlags(fs *pflag.FlagSet) {
|
||||
o.RecommendedOptions.AddFlags(fs)
|
||||
o.APIEnablement.AddFlags(fs)
|
||||
}
|
||||
|
||||
// Validate validates the apiextensions-apiserver options.
|
||||
func (o CustomResourceDefinitionsServerOptions) Validate() error {
|
||||
errors := []error{}
|
||||
errors = append(errors, o.RecommendedOptions.Validate()...)
|
||||
errors = append(errors, o.APIEnablement.Validate(apiserver.Scheme)...)
|
||||
return utilerrors.NewAggregate(errors)
|
||||
}
|
||||
|
||||
// Complete fills in missing options.
|
||||
func (o *CustomResourceDefinitionsServerOptions) Complete() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Config returns an apiextensions-apiserver configuration.
|
||||
func (o CustomResourceDefinitionsServerOptions) Config() (*apiserver.Config, error) {
|
||||
// TODO have a "real" external address
|
||||
if err := o.RecommendedOptions.SecureServing.MaybeDefaultWithSelfSignedCerts("localhost", nil, []net.IP{net.ParseIP("127.0.0.1")}); err != nil {
|
||||
return nil, fmt.Errorf("error creating self-signed certificates: %v", err)
|
||||
}
|
||||
|
||||
serverConfig := genericapiserver.NewRecommendedConfig(apiserver.Codecs)
|
||||
if err := o.RecommendedOptions.ApplyTo(serverConfig, apiserver.Scheme); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := o.APIEnablement.ApplyTo(&serverConfig.Config, apiserver.DefaultAPIResourceConfigSource(), apiserver.Scheme); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
config := &apiserver.Config{
|
||||
GenericConfig: serverConfig,
|
||||
ExtraConfig: apiserver.ExtraConfig{
|
||||
CRDRESTOptionsGetter: NewCRDRESTOptionsGetter(*o.RecommendedOptions.Etcd),
|
||||
},
|
||||
}
|
||||
return config, nil
|
||||
}
|
||||
|
||||
// NewCRDRESTOptionsGetter create a RESTOptionsGetter for CustomResources.
|
||||
func NewCRDRESTOptionsGetter(etcdOptions genericoptions.EtcdOptions) genericregistry.RESTOptionsGetter {
|
||||
ret := apiserver.CRDRESTOptionsGetter{
|
||||
StorageConfig: etcdOptions.StorageConfig,
|
||||
StoragePrefix: etcdOptions.StorageConfig.Prefix,
|
||||
EnableWatchCache: etcdOptions.EnableWatchCache,
|
||||
DefaultWatchCacheSize: etcdOptions.DefaultWatchCacheSize,
|
||||
EnableGarbageCollection: etcdOptions.EnableGarbageCollection,
|
||||
DeleteCollectionWorkers: etcdOptions.DeleteCollectionWorkers,
|
||||
}
|
||||
ret.StorageConfig.Codec = unstructured.UnstructuredJSONScheme
|
||||
|
||||
return ret
|
||||
}
|
||||
64
vendor/k8s.io/apiextensions-apiserver/pkg/cmd/server/server.go
generated
vendored
Normal file
64
vendor/k8s.io/apiextensions-apiserver/pkg/cmd/server/server.go
generated
vendored
Normal file
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
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 server
|
||||
|
||||
import (
|
||||
"io"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"k8s.io/apiextensions-apiserver/pkg/cmd/server/options"
|
||||
genericapiserver "k8s.io/apiserver/pkg/server"
|
||||
)
|
||||
|
||||
func NewServerCommand(out, errOut io.Writer, stopCh <-chan struct{}) *cobra.Command {
|
||||
o := options.NewCustomResourceDefinitionsServerOptions(out, errOut)
|
||||
|
||||
cmd := &cobra.Command{
|
||||
Short: "Launch an API extensions API server",
|
||||
Long: "Launch an API extensions API server",
|
||||
RunE: func(c *cobra.Command, args []string) error {
|
||||
if err := o.Complete(); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := o.Validate(); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := Run(o, stopCh); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
fs := cmd.Flags()
|
||||
o.AddFlags(fs)
|
||||
return cmd
|
||||
}
|
||||
|
||||
func Run(o *options.CustomResourceDefinitionsServerOptions, stopCh <-chan struct{}) error {
|
||||
config, err := o.Config()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
server, err := config.Complete().New(genericapiserver.NewEmptyDelegate())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return server.GenericAPIServer.PrepareRun().Run(stopCh)
|
||||
}
|
||||
201
vendor/k8s.io/apiextensions-apiserver/pkg/cmd/server/testing/testserver.go
generated
vendored
Normal file
201
vendor/k8s.io/apiextensions-apiserver/pkg/cmd/server/testing/testserver.go
generated
vendored
Normal file
@@ -0,0 +1,201 @@
|
||||
/*
|
||||
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 testing
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"github.com/spf13/pflag"
|
||||
|
||||
"k8s.io/apiextensions-apiserver/pkg/cmd/server/options"
|
||||
"k8s.io/apimachinery/pkg/util/wait"
|
||||
"k8s.io/apiserver/pkg/registry/generic/registry"
|
||||
genericapiserver "k8s.io/apiserver/pkg/server"
|
||||
"k8s.io/apiserver/pkg/storage/storagebackend"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
restclient "k8s.io/client-go/rest"
|
||||
)
|
||||
|
||||
// TearDownFunc is to be called to tear down a test server.
|
||||
type TearDownFunc func()
|
||||
|
||||
// TestServerInstanceOptions Instance options the TestServer
|
||||
type TestServerInstanceOptions struct {
|
||||
// DisableStorageCleanup Disable the automatic storage cleanup
|
||||
DisableStorageCleanup bool
|
||||
}
|
||||
|
||||
// TestServer return values supplied by kube-test-ApiServer
|
||||
type TestServer struct {
|
||||
ClientConfig *restclient.Config // Rest client config
|
||||
ServerOpts *options.CustomResourceDefinitionsServerOptions // ServerOpts
|
||||
TearDownFn TearDownFunc // TearDown function
|
||||
TmpDir string // Temp Dir used, by the apiserver
|
||||
}
|
||||
|
||||
// Logger allows t.Testing and b.Testing to be passed to StartTestServer and StartTestServerOrDie
|
||||
type Logger interface {
|
||||
Errorf(format string, args ...interface{})
|
||||
Fatalf(format string, args ...interface{})
|
||||
Logf(format string, args ...interface{})
|
||||
}
|
||||
|
||||
// NewDefaultTestServerOptions Default options for TestServer instances
|
||||
func NewDefaultTestServerOptions() *TestServerInstanceOptions {
|
||||
return &TestServerInstanceOptions{
|
||||
DisableStorageCleanup: false,
|
||||
}
|
||||
}
|
||||
|
||||
// StartTestServer starts a apiextensions-apiserver. A rest client config and a tear-down func,
|
||||
// and location of the tmpdir are returned.
|
||||
//
|
||||
// Note: we return a tear-down func instead of a stop channel because the later will leak temporary
|
||||
// files that because Golang testing's call to os.Exit will not give a stop channel go routine
|
||||
// enough time to remove temporary files.
|
||||
func StartTestServer(t Logger, instanceOptions *TestServerInstanceOptions, customFlags []string, storageConfig *storagebackend.Config) (result TestServer, err error) {
|
||||
if instanceOptions == nil {
|
||||
instanceOptions = NewDefaultTestServerOptions()
|
||||
}
|
||||
|
||||
// TODO : Remove TrackStorageCleanup below when PR
|
||||
// https://github.com/kubernetes/kubernetes/pull/50690
|
||||
// merges as that shuts down storage properly
|
||||
if !instanceOptions.DisableStorageCleanup {
|
||||
registry.TrackStorageCleanup()
|
||||
}
|
||||
|
||||
stopCh := make(chan struct{})
|
||||
tearDown := func() {
|
||||
if !instanceOptions.DisableStorageCleanup {
|
||||
registry.CleanupStorage()
|
||||
}
|
||||
close(stopCh)
|
||||
if len(result.TmpDir) != 0 {
|
||||
os.RemoveAll(result.TmpDir)
|
||||
}
|
||||
}
|
||||
defer func() {
|
||||
if result.TearDownFn == nil {
|
||||
tearDown()
|
||||
}
|
||||
}()
|
||||
|
||||
result.TmpDir, err = ioutil.TempDir("", "apiextensions-apiserver")
|
||||
if err != nil {
|
||||
return result, fmt.Errorf("failed to create temp dir: %v", err)
|
||||
}
|
||||
|
||||
fs := pflag.NewFlagSet("test", pflag.PanicOnError)
|
||||
|
||||
s := options.NewCustomResourceDefinitionsServerOptions(os.Stdout, os.Stderr)
|
||||
s.AddFlags(fs)
|
||||
|
||||
s.RecommendedOptions.SecureServing.Listener, s.RecommendedOptions.SecureServing.BindPort, err = createListenerOnFreePort()
|
||||
if err != nil {
|
||||
return result, fmt.Errorf("failed to create listener: %v", err)
|
||||
}
|
||||
s.RecommendedOptions.SecureServing.ServerCert.CertDirectory = result.TmpDir
|
||||
if storageConfig != nil {
|
||||
s.RecommendedOptions.Etcd.StorageConfig = *storageConfig
|
||||
}
|
||||
s.APIEnablement.RuntimeConfig.Set("api/all=true")
|
||||
|
||||
fs.Parse(customFlags)
|
||||
|
||||
if err := s.Complete(); err != nil {
|
||||
return result, fmt.Errorf("failed to set default options: %v", err)
|
||||
}
|
||||
if err := s.Validate(); err != nil {
|
||||
return result, fmt.Errorf("failed to validate options: %v", err)
|
||||
}
|
||||
|
||||
t.Logf("runtime-config=%v", s.APIEnablement.RuntimeConfig)
|
||||
t.Logf("Starting apiextensions-apiserver on port %d...", s.RecommendedOptions.SecureServing.BindPort)
|
||||
|
||||
config, err := s.Config()
|
||||
if err != nil {
|
||||
return result, fmt.Errorf("failed to create config from options: %v", err)
|
||||
}
|
||||
server, err := config.Complete().New(genericapiserver.NewEmptyDelegate())
|
||||
if err != nil {
|
||||
return result, fmt.Errorf("failed to create server: %v", err)
|
||||
}
|
||||
|
||||
go func(stopCh <-chan struct{}) {
|
||||
if err := server.GenericAPIServer.PrepareRun().Run(stopCh); err != nil {
|
||||
t.Errorf("apiextensions-apiserver failed run: %v", err)
|
||||
}
|
||||
}(stopCh)
|
||||
|
||||
t.Logf("Waiting for /healthz to be ok...")
|
||||
|
||||
client, err := kubernetes.NewForConfig(server.GenericAPIServer.LoopbackClientConfig)
|
||||
if err != nil {
|
||||
return result, fmt.Errorf("failed to create a client: %v", err)
|
||||
}
|
||||
err = wait.Poll(100*time.Millisecond, 30*time.Second, func() (bool, error) {
|
||||
result := client.CoreV1().RESTClient().Get().AbsPath("/healthz").Do()
|
||||
status := 0
|
||||
result.StatusCode(&status)
|
||||
if status == 200 {
|
||||
return true, nil
|
||||
}
|
||||
return false, nil
|
||||
})
|
||||
if err != nil {
|
||||
return result, fmt.Errorf("failed to wait for /healthz to return ok: %v", err)
|
||||
}
|
||||
|
||||
// from here the caller must call tearDown
|
||||
result.ClientConfig = server.GenericAPIServer.LoopbackClientConfig
|
||||
result.ServerOpts = s
|
||||
result.TearDownFn = tearDown
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// StartTestServerOrDie calls StartTestServer t.Fatal if it does not succeed.
|
||||
func StartTestServerOrDie(t Logger, instanceOptions *TestServerInstanceOptions, flags []string, storageConfig *storagebackend.Config) *TestServer {
|
||||
result, err := StartTestServer(t, instanceOptions, flags, storageConfig)
|
||||
if err == nil {
|
||||
return &result
|
||||
}
|
||||
|
||||
t.Fatalf("failed to launch server: %v", err)
|
||||
return nil
|
||||
}
|
||||
|
||||
func createListenerOnFreePort() (net.Listener, int, error) {
|
||||
ln, err := net.Listen("tcp", ":0")
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
// get port
|
||||
tcpAddr, ok := ln.Addr().(*net.TCPAddr)
|
||||
if !ok {
|
||||
ln.Close()
|
||||
return nil, 0, fmt.Errorf("invalid listen address: %q", ln.Addr().String())
|
||||
}
|
||||
|
||||
return ln, tcpAddr.Port, nil
|
||||
}
|
||||
142
vendor/k8s.io/apiextensions-apiserver/pkg/controller/establish/establishing_controller.go
generated
vendored
Normal file
142
vendor/k8s.io/apiextensions-apiserver/pkg/controller/establish/establishing_controller.go
generated
vendored
Normal file
@@ -0,0 +1,142 @@
|
||||
/*
|
||||
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 establish
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/golang/glog"
|
||||
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
||||
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
|
||||
"k8s.io/apimachinery/pkg/util/wait"
|
||||
"k8s.io/client-go/tools/cache"
|
||||
"k8s.io/client-go/util/workqueue"
|
||||
|
||||
"k8s.io/apiextensions-apiserver/pkg/apis/apiextensions"
|
||||
client "k8s.io/apiextensions-apiserver/pkg/client/clientset/internalclientset/typed/apiextensions/internalversion"
|
||||
informers "k8s.io/apiextensions-apiserver/pkg/client/informers/internalversion/apiextensions/internalversion"
|
||||
listers "k8s.io/apiextensions-apiserver/pkg/client/listers/apiextensions/internalversion"
|
||||
)
|
||||
|
||||
// EstablishingController controls how and when CRD is established.
|
||||
type EstablishingController struct {
|
||||
crdClient client.CustomResourceDefinitionsGetter
|
||||
crdLister listers.CustomResourceDefinitionLister
|
||||
crdSynced cache.InformerSynced
|
||||
|
||||
// To allow injection for testing.
|
||||
syncFn func(key string) error
|
||||
|
||||
queue workqueue.RateLimitingInterface
|
||||
}
|
||||
|
||||
// NewEstablishingController creates new EstablishingController.
|
||||
func NewEstablishingController(crdInformer informers.CustomResourceDefinitionInformer,
|
||||
crdClient client.CustomResourceDefinitionsGetter) *EstablishingController {
|
||||
ec := &EstablishingController{
|
||||
crdClient: crdClient,
|
||||
crdLister: crdInformer.Lister(),
|
||||
crdSynced: crdInformer.Informer().HasSynced,
|
||||
queue: workqueue.NewNamedRateLimitingQueue(workqueue.DefaultControllerRateLimiter(), "crdEstablishing"),
|
||||
}
|
||||
|
||||
ec.syncFn = ec.sync
|
||||
|
||||
return ec
|
||||
}
|
||||
|
||||
// QueueCRD adds CRD into the establishing queue.
|
||||
func (ec *EstablishingController) QueueCRD(key string, timeout time.Duration) {
|
||||
ec.queue.AddAfter(key, timeout)
|
||||
}
|
||||
|
||||
// Run starts the EstablishingController.
|
||||
func (ec *EstablishingController) Run(stopCh <-chan struct{}) {
|
||||
defer utilruntime.HandleCrash()
|
||||
defer ec.queue.ShutDown()
|
||||
|
||||
glog.Infof("Starting EstablishingController")
|
||||
defer glog.Infof("Shutting down EstablishingController")
|
||||
|
||||
if !cache.WaitForCacheSync(stopCh, ec.crdSynced) {
|
||||
return
|
||||
}
|
||||
|
||||
// only start one worker thread since its a slow moving API
|
||||
go wait.Until(ec.runWorker, time.Second, stopCh)
|
||||
|
||||
<-stopCh
|
||||
}
|
||||
|
||||
func (ec *EstablishingController) runWorker() {
|
||||
for ec.processNextWorkItem() {
|
||||
}
|
||||
}
|
||||
|
||||
// processNextWorkItem deals with one key off the queue.
|
||||
// It returns false when it's time to quit.
|
||||
func (ec *EstablishingController) processNextWorkItem() bool {
|
||||
key, quit := ec.queue.Get()
|
||||
if quit {
|
||||
return false
|
||||
}
|
||||
defer ec.queue.Done(key)
|
||||
|
||||
err := ec.syncFn(key.(string))
|
||||
if err == nil {
|
||||
return true
|
||||
}
|
||||
|
||||
utilruntime.HandleError(fmt.Errorf("%v failed with: %v", key, err))
|
||||
ec.queue.AddRateLimited(key)
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
// sync is used to turn CRDs into the Established state.
|
||||
func (ec *EstablishingController) sync(key string) error {
|
||||
cachedCRD, err := ec.crdLister.Get(key)
|
||||
if apierrors.IsNotFound(err) {
|
||||
return nil
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if !apiextensions.IsCRDConditionTrue(cachedCRD, apiextensions.NamesAccepted) ||
|
||||
apiextensions.IsCRDConditionTrue(cachedCRD, apiextensions.Established) {
|
||||
return nil
|
||||
}
|
||||
|
||||
crd := cachedCRD.DeepCopy()
|
||||
establishedCondition := apiextensions.CustomResourceDefinitionCondition{
|
||||
Type: apiextensions.Established,
|
||||
Status: apiextensions.ConditionTrue,
|
||||
Reason: "InitialNamesAccepted",
|
||||
Message: "the initial names have been accepted",
|
||||
}
|
||||
apiextensions.SetCRDCondition(crd, establishedCondition)
|
||||
|
||||
// Update server with new CRD condition.
|
||||
_, err = ec.crdClient.CustomResourceDefinitions().UpdateStatus(crd)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
327
vendor/k8s.io/apiextensions-apiserver/pkg/controller/finalizer/crd_finalizer.go
generated
vendored
Normal file
327
vendor/k8s.io/apiextensions-apiserver/pkg/controller/finalizer/crd_finalizer.go
generated
vendored
Normal file
@@ -0,0 +1,327 @@
|
||||
/*
|
||||
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 finalizer
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"time"
|
||||
|
||||
"github.com/golang/glog"
|
||||
|
||||
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
||||
"k8s.io/apimachinery/pkg/api/meta"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
utilerrors "k8s.io/apimachinery/pkg/util/errors"
|
||||
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
|
||||
"k8s.io/apimachinery/pkg/util/sets"
|
||||
"k8s.io/apimachinery/pkg/util/wait"
|
||||
genericapirequest "k8s.io/apiserver/pkg/endpoints/request"
|
||||
"k8s.io/apiserver/pkg/registry/rest"
|
||||
"k8s.io/client-go/tools/cache"
|
||||
"k8s.io/client-go/util/workqueue"
|
||||
|
||||
"k8s.io/apiextensions-apiserver/pkg/apis/apiextensions"
|
||||
client "k8s.io/apiextensions-apiserver/pkg/client/clientset/internalclientset/typed/apiextensions/internalversion"
|
||||
informers "k8s.io/apiextensions-apiserver/pkg/client/informers/internalversion/apiextensions/internalversion"
|
||||
listers "k8s.io/apiextensions-apiserver/pkg/client/listers/apiextensions/internalversion"
|
||||
)
|
||||
|
||||
// CRDFinalizer is a controller that finalizes the CRD by deleting all the CRs associated with it.
|
||||
type CRDFinalizer struct {
|
||||
crdClient client.CustomResourceDefinitionsGetter
|
||||
crClientGetter CRClientGetter
|
||||
|
||||
crdLister listers.CustomResourceDefinitionLister
|
||||
crdSynced cache.InformerSynced
|
||||
|
||||
// To allow injection for testing.
|
||||
syncFn func(key string) error
|
||||
|
||||
queue workqueue.RateLimitingInterface
|
||||
}
|
||||
|
||||
// ListerCollectionDeleter combines rest.Lister and rest.CollectionDeleter.
|
||||
type ListerCollectionDeleter interface {
|
||||
rest.Lister
|
||||
rest.CollectionDeleter
|
||||
}
|
||||
|
||||
// CRClientGetter knows how to get a ListerCollectionDeleter for a given CRD UID.
|
||||
type CRClientGetter interface {
|
||||
// GetCustomResourceListerCollectionDeleter gets the ListerCollectionDeleter for the given CRD
|
||||
// UID.
|
||||
GetCustomResourceListerCollectionDeleter(crd *apiextensions.CustomResourceDefinition) (ListerCollectionDeleter, error)
|
||||
}
|
||||
|
||||
// NewCRDFinalizer creates a new CRDFinalizer.
|
||||
func NewCRDFinalizer(
|
||||
crdInformer informers.CustomResourceDefinitionInformer,
|
||||
crdClient client.CustomResourceDefinitionsGetter,
|
||||
crClientGetter CRClientGetter,
|
||||
) *CRDFinalizer {
|
||||
c := &CRDFinalizer{
|
||||
crdClient: crdClient,
|
||||
crdLister: crdInformer.Lister(),
|
||||
crdSynced: crdInformer.Informer().HasSynced,
|
||||
crClientGetter: crClientGetter,
|
||||
queue: workqueue.NewNamedRateLimitingQueue(workqueue.DefaultControllerRateLimiter(), "CustomResourceDefinition-CRDFinalizer"),
|
||||
}
|
||||
|
||||
crdInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{
|
||||
AddFunc: c.addCustomResourceDefinition,
|
||||
UpdateFunc: c.updateCustomResourceDefinition,
|
||||
})
|
||||
|
||||
c.syncFn = c.sync
|
||||
|
||||
return c
|
||||
}
|
||||
|
||||
func (c *CRDFinalizer) sync(key string) error {
|
||||
cachedCRD, err := c.crdLister.Get(key)
|
||||
if apierrors.IsNotFound(err) {
|
||||
return nil
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// no work to do
|
||||
if cachedCRD.DeletionTimestamp.IsZero() || !apiextensions.CRDHasFinalizer(cachedCRD, apiextensions.CustomResourceCleanupFinalizer) {
|
||||
return nil
|
||||
}
|
||||
|
||||
crd := cachedCRD.DeepCopy()
|
||||
|
||||
// update the status condition. This cleanup could take a while.
|
||||
apiextensions.SetCRDCondition(crd, apiextensions.CustomResourceDefinitionCondition{
|
||||
Type: apiextensions.Terminating,
|
||||
Status: apiextensions.ConditionTrue,
|
||||
Reason: "InstanceDeletionInProgress",
|
||||
Message: "CustomResource deletion is in progress",
|
||||
})
|
||||
crd, err = c.crdClient.CustomResourceDefinitions().UpdateStatus(crd)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Now we can start deleting items. We should use the REST API to ensure that all normal admission runs.
|
||||
// Since we control the endpoints, we know that delete collection works. No need to delete if not established.
|
||||
if apiextensions.IsCRDConditionTrue(crd, apiextensions.Established) {
|
||||
cond, deleteErr := c.deleteInstances(crd)
|
||||
apiextensions.SetCRDCondition(crd, cond)
|
||||
if deleteErr != nil {
|
||||
crd, err = c.crdClient.CustomResourceDefinitions().UpdateStatus(crd)
|
||||
if err != nil {
|
||||
utilruntime.HandleError(err)
|
||||
}
|
||||
return deleteErr
|
||||
}
|
||||
} else {
|
||||
apiextensions.SetCRDCondition(crd, apiextensions.CustomResourceDefinitionCondition{
|
||||
Type: apiextensions.Terminating,
|
||||
Status: apiextensions.ConditionFalse,
|
||||
Reason: "NeverEstablished",
|
||||
Message: "resource was never established",
|
||||
})
|
||||
}
|
||||
|
||||
apiextensions.CRDRemoveFinalizer(crd, apiextensions.CustomResourceCleanupFinalizer)
|
||||
crd, err = c.crdClient.CustomResourceDefinitions().UpdateStatus(crd)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// and now issue another delete, which should clean it all up if no finalizers remain or no-op if they do
|
||||
return c.crdClient.CustomResourceDefinitions().Delete(crd.Name, nil)
|
||||
}
|
||||
|
||||
func (c *CRDFinalizer) deleteInstances(crd *apiextensions.CustomResourceDefinition) (apiextensions.CustomResourceDefinitionCondition, error) {
|
||||
// Now we can start deleting items. While it would be ideal to use a REST API client, doing so
|
||||
// could incorrectly delete a ThirdPartyResource with the same URL as the CustomResource, so we go
|
||||
// directly to the storage instead. Since we control the storage, we know that delete collection works.
|
||||
crClient, err := c.crClientGetter.GetCustomResourceListerCollectionDeleter(crd)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("unable to find a custom resource client for %s.%s: %v", crd.Status.AcceptedNames.Plural, crd.Spec.Group, err)
|
||||
return apiextensions.CustomResourceDefinitionCondition{
|
||||
Type: apiextensions.Terminating,
|
||||
Status: apiextensions.ConditionTrue,
|
||||
Reason: "InstanceDeletionFailed",
|
||||
Message: fmt.Sprintf("could not list instances: %v", err),
|
||||
}, err
|
||||
}
|
||||
|
||||
ctx := genericapirequest.NewContext()
|
||||
allResources, err := crClient.List(ctx, nil)
|
||||
if err != nil {
|
||||
return apiextensions.CustomResourceDefinitionCondition{
|
||||
Type: apiextensions.Terminating,
|
||||
Status: apiextensions.ConditionTrue,
|
||||
Reason: "InstanceDeletionFailed",
|
||||
Message: fmt.Sprintf("could not list instances: %v", err),
|
||||
}, err
|
||||
}
|
||||
|
||||
deletedNamespaces := sets.String{}
|
||||
deleteErrors := []error{}
|
||||
for _, item := range allResources.(*unstructured.UnstructuredList).Items {
|
||||
metadata, err := meta.Accessor(&item)
|
||||
if err != nil {
|
||||
utilruntime.HandleError(err)
|
||||
continue
|
||||
}
|
||||
if deletedNamespaces.Has(metadata.GetNamespace()) {
|
||||
continue
|
||||
}
|
||||
// don't retry deleting the same namespace
|
||||
deletedNamespaces.Insert(metadata.GetNamespace())
|
||||
nsCtx := genericapirequest.WithNamespace(ctx, metadata.GetNamespace())
|
||||
if _, err := crClient.DeleteCollection(nsCtx, nil, nil); err != nil {
|
||||
deleteErrors = append(deleteErrors, err)
|
||||
continue
|
||||
}
|
||||
}
|
||||
if deleteError := utilerrors.NewAggregate(deleteErrors); deleteError != nil {
|
||||
return apiextensions.CustomResourceDefinitionCondition{
|
||||
Type: apiextensions.Terminating,
|
||||
Status: apiextensions.ConditionTrue,
|
||||
Reason: "InstanceDeletionFailed",
|
||||
Message: fmt.Sprintf("could not issue all deletes: %v", deleteError),
|
||||
}, deleteError
|
||||
}
|
||||
|
||||
// now we need to wait until all the resources are deleted. Start with a simple poll before we do anything fancy.
|
||||
// TODO not all servers are synchronized on caches. It is possible for a stale one to still be creating things.
|
||||
// Once we have a mechanism for servers to indicate their states, we should check that for concurrence.
|
||||
err = wait.PollImmediate(5*time.Second, 1*time.Minute, func() (bool, error) {
|
||||
listObj, err := crClient.List(ctx, nil)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
if len(listObj.(*unstructured.UnstructuredList).Items) == 0 {
|
||||
return true, nil
|
||||
}
|
||||
glog.V(2).Infof("%s.%s waiting for %d items to be removed", crd.Status.AcceptedNames.Plural, crd.Spec.Group, len(listObj.(*unstructured.UnstructuredList).Items))
|
||||
return false, nil
|
||||
})
|
||||
if err != nil {
|
||||
return apiextensions.CustomResourceDefinitionCondition{
|
||||
Type: apiextensions.Terminating,
|
||||
Status: apiextensions.ConditionTrue,
|
||||
Reason: "InstanceDeletionCheck",
|
||||
Message: fmt.Sprintf("could not confirm zero CustomResources remaining: %v", err),
|
||||
}, err
|
||||
}
|
||||
return apiextensions.CustomResourceDefinitionCondition{
|
||||
Type: apiextensions.Terminating,
|
||||
Status: apiextensions.ConditionFalse,
|
||||
Reason: "InstanceDeletionCompleted",
|
||||
Message: "removed all instances",
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (c *CRDFinalizer) Run(workers int, stopCh <-chan struct{}) {
|
||||
defer utilruntime.HandleCrash()
|
||||
defer c.queue.ShutDown()
|
||||
|
||||
glog.Infof("Starting CRDFinalizer")
|
||||
defer glog.Infof("Shutting down CRDFinalizer")
|
||||
|
||||
if !cache.WaitForCacheSync(stopCh, c.crdSynced) {
|
||||
return
|
||||
}
|
||||
|
||||
for i := 0; i < workers; i++ {
|
||||
go wait.Until(c.runWorker, time.Second, stopCh)
|
||||
}
|
||||
|
||||
<-stopCh
|
||||
}
|
||||
|
||||
func (c *CRDFinalizer) runWorker() {
|
||||
for c.processNextWorkItem() {
|
||||
}
|
||||
}
|
||||
|
||||
// processNextWorkItem deals with one key off the queue. It returns false when it's time to quit.
|
||||
func (c *CRDFinalizer) processNextWorkItem() bool {
|
||||
key, quit := c.queue.Get()
|
||||
if quit {
|
||||
return false
|
||||
}
|
||||
defer c.queue.Done(key)
|
||||
|
||||
err := c.syncFn(key.(string))
|
||||
if err == nil {
|
||||
c.queue.Forget(key)
|
||||
return true
|
||||
}
|
||||
|
||||
utilruntime.HandleError(fmt.Errorf("%v failed with: %v", key, err))
|
||||
c.queue.AddRateLimited(key)
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
func (c *CRDFinalizer) enqueue(obj *apiextensions.CustomResourceDefinition) {
|
||||
key, err := cache.DeletionHandlingMetaNamespaceKeyFunc(obj)
|
||||
if err != nil {
|
||||
utilruntime.HandleError(fmt.Errorf("Couldn't get key for object %#v: %v", obj, err))
|
||||
return
|
||||
}
|
||||
|
||||
c.queue.Add(key)
|
||||
}
|
||||
|
||||
func (c *CRDFinalizer) addCustomResourceDefinition(obj interface{}) {
|
||||
castObj := obj.(*apiextensions.CustomResourceDefinition)
|
||||
// only queue deleted things
|
||||
if !castObj.DeletionTimestamp.IsZero() && apiextensions.CRDHasFinalizer(castObj, apiextensions.CustomResourceCleanupFinalizer) {
|
||||
c.enqueue(castObj)
|
||||
}
|
||||
}
|
||||
|
||||
func (c *CRDFinalizer) updateCustomResourceDefinition(oldObj, newObj interface{}) {
|
||||
oldCRD := oldObj.(*apiextensions.CustomResourceDefinition)
|
||||
newCRD := newObj.(*apiextensions.CustomResourceDefinition)
|
||||
// only queue deleted things that haven't been finalized by us
|
||||
if newCRD.DeletionTimestamp.IsZero() || !apiextensions.CRDHasFinalizer(newCRD, apiextensions.CustomResourceCleanupFinalizer) {
|
||||
return
|
||||
}
|
||||
|
||||
// always requeue resyncs just in case
|
||||
if oldCRD.ResourceVersion == newCRD.ResourceVersion {
|
||||
c.enqueue(newCRD)
|
||||
return
|
||||
}
|
||||
|
||||
// If the only difference is in the terminating condition, then there's no reason to requeue here. This controller
|
||||
// is likely to be the originator, so requeuing would hot-loop us. Failures are requeued by the workqueue directly.
|
||||
// This is a low traffic and scale resource, so the copy is terrible. It's not good, so better ideas
|
||||
// are welcome.
|
||||
oldCopy := oldCRD.DeepCopy()
|
||||
newCopy := newCRD.DeepCopy()
|
||||
oldCopy.ResourceVersion = ""
|
||||
newCopy.ResourceVersion = ""
|
||||
apiextensions.RemoveCRDCondition(oldCopy, apiextensions.Terminating)
|
||||
apiextensions.RemoveCRDCondition(newCopy, apiextensions.Terminating)
|
||||
|
||||
if !reflect.DeepEqual(oldCopy, newCopy) {
|
||||
c.enqueue(newCRD)
|
||||
}
|
||||
}
|
||||
374
vendor/k8s.io/apiextensions-apiserver/pkg/controller/status/naming_controller.go
generated
vendored
Normal file
374
vendor/k8s.io/apiextensions-apiserver/pkg/controller/status/naming_controller.go
generated
vendored
Normal file
@@ -0,0 +1,374 @@
|
||||
/*
|
||||
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 status
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/golang/glog"
|
||||
|
||||
"k8s.io/apimachinery/pkg/api/equality"
|
||||
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
utilerrors "k8s.io/apimachinery/pkg/util/errors"
|
||||
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
|
||||
"k8s.io/apimachinery/pkg/util/sets"
|
||||
"k8s.io/apimachinery/pkg/util/wait"
|
||||
"k8s.io/client-go/tools/cache"
|
||||
"k8s.io/client-go/util/workqueue"
|
||||
|
||||
"k8s.io/apiextensions-apiserver/pkg/apis/apiextensions"
|
||||
client "k8s.io/apiextensions-apiserver/pkg/client/clientset/internalclientset/typed/apiextensions/internalversion"
|
||||
informers "k8s.io/apiextensions-apiserver/pkg/client/informers/internalversion/apiextensions/internalversion"
|
||||
listers "k8s.io/apiextensions-apiserver/pkg/client/listers/apiextensions/internalversion"
|
||||
)
|
||||
|
||||
// This controller is reserving names. To avoid conflicts, be sure to run only one instance of the worker at a time.
|
||||
// This could eventually be lifted, but starting simple.
|
||||
type NamingConditionController struct {
|
||||
crdClient client.CustomResourceDefinitionsGetter
|
||||
|
||||
crdLister listers.CustomResourceDefinitionLister
|
||||
crdSynced cache.InformerSynced
|
||||
// crdMutationCache backs our lister and keeps track of committed updates to avoid racy
|
||||
// write/lookup cycles. It's got 100 slots by default, so it unlikely to overrun
|
||||
// TODO to revisit this if naming conflicts are found to occur in the wild
|
||||
crdMutationCache cache.MutationCache
|
||||
|
||||
// To allow injection for testing.
|
||||
syncFn func(key string) error
|
||||
|
||||
queue workqueue.RateLimitingInterface
|
||||
}
|
||||
|
||||
func NewNamingConditionController(
|
||||
crdInformer informers.CustomResourceDefinitionInformer,
|
||||
crdClient client.CustomResourceDefinitionsGetter,
|
||||
) *NamingConditionController {
|
||||
c := &NamingConditionController{
|
||||
crdClient: crdClient,
|
||||
crdLister: crdInformer.Lister(),
|
||||
crdSynced: crdInformer.Informer().HasSynced,
|
||||
queue: workqueue.NewNamedRateLimitingQueue(workqueue.DefaultControllerRateLimiter(), "CustomResourceDefinition-NamingConditionController"),
|
||||
}
|
||||
|
||||
informerIndexer := crdInformer.Informer().GetIndexer()
|
||||
c.crdMutationCache = cache.NewIntegerResourceVersionMutationCache(informerIndexer, informerIndexer, 60*time.Second, false)
|
||||
|
||||
crdInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{
|
||||
AddFunc: c.addCustomResourceDefinition,
|
||||
UpdateFunc: c.updateCustomResourceDefinition,
|
||||
DeleteFunc: c.deleteCustomResourceDefinition,
|
||||
})
|
||||
|
||||
c.syncFn = c.sync
|
||||
|
||||
return c
|
||||
}
|
||||
|
||||
func (c *NamingConditionController) getAcceptedNamesForGroup(group string) (allResources sets.String, allKinds sets.String) {
|
||||
allResources = sets.String{}
|
||||
allKinds = sets.String{}
|
||||
|
||||
list, err := c.crdLister.List(labels.Everything())
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
for _, curr := range list {
|
||||
if curr.Spec.Group != group {
|
||||
continue
|
||||
}
|
||||
|
||||
// for each item here, see if we have a mutation cache entry that is more recent
|
||||
// this makes sure that if we tight loop on update and run, our mutation cache will show
|
||||
// us the version of the objects we just updated to.
|
||||
item := curr
|
||||
obj, exists, err := c.crdMutationCache.GetByKey(curr.Name)
|
||||
if exists && err == nil {
|
||||
item = obj.(*apiextensions.CustomResourceDefinition)
|
||||
}
|
||||
|
||||
allResources.Insert(item.Status.AcceptedNames.Plural)
|
||||
allResources.Insert(item.Status.AcceptedNames.Singular)
|
||||
allResources.Insert(item.Status.AcceptedNames.ShortNames...)
|
||||
|
||||
allKinds.Insert(item.Status.AcceptedNames.Kind)
|
||||
allKinds.Insert(item.Status.AcceptedNames.ListKind)
|
||||
}
|
||||
|
||||
return allResources, allKinds
|
||||
}
|
||||
|
||||
func (c *NamingConditionController) calculateNamesAndConditions(in *apiextensions.CustomResourceDefinition) (apiextensions.CustomResourceDefinitionNames, apiextensions.CustomResourceDefinitionCondition, apiextensions.CustomResourceDefinitionCondition) {
|
||||
// Get the names that have already been claimed
|
||||
allResources, allKinds := c.getAcceptedNamesForGroup(in.Spec.Group)
|
||||
|
||||
namesAcceptedCondition := apiextensions.CustomResourceDefinitionCondition{
|
||||
Type: apiextensions.NamesAccepted,
|
||||
Status: apiextensions.ConditionUnknown,
|
||||
}
|
||||
|
||||
requestedNames := in.Spec.Names
|
||||
acceptedNames := in.Status.AcceptedNames
|
||||
newNames := in.Status.AcceptedNames
|
||||
|
||||
// Check each name for mismatches. If there's a mismatch between spec and status, then try to deconflict.
|
||||
// Continue on errors so that the status is the best match possible
|
||||
if err := equalToAcceptedOrFresh(requestedNames.Plural, acceptedNames.Plural, allResources); err != nil {
|
||||
namesAcceptedCondition.Status = apiextensions.ConditionFalse
|
||||
namesAcceptedCondition.Reason = "PluralConflict"
|
||||
namesAcceptedCondition.Message = err.Error()
|
||||
} else {
|
||||
newNames.Plural = requestedNames.Plural
|
||||
}
|
||||
if err := equalToAcceptedOrFresh(requestedNames.Singular, acceptedNames.Singular, allResources); err != nil {
|
||||
namesAcceptedCondition.Status = apiextensions.ConditionFalse
|
||||
namesAcceptedCondition.Reason = "SingularConflict"
|
||||
namesAcceptedCondition.Message = err.Error()
|
||||
} else {
|
||||
newNames.Singular = requestedNames.Singular
|
||||
}
|
||||
if !reflect.DeepEqual(requestedNames.ShortNames, acceptedNames.ShortNames) {
|
||||
errs := []error{}
|
||||
existingShortNames := sets.NewString(acceptedNames.ShortNames...)
|
||||
for _, shortName := range requestedNames.ShortNames {
|
||||
// if the shortname is already ours, then we're fine
|
||||
if existingShortNames.Has(shortName) {
|
||||
continue
|
||||
}
|
||||
if err := equalToAcceptedOrFresh(shortName, "", allResources); err != nil {
|
||||
errs = append(errs, err)
|
||||
}
|
||||
|
||||
}
|
||||
if err := utilerrors.NewAggregate(errs); err != nil {
|
||||
namesAcceptedCondition.Status = apiextensions.ConditionFalse
|
||||
namesAcceptedCondition.Reason = "ShortNamesConflict"
|
||||
namesAcceptedCondition.Message = err.Error()
|
||||
} else {
|
||||
newNames.ShortNames = requestedNames.ShortNames
|
||||
}
|
||||
}
|
||||
|
||||
if err := equalToAcceptedOrFresh(requestedNames.Kind, acceptedNames.Kind, allKinds); err != nil {
|
||||
namesAcceptedCondition.Status = apiextensions.ConditionFalse
|
||||
namesAcceptedCondition.Reason = "KindConflict"
|
||||
namesAcceptedCondition.Message = err.Error()
|
||||
} else {
|
||||
newNames.Kind = requestedNames.Kind
|
||||
}
|
||||
if err := equalToAcceptedOrFresh(requestedNames.ListKind, acceptedNames.ListKind, allKinds); err != nil {
|
||||
namesAcceptedCondition.Status = apiextensions.ConditionFalse
|
||||
namesAcceptedCondition.Reason = "ListKindConflict"
|
||||
namesAcceptedCondition.Message = err.Error()
|
||||
} else {
|
||||
newNames.ListKind = requestedNames.ListKind
|
||||
}
|
||||
|
||||
newNames.Categories = requestedNames.Categories
|
||||
|
||||
// if we haven't changed the condition, then our names must be good.
|
||||
if namesAcceptedCondition.Status == apiextensions.ConditionUnknown {
|
||||
namesAcceptedCondition.Status = apiextensions.ConditionTrue
|
||||
namesAcceptedCondition.Reason = "NoConflicts"
|
||||
namesAcceptedCondition.Message = "no conflicts found"
|
||||
}
|
||||
|
||||
// set EstablishedCondition initially to false, then set it to true in establishing controller.
|
||||
// The Establishing Controller will see the NamesAccepted condition when it arrives through the shared informer.
|
||||
// At that time the API endpoint handler will serve the endpoint, avoiding a race
|
||||
// which we had if we set Established to true here.
|
||||
establishedCondition := apiextensions.CustomResourceDefinitionCondition{
|
||||
Type: apiextensions.Established,
|
||||
Status: apiextensions.ConditionFalse,
|
||||
Reason: "NotAccepted",
|
||||
Message: "not all names are accepted",
|
||||
}
|
||||
if old := apiextensions.FindCRDCondition(in, apiextensions.Established); old != nil {
|
||||
establishedCondition = *old
|
||||
}
|
||||
if establishedCondition.Status != apiextensions.ConditionTrue && namesAcceptedCondition.Status == apiextensions.ConditionTrue {
|
||||
establishedCondition = apiextensions.CustomResourceDefinitionCondition{
|
||||
Type: apiextensions.Established,
|
||||
Status: apiextensions.ConditionFalse,
|
||||
Reason: "Installing",
|
||||
Message: "the initial names have been accepted",
|
||||
}
|
||||
}
|
||||
|
||||
return newNames, namesAcceptedCondition, establishedCondition
|
||||
}
|
||||
|
||||
func equalToAcceptedOrFresh(requestedName, acceptedName string, usedNames sets.String) error {
|
||||
if requestedName == acceptedName {
|
||||
return nil
|
||||
}
|
||||
if !usedNames.Has(requestedName) {
|
||||
return nil
|
||||
}
|
||||
|
||||
return fmt.Errorf("%q is already in use", requestedName)
|
||||
}
|
||||
|
||||
func (c *NamingConditionController) sync(key string) error {
|
||||
inCustomResourceDefinition, err := c.crdLister.Get(key)
|
||||
if apierrors.IsNotFound(err) {
|
||||
// CRD was deleted and has freed its names.
|
||||
// Reconsider all other CRDs in the same group.
|
||||
if err := c.requeueAllOtherGroupCRDs(key); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Skip checking names if Spec and Status names are same.
|
||||
if equality.Semantic.DeepEqual(inCustomResourceDefinition.Spec.Names, inCustomResourceDefinition.Status.AcceptedNames) {
|
||||
return nil
|
||||
}
|
||||
|
||||
acceptedNames, namingCondition, establishedCondition := c.calculateNamesAndConditions(inCustomResourceDefinition)
|
||||
|
||||
// nothing to do if accepted names and NamesAccepted condition didn't change
|
||||
if reflect.DeepEqual(inCustomResourceDefinition.Status.AcceptedNames, acceptedNames) &&
|
||||
apiextensions.IsCRDConditionEquivalent(&namingCondition, apiextensions.FindCRDCondition(inCustomResourceDefinition, apiextensions.NamesAccepted)) {
|
||||
return nil
|
||||
}
|
||||
|
||||
crd := inCustomResourceDefinition.DeepCopy()
|
||||
crd.Status.AcceptedNames = acceptedNames
|
||||
apiextensions.SetCRDCondition(crd, namingCondition)
|
||||
apiextensions.SetCRDCondition(crd, establishedCondition)
|
||||
|
||||
updatedObj, err := c.crdClient.CustomResourceDefinitions().UpdateStatus(crd)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// if the update was successful, go ahead and add the entry to the mutation cache
|
||||
c.crdMutationCache.Mutation(updatedObj)
|
||||
|
||||
// we updated our status, so we may be releasing a name. When this happens, we need to rekick everything in our group
|
||||
// if we fail to rekick, just return as normal. We'll get everything on a resync
|
||||
if err := c.requeueAllOtherGroupCRDs(key); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *NamingConditionController) Run(stopCh <-chan struct{}) {
|
||||
defer utilruntime.HandleCrash()
|
||||
defer c.queue.ShutDown()
|
||||
|
||||
glog.Infof("Starting NamingConditionController")
|
||||
defer glog.Infof("Shutting down NamingConditionController")
|
||||
|
||||
if !cache.WaitForCacheSync(stopCh, c.crdSynced) {
|
||||
return
|
||||
}
|
||||
|
||||
// only start one worker thread since its a slow moving API and the naming conflict resolution bits aren't thread-safe
|
||||
go wait.Until(c.runWorker, time.Second, stopCh)
|
||||
|
||||
<-stopCh
|
||||
}
|
||||
|
||||
func (c *NamingConditionController) runWorker() {
|
||||
for c.processNextWorkItem() {
|
||||
}
|
||||
}
|
||||
|
||||
// processNextWorkItem deals with one key off the queue. It returns false when it's time to quit.
|
||||
func (c *NamingConditionController) processNextWorkItem() bool {
|
||||
key, quit := c.queue.Get()
|
||||
if quit {
|
||||
return false
|
||||
}
|
||||
defer c.queue.Done(key)
|
||||
|
||||
err := c.syncFn(key.(string))
|
||||
if err == nil {
|
||||
c.queue.Forget(key)
|
||||
return true
|
||||
}
|
||||
|
||||
utilruntime.HandleError(fmt.Errorf("%v failed with: %v", key, err))
|
||||
c.queue.AddRateLimited(key)
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
func (c *NamingConditionController) enqueue(obj *apiextensions.CustomResourceDefinition) {
|
||||
key, err := cache.DeletionHandlingMetaNamespaceKeyFunc(obj)
|
||||
if err != nil {
|
||||
utilruntime.HandleError(fmt.Errorf("Couldn't get key for object %#v: %v", obj, err))
|
||||
return
|
||||
}
|
||||
|
||||
c.queue.Add(key)
|
||||
}
|
||||
|
||||
func (c *NamingConditionController) addCustomResourceDefinition(obj interface{}) {
|
||||
castObj := obj.(*apiextensions.CustomResourceDefinition)
|
||||
glog.V(4).Infof("Adding %s", castObj.Name)
|
||||
c.enqueue(castObj)
|
||||
}
|
||||
|
||||
func (c *NamingConditionController) updateCustomResourceDefinition(obj, _ interface{}) {
|
||||
castObj := obj.(*apiextensions.CustomResourceDefinition)
|
||||
glog.V(4).Infof("Updating %s", castObj.Name)
|
||||
c.enqueue(castObj)
|
||||
}
|
||||
|
||||
func (c *NamingConditionController) deleteCustomResourceDefinition(obj interface{}) {
|
||||
castObj, ok := obj.(*apiextensions.CustomResourceDefinition)
|
||||
if !ok {
|
||||
tombstone, ok := obj.(cache.DeletedFinalStateUnknown)
|
||||
if !ok {
|
||||
glog.Errorf("Couldn't get object from tombstone %#v", obj)
|
||||
return
|
||||
}
|
||||
castObj, ok = tombstone.Obj.(*apiextensions.CustomResourceDefinition)
|
||||
if !ok {
|
||||
glog.Errorf("Tombstone contained object that is not expected %#v", obj)
|
||||
return
|
||||
}
|
||||
}
|
||||
glog.V(4).Infof("Deleting %q", castObj.Name)
|
||||
c.enqueue(castObj)
|
||||
}
|
||||
|
||||
func (c *NamingConditionController) requeueAllOtherGroupCRDs(name string) error {
|
||||
pluralGroup := strings.SplitN(name, ".", 2)
|
||||
list, err := c.crdLister.List(labels.Everything())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, curr := range list {
|
||||
if curr.Spec.Group == pluralGroup[1] && curr.Name != name {
|
||||
c.queue.Add(curr.Name)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
344
vendor/k8s.io/apiextensions-apiserver/pkg/controller/status/naming_controller_test.go
generated
vendored
Normal file
344
vendor/k8s.io/apiextensions-apiserver/pkg/controller/status/naming_controller_test.go
generated
vendored
Normal file
@@ -0,0 +1,344 @@
|
||||
/*
|
||||
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 status
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"k8s.io/apiextensions-apiserver/pkg/apis/apiextensions"
|
||||
listers "k8s.io/apiextensions-apiserver/pkg/client/listers/apiextensions/internalversion"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/client-go/tools/cache"
|
||||
)
|
||||
|
||||
type crdBuilder struct {
|
||||
curr apiextensions.CustomResourceDefinition
|
||||
}
|
||||
|
||||
func newCRD(name string) *crdBuilder {
|
||||
tokens := strings.SplitN(name, ".", 2)
|
||||
return &crdBuilder{
|
||||
curr: apiextensions.CustomResourceDefinition{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: name},
|
||||
Spec: apiextensions.CustomResourceDefinitionSpec{
|
||||
Group: tokens[1],
|
||||
Names: apiextensions.CustomResourceDefinitionNames{
|
||||
Plural: tokens[0],
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (b *crdBuilder) SpecNames(plural, singular, kind, listKind string, shortNames ...string) *crdBuilder {
|
||||
b.curr.Spec.Names.Plural = plural
|
||||
b.curr.Spec.Names.Singular = singular
|
||||
b.curr.Spec.Names.Kind = kind
|
||||
b.curr.Spec.Names.ListKind = listKind
|
||||
b.curr.Spec.Names.ShortNames = shortNames
|
||||
|
||||
return b
|
||||
}
|
||||
|
||||
func (b *crdBuilder) StatusNames(plural, singular, kind, listKind string, shortNames ...string) *crdBuilder {
|
||||
b.curr.Status.AcceptedNames.Plural = plural
|
||||
b.curr.Status.AcceptedNames.Singular = singular
|
||||
b.curr.Status.AcceptedNames.Kind = kind
|
||||
b.curr.Status.AcceptedNames.ListKind = listKind
|
||||
b.curr.Status.AcceptedNames.ShortNames = shortNames
|
||||
|
||||
return b
|
||||
}
|
||||
|
||||
func (b *crdBuilder) Condition(c apiextensions.CustomResourceDefinitionCondition) *crdBuilder {
|
||||
b.curr.Status.Conditions = append(b.curr.Status.Conditions, c)
|
||||
|
||||
return b
|
||||
}
|
||||
|
||||
func names(plural, singular, kind, listKind string, shortNames ...string) apiextensions.CustomResourceDefinitionNames {
|
||||
ret := apiextensions.CustomResourceDefinitionNames{
|
||||
Plural: plural,
|
||||
Singular: singular,
|
||||
Kind: kind,
|
||||
ListKind: listKind,
|
||||
ShortNames: shortNames,
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
func (b *crdBuilder) NewOrDie() *apiextensions.CustomResourceDefinition {
|
||||
return &b.curr
|
||||
}
|
||||
|
||||
var acceptedCondition = apiextensions.CustomResourceDefinitionCondition{
|
||||
Type: apiextensions.NamesAccepted,
|
||||
Status: apiextensions.ConditionTrue,
|
||||
Reason: "NoConflicts",
|
||||
Message: "no conflicts found",
|
||||
}
|
||||
|
||||
var notAcceptedCondition = apiextensions.CustomResourceDefinitionCondition{
|
||||
Type: apiextensions.NamesAccepted,
|
||||
Status: apiextensions.ConditionFalse,
|
||||
Reason: "NotAccepted",
|
||||
Message: "not all names are accepted",
|
||||
}
|
||||
|
||||
var installingCondition = apiextensions.CustomResourceDefinitionCondition{
|
||||
Type: apiextensions.Established,
|
||||
Status: apiextensions.ConditionFalse,
|
||||
Reason: "Installing",
|
||||
Message: "the initial names have been accepted",
|
||||
}
|
||||
|
||||
var notEstablishedCondition = apiextensions.CustomResourceDefinitionCondition{
|
||||
Type: apiextensions.Established,
|
||||
Status: apiextensions.ConditionFalse,
|
||||
Reason: "NotAccepted",
|
||||
Message: "not all names are accepted",
|
||||
}
|
||||
|
||||
func nameConflictCondition(reason, message string) apiextensions.CustomResourceDefinitionCondition {
|
||||
return apiextensions.CustomResourceDefinitionCondition{
|
||||
Type: apiextensions.NamesAccepted,
|
||||
Status: apiextensions.ConditionFalse,
|
||||
Reason: reason,
|
||||
Message: message,
|
||||
}
|
||||
}
|
||||
|
||||
func TestSync(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
|
||||
in *apiextensions.CustomResourceDefinition
|
||||
existing []*apiextensions.CustomResourceDefinition
|
||||
expectedNames apiextensions.CustomResourceDefinitionNames
|
||||
expectedNameConflictCondition apiextensions.CustomResourceDefinitionCondition
|
||||
expectedEstablishedCondition apiextensions.CustomResourceDefinitionCondition
|
||||
}{
|
||||
{
|
||||
name: "first resource",
|
||||
in: newCRD("alfa.bravo.com").NewOrDie(),
|
||||
existing: []*apiextensions.CustomResourceDefinition{},
|
||||
expectedNames: apiextensions.CustomResourceDefinitionNames{
|
||||
Plural: "alfa",
|
||||
},
|
||||
expectedNameConflictCondition: acceptedCondition,
|
||||
expectedEstablishedCondition: installingCondition,
|
||||
},
|
||||
{
|
||||
name: "different groups",
|
||||
in: newCRD("alfa.bravo.com").SpecNames("alfa", "delta-singular", "echo-kind", "foxtrot-listkind", "golf-shortname-1", "hotel-shortname-2").NewOrDie(),
|
||||
existing: []*apiextensions.CustomResourceDefinition{
|
||||
newCRD("alfa.charlie.com").StatusNames("alfa", "delta-singular", "echo-kind", "foxtrot-listkind", "golf-shortname-1", "hotel-shortname-2").NewOrDie(),
|
||||
},
|
||||
expectedNames: names("alfa", "delta-singular", "echo-kind", "foxtrot-listkind", "golf-shortname-1", "hotel-shortname-2"),
|
||||
expectedNameConflictCondition: acceptedCondition,
|
||||
expectedEstablishedCondition: installingCondition,
|
||||
},
|
||||
{
|
||||
name: "conflict plural to singular",
|
||||
in: newCRD("alfa.bravo.com").SpecNames("alfa", "delta-singular", "echo-kind", "foxtrot-listkind", "golf-shortname-1", "hotel-shortname-2").NewOrDie(),
|
||||
existing: []*apiextensions.CustomResourceDefinition{
|
||||
newCRD("india.bravo.com").StatusNames("india", "alfa", "", "").NewOrDie(),
|
||||
},
|
||||
expectedNames: names("", "delta-singular", "echo-kind", "foxtrot-listkind", "golf-shortname-1", "hotel-shortname-2"),
|
||||
expectedNameConflictCondition: nameConflictCondition("PluralConflict", `"alfa" is already in use`),
|
||||
expectedEstablishedCondition: notEstablishedCondition,
|
||||
},
|
||||
{
|
||||
name: "conflict singular to shortName",
|
||||
in: newCRD("alfa.bravo.com").SpecNames("alfa", "delta-singular", "echo-kind", "foxtrot-listkind", "golf-shortname-1", "hotel-shortname-2").NewOrDie(),
|
||||
existing: []*apiextensions.CustomResourceDefinition{
|
||||
newCRD("india.bravo.com").StatusNames("india", "indias", "", "", "delta-singular").NewOrDie(),
|
||||
},
|
||||
expectedNames: names("alfa", "", "echo-kind", "foxtrot-listkind", "golf-shortname-1", "hotel-shortname-2"),
|
||||
expectedNameConflictCondition: nameConflictCondition("SingularConflict", `"delta-singular" is already in use`),
|
||||
expectedEstablishedCondition: notEstablishedCondition,
|
||||
},
|
||||
{
|
||||
name: "conflict on shortName to shortName",
|
||||
in: newCRD("alfa.bravo.com").SpecNames("alfa", "delta-singular", "echo-kind", "foxtrot-listkind", "golf-shortname-1", "hotel-shortname-2").NewOrDie(),
|
||||
existing: []*apiextensions.CustomResourceDefinition{
|
||||
newCRD("india.bravo.com").StatusNames("india", "indias", "", "", "hotel-shortname-2").NewOrDie(),
|
||||
},
|
||||
expectedNames: names("alfa", "delta-singular", "echo-kind", "foxtrot-listkind"),
|
||||
expectedNameConflictCondition: nameConflictCondition("ShortNamesConflict", `"hotel-shortname-2" is already in use`),
|
||||
expectedEstablishedCondition: notEstablishedCondition,
|
||||
},
|
||||
{
|
||||
name: "conflict on kind to listkind",
|
||||
in: newCRD("alfa.bravo.com").SpecNames("alfa", "delta-singular", "echo-kind", "foxtrot-listkind", "golf-shortname-1", "hotel-shortname-2").NewOrDie(),
|
||||
existing: []*apiextensions.CustomResourceDefinition{
|
||||
newCRD("india.bravo.com").StatusNames("india", "indias", "", "echo-kind").NewOrDie(),
|
||||
},
|
||||
expectedNames: names("alfa", "delta-singular", "", "foxtrot-listkind", "golf-shortname-1", "hotel-shortname-2"),
|
||||
expectedNameConflictCondition: nameConflictCondition("KindConflict", `"echo-kind" is already in use`),
|
||||
expectedEstablishedCondition: notEstablishedCondition,
|
||||
},
|
||||
{
|
||||
name: "conflict on listkind to kind",
|
||||
in: newCRD("alfa.bravo.com").SpecNames("alfa", "delta-singular", "echo-kind", "foxtrot-listkind", "golf-shortname-1", "hotel-shortname-2").NewOrDie(),
|
||||
existing: []*apiextensions.CustomResourceDefinition{
|
||||
newCRD("india.bravo.com").StatusNames("india", "indias", "foxtrot-listkind", "").NewOrDie(),
|
||||
},
|
||||
expectedNames: names("alfa", "delta-singular", "echo-kind", "", "golf-shortname-1", "hotel-shortname-2"),
|
||||
expectedNameConflictCondition: nameConflictCondition("ListKindConflict", `"foxtrot-listkind" is already in use`),
|
||||
expectedEstablishedCondition: notEstablishedCondition,
|
||||
},
|
||||
{
|
||||
name: "no conflict on resource and kind",
|
||||
in: newCRD("alfa.bravo.com").SpecNames("alfa", "delta-singular", "echo-kind", "foxtrot-listkind", "golf-shortname-1", "hotel-shortname-2").NewOrDie(),
|
||||
existing: []*apiextensions.CustomResourceDefinition{
|
||||
newCRD("india.bravo.com").StatusNames("india", "echo-kind", "", "").NewOrDie(),
|
||||
},
|
||||
expectedNames: names("alfa", "delta-singular", "echo-kind", "foxtrot-listkind", "golf-shortname-1", "hotel-shortname-2"),
|
||||
expectedNameConflictCondition: acceptedCondition,
|
||||
expectedEstablishedCondition: installingCondition,
|
||||
},
|
||||
{
|
||||
name: "merge on conflicts",
|
||||
in: newCRD("alfa.bravo.com").
|
||||
SpecNames("alfa", "delta-singular", "echo-kind", "foxtrot-listkind", "golf-shortname-1", "hotel-shortname-2").
|
||||
StatusNames("zulu", "yankee-singular", "xray-kind", "whiskey-listkind", "victor-shortname-1", "uniform-shortname-2").
|
||||
NewOrDie(),
|
||||
existing: []*apiextensions.CustomResourceDefinition{
|
||||
newCRD("india.bravo.com").StatusNames("india", "indias", "foxtrot-listkind", "", "delta-singular").NewOrDie(),
|
||||
},
|
||||
expectedNames: names("alfa", "yankee-singular", "echo-kind", "whiskey-listkind", "golf-shortname-1", "hotel-shortname-2"),
|
||||
expectedNameConflictCondition: nameConflictCondition("ListKindConflict", `"foxtrot-listkind" is already in use`),
|
||||
expectedEstablishedCondition: notEstablishedCondition,
|
||||
},
|
||||
{
|
||||
name: "merge on conflicts shortNames as one",
|
||||
in: newCRD("alfa.bravo.com").
|
||||
SpecNames("alfa", "delta-singular", "echo-kind", "foxtrot-listkind", "golf-shortname-1", "hotel-shortname-2").
|
||||
StatusNames("zulu", "yankee-singular", "xray-kind", "whiskey-listkind", "victor-shortname-1", "uniform-shortname-2").
|
||||
NewOrDie(),
|
||||
existing: []*apiextensions.CustomResourceDefinition{
|
||||
newCRD("india.bravo.com").StatusNames("india", "indias", "foxtrot-listkind", "", "delta-singular", "golf-shortname-1").NewOrDie(),
|
||||
},
|
||||
expectedNames: names("alfa", "yankee-singular", "echo-kind", "whiskey-listkind", "victor-shortname-1", "uniform-shortname-2"),
|
||||
expectedNameConflictCondition: nameConflictCondition("ListKindConflict", `"foxtrot-listkind" is already in use`),
|
||||
expectedEstablishedCondition: notEstablishedCondition,
|
||||
},
|
||||
{
|
||||
name: "no conflicts on self",
|
||||
in: newCRD("alfa.bravo.com").
|
||||
SpecNames("alfa", "delta-singular", "echo-kind", "foxtrot-listkind", "golf-shortname-1", "hotel-shortname-2").
|
||||
StatusNames("alfa", "delta-singular", "echo-kind", "foxtrot-listkind", "golf-shortname-1", "hotel-shortname-2").
|
||||
NewOrDie(),
|
||||
existing: []*apiextensions.CustomResourceDefinition{
|
||||
newCRD("alfa.bravo.com").
|
||||
SpecNames("alfa", "delta-singular", "echo-kind", "foxtrot-listkind", "golf-shortname-1", "hotel-shortname-2").
|
||||
StatusNames("alfa", "delta-singular", "echo-kind", "foxtrot-listkind", "golf-shortname-1", "hotel-shortname-2").
|
||||
NewOrDie(),
|
||||
},
|
||||
expectedNames: names("alfa", "delta-singular", "echo-kind", "foxtrot-listkind", "golf-shortname-1", "hotel-shortname-2"),
|
||||
expectedNameConflictCondition: acceptedCondition,
|
||||
expectedEstablishedCondition: installingCondition,
|
||||
},
|
||||
{
|
||||
name: "no conflicts on self, remove shortname",
|
||||
in: newCRD("alfa.bravo.com").
|
||||
SpecNames("alfa", "delta-singular", "echo-kind", "foxtrot-listkind", "golf-shortname-1").
|
||||
StatusNames("alfa", "delta-singular", "echo-kind", "foxtrot-listkind", "golf-shortname-1", "hotel-shortname-2").
|
||||
NewOrDie(),
|
||||
existing: []*apiextensions.CustomResourceDefinition{
|
||||
newCRD("alfa.bravo.com").
|
||||
SpecNames("alfa", "delta-singular", "echo-kind", "foxtrot-listkind", "golf-shortname-1", "hotel-shortname-2").
|
||||
StatusNames("alfa", "delta-singular", "echo-kind", "foxtrot-listkind", "golf-shortname-1", "hotel-shortname-2").
|
||||
NewOrDie(),
|
||||
},
|
||||
expectedNames: names("alfa", "delta-singular", "echo-kind", "foxtrot-listkind", "golf-shortname-1"),
|
||||
expectedNameConflictCondition: acceptedCondition,
|
||||
expectedEstablishedCondition: installingCondition,
|
||||
},
|
||||
{
|
||||
name: "installing before with true condition",
|
||||
in: newCRD("alfa.bravo.com").Condition(acceptedCondition).NewOrDie(),
|
||||
existing: []*apiextensions.CustomResourceDefinition{},
|
||||
expectedNames: apiextensions.CustomResourceDefinitionNames{
|
||||
Plural: "alfa",
|
||||
},
|
||||
expectedNameConflictCondition: acceptedCondition,
|
||||
expectedEstablishedCondition: installingCondition,
|
||||
},
|
||||
{
|
||||
name: "not installing before with false condition",
|
||||
in: newCRD("alfa.bravo.com").Condition(notAcceptedCondition).NewOrDie(),
|
||||
existing: []*apiextensions.CustomResourceDefinition{},
|
||||
expectedNames: apiextensions.CustomResourceDefinitionNames{
|
||||
Plural: "alfa",
|
||||
},
|
||||
expectedNameConflictCondition: acceptedCondition,
|
||||
expectedEstablishedCondition: installingCondition,
|
||||
},
|
||||
{
|
||||
name: "conflicting, installing before with true condition",
|
||||
in: newCRD("alfa.bravo.com").SpecNames("alfa", "delta-singular", "echo-kind", "foxtrot-listkind", "golf-shortname-1", "hotel-shortname-2").
|
||||
Condition(acceptedCondition).
|
||||
NewOrDie(),
|
||||
existing: []*apiextensions.CustomResourceDefinition{
|
||||
newCRD("india.bravo.com").StatusNames("india", "alfa", "", "").NewOrDie(),
|
||||
},
|
||||
expectedNames: names("", "delta-singular", "echo-kind", "foxtrot-listkind", "golf-shortname-1", "hotel-shortname-2"),
|
||||
expectedNameConflictCondition: nameConflictCondition("PluralConflict", `"alfa" is already in use`),
|
||||
expectedEstablishedCondition: notEstablishedCondition,
|
||||
},
|
||||
{
|
||||
name: "conflicting, not installing before with false condition",
|
||||
in: newCRD("alfa.bravo.com").SpecNames("alfa", "delta-singular", "echo-kind", "foxtrot-listkind", "golf-shortname-1", "hotel-shortname-2").
|
||||
Condition(notAcceptedCondition).
|
||||
NewOrDie(),
|
||||
existing: []*apiextensions.CustomResourceDefinition{
|
||||
newCRD("india.bravo.com").StatusNames("india", "alfa", "", "").NewOrDie(),
|
||||
},
|
||||
expectedNames: names("", "delta-singular", "echo-kind", "foxtrot-listkind", "golf-shortname-1", "hotel-shortname-2"),
|
||||
expectedNameConflictCondition: nameConflictCondition("PluralConflict", `"alfa" is already in use`),
|
||||
expectedEstablishedCondition: notEstablishedCondition,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range tests {
|
||||
crdIndexer := cache.NewIndexer(cache.MetaNamespaceKeyFunc, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc})
|
||||
for _, obj := range tc.existing {
|
||||
crdIndexer.Add(obj)
|
||||
}
|
||||
|
||||
c := NamingConditionController{
|
||||
crdLister: listers.NewCustomResourceDefinitionLister(crdIndexer),
|
||||
crdMutationCache: cache.NewIntegerResourceVersionMutationCache(crdIndexer, crdIndexer, 60*time.Second, false),
|
||||
}
|
||||
actualNames, actualNameConflictCondition, establishedCondition := c.calculateNamesAndConditions(tc.in)
|
||||
|
||||
if e, a := tc.expectedNames, actualNames; !reflect.DeepEqual(e, a) {
|
||||
t.Errorf("%v expected %v, got %#v", tc.name, e, a)
|
||||
}
|
||||
if e, a := tc.expectedNameConflictCondition, actualNameConflictCondition; !apiextensions.IsCRDConditionEquivalent(&e, &a) {
|
||||
t.Errorf("%v expected %v, got %v", tc.name, e, a)
|
||||
}
|
||||
if e, a := tc.expectedEstablishedCondition, establishedCondition; !apiextensions.IsCRDConditionEquivalent(&e, &a) {
|
||||
t.Errorf("%v expected %v, got %v", tc.name, e, a)
|
||||
}
|
||||
}
|
||||
}
|
||||
67
vendor/k8s.io/apiextensions-apiserver/pkg/crdserverscheme/unstructured.go
generated
vendored
Normal file
67
vendor/k8s.io/apiextensions-apiserver/pkg/crdserverscheme/unstructured.go
generated
vendored
Normal file
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
Copyright 2016 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 crdserverscheme
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
)
|
||||
|
||||
// UnstructuredObjectTyper provides a runtime.ObjectTyper implementation for
|
||||
// runtime.Unstructured object based on discovery information.
|
||||
type UnstructuredObjectTyper struct {
|
||||
}
|
||||
|
||||
// NewUnstructuredObjectTyper returns a runtime.ObjectTyper for
|
||||
// unstructured objects based on discovery information. It accepts a list of fallback typers
|
||||
// for handling objects that are not runtime.Unstructured. It does not delegate the Recognizes
|
||||
// check, only ObjectKinds.
|
||||
// TODO this only works for the apiextensions server and doesn't recognize any types. Move to point of use.
|
||||
func NewUnstructuredObjectTyper() *UnstructuredObjectTyper {
|
||||
dot := &UnstructuredObjectTyper{}
|
||||
return dot
|
||||
}
|
||||
|
||||
// ObjectKinds returns a slice of one element with the group,version,kind of the
|
||||
// provided object, or an error if the object is not runtime.Unstructured or
|
||||
// has no group,version,kind information. unversionedType will always be false
|
||||
// because runtime.Unstructured object should always have group,version,kind
|
||||
// information set.
|
||||
func (d *UnstructuredObjectTyper) ObjectKinds(obj runtime.Object) (gvks []schema.GroupVersionKind, unversionedType bool, err error) {
|
||||
if _, ok := obj.(runtime.Unstructured); ok {
|
||||
gvk := obj.GetObjectKind().GroupVersionKind()
|
||||
if len(gvk.Kind) == 0 {
|
||||
return nil, false, runtime.NewMissingKindErr("object has no kind field ")
|
||||
}
|
||||
if len(gvk.Version) == 0 {
|
||||
return nil, false, runtime.NewMissingVersionErr("object has no apiVersion field")
|
||||
}
|
||||
return []schema.GroupVersionKind{gvk}, false, nil
|
||||
}
|
||||
|
||||
return nil, false, runtime.NewNotRegisteredErrForType("crdserverscheme.UnstructuredObjectTyper", reflect.TypeOf(obj))
|
||||
}
|
||||
|
||||
// Recognizes returns true if the provided group,version,kind was in the
|
||||
// discovery information.
|
||||
func (d *UnstructuredObjectTyper) Recognizes(gvk schema.GroupVersionKind) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
var _ runtime.ObjectTyper = &UnstructuredObjectTyper{}
|
||||
2
vendor/k8s.io/apiextensions-apiserver/pkg/features/OWNERS
generated
vendored
Normal file
2
vendor/k8s.io/apiextensions-apiserver/pkg/features/OWNERS
generated
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
approvers:
|
||||
- feature-approvers
|
||||
55
vendor/k8s.io/apiextensions-apiserver/pkg/features/kube_features.go
generated
vendored
Normal file
55
vendor/k8s.io/apiextensions-apiserver/pkg/features/kube_features.go
generated
vendored
Normal file
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
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 features
|
||||
|
||||
import (
|
||||
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||
)
|
||||
|
||||
const (
|
||||
// Every feature gate should add method here following this template:
|
||||
//
|
||||
// // owner: @username
|
||||
// // alpha: v1.4
|
||||
// MyFeature() bool
|
||||
|
||||
// owner: @sttts, @nikhita
|
||||
// alpha: v1.8
|
||||
// beta: v1.9
|
||||
//
|
||||
// CustomResourceValidation is a list of validation methods for CustomResources
|
||||
CustomResourceValidation utilfeature.Feature = "CustomResourceValidation"
|
||||
|
||||
// owner: @sttts, @nikhita
|
||||
// alpha: v1.10
|
||||
// beta: v1.11
|
||||
//
|
||||
// CustomResourceSubresources defines the subresources for CustomResources
|
||||
CustomResourceSubresources utilfeature.Feature = "CustomResourceSubresources"
|
||||
)
|
||||
|
||||
func init() {
|
||||
utilfeature.DefaultFeatureGate.Add(defaultKubernetesFeatureGates)
|
||||
}
|
||||
|
||||
// defaultKubernetesFeatureGates consists of all known Kubernetes-specific feature keys.
|
||||
// To add a new feature, define a key for it above and add it here. The features will be
|
||||
// available throughout Kubernetes binaries.
|
||||
var defaultKubernetesFeatureGates = map[utilfeature.Feature]utilfeature.FeatureSpec{
|
||||
CustomResourceValidation: {Default: true, PreRelease: utilfeature.Beta},
|
||||
CustomResourceSubresources: {Default: true, PreRelease: utilfeature.Beta},
|
||||
}
|
||||
323
vendor/k8s.io/apiextensions-apiserver/pkg/registry/customresource/etcd.go
generated
vendored
Normal file
323
vendor/k8s.io/apiextensions-apiserver/pkg/registry/customresource/etcd.go
generated
vendored
Normal file
@@ -0,0 +1,323 @@
|
||||
/*
|
||||
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 customresource
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
autoscalingv1 "k8s.io/api/autoscaling/v1"
|
||||
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
||||
metainternalversion "k8s.io/apimachinery/pkg/apis/meta/internalversion"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"k8s.io/apiserver/pkg/registry/generic"
|
||||
genericregistry "k8s.io/apiserver/pkg/registry/generic/registry"
|
||||
"k8s.io/apiserver/pkg/registry/rest"
|
||||
)
|
||||
|
||||
// CustomResourceStorage includes dummy storage for CustomResources, and their Status and Scale subresources.
|
||||
type CustomResourceStorage struct {
|
||||
CustomResource *REST
|
||||
Status *StatusREST
|
||||
Scale *ScaleREST
|
||||
}
|
||||
|
||||
func NewStorage(resource schema.GroupResource, listKind schema.GroupVersionKind, strategy customResourceStrategy, optsGetter generic.RESTOptionsGetter, categories []string, tableConvertor rest.TableConvertor) CustomResourceStorage {
|
||||
customResourceREST, customResourceStatusREST := newREST(resource, listKind, strategy, optsGetter, categories, tableConvertor)
|
||||
customResourceRegistry := NewRegistry(customResourceREST)
|
||||
|
||||
s := CustomResourceStorage{
|
||||
CustomResource: customResourceREST,
|
||||
}
|
||||
|
||||
if strategy.status != nil {
|
||||
s.Status = customResourceStatusREST
|
||||
}
|
||||
|
||||
if scale := strategy.scale; scale != nil {
|
||||
var labelSelectorPath string
|
||||
if scale.LabelSelectorPath != nil {
|
||||
labelSelectorPath = *scale.LabelSelectorPath
|
||||
}
|
||||
|
||||
s.Scale = &ScaleREST{
|
||||
registry: customResourceRegistry,
|
||||
specReplicasPath: scale.SpecReplicasPath,
|
||||
statusReplicasPath: scale.StatusReplicasPath,
|
||||
labelSelectorPath: labelSelectorPath,
|
||||
}
|
||||
}
|
||||
|
||||
return s
|
||||
}
|
||||
|
||||
// REST implements a RESTStorage for API services against etcd
|
||||
type REST struct {
|
||||
*genericregistry.Store
|
||||
categories []string
|
||||
}
|
||||
|
||||
// newREST returns a RESTStorage object that will work against API services.
|
||||
func newREST(resource schema.GroupResource, listKind schema.GroupVersionKind, strategy customResourceStrategy, optsGetter generic.RESTOptionsGetter, categories []string, tableConvertor rest.TableConvertor) (*REST, *StatusREST) {
|
||||
store := &genericregistry.Store{
|
||||
NewFunc: func() runtime.Object { return &unstructured.Unstructured{} },
|
||||
NewListFunc: func() runtime.Object {
|
||||
// lists are never stored, only manufactured, so stomp in the right kind
|
||||
ret := &unstructured.UnstructuredList{}
|
||||
ret.SetGroupVersionKind(listKind)
|
||||
return ret
|
||||
},
|
||||
PredicateFunc: strategy.MatchCustomResourceDefinitionStorage,
|
||||
DefaultQualifiedResource: resource,
|
||||
|
||||
CreateStrategy: strategy,
|
||||
UpdateStrategy: strategy,
|
||||
DeleteStrategy: strategy,
|
||||
|
||||
TableConvertor: tableConvertor,
|
||||
}
|
||||
options := &generic.StoreOptions{RESTOptions: optsGetter, AttrFunc: strategy.GetAttrs}
|
||||
if err := store.CompleteWithOptions(options); err != nil {
|
||||
panic(err) // TODO: Propagate error up
|
||||
}
|
||||
|
||||
statusStore := *store
|
||||
statusStore.UpdateStrategy = NewStatusStrategy(strategy)
|
||||
return &REST{store, categories}, &StatusREST{store: &statusStore}
|
||||
}
|
||||
|
||||
// Implement CategoriesProvider
|
||||
var _ rest.CategoriesProvider = &REST{}
|
||||
|
||||
// List returns a list of items matching labels and field according to the store's PredicateFunc.
|
||||
func (e *REST) List(ctx context.Context, options *metainternalversion.ListOptions) (runtime.Object, error) {
|
||||
l, err := e.Store.List(ctx, options)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Shallow copy ObjectMeta in returned list for each item. Native types have `Items []Item` fields and therefore
|
||||
// implicitly shallow copy ObjectMeta. The generic store sets the self-link for each item. So this is necessary
|
||||
// to avoid mutation of the objects from the cache.
|
||||
if ul, ok := l.(*unstructured.UnstructuredList); ok {
|
||||
for i := range ul.Items {
|
||||
shallowCopyObjectMeta(&ul.Items[i])
|
||||
}
|
||||
}
|
||||
|
||||
return l, nil
|
||||
}
|
||||
|
||||
func (r *REST) Get(ctx context.Context, name string, options *metav1.GetOptions) (runtime.Object, error) {
|
||||
o, err := r.Store.Get(ctx, name, options)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if u, ok := o.(*unstructured.Unstructured); ok {
|
||||
shallowCopyObjectMeta(u)
|
||||
}
|
||||
return o, nil
|
||||
}
|
||||
|
||||
func shallowCopyObjectMeta(u runtime.Unstructured) {
|
||||
obj := shallowMapDeepCopy(u.UnstructuredContent())
|
||||
if metadata, ok := obj["metadata"]; ok {
|
||||
if metadata, ok := metadata.(map[string]interface{}); ok {
|
||||
obj["metadata"] = shallowMapDeepCopy(metadata)
|
||||
u.SetUnstructuredContent(obj)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func shallowMapDeepCopy(in map[string]interface{}) map[string]interface{} {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
out := make(map[string]interface{}, len(in))
|
||||
for k, v := range in {
|
||||
out[k] = v
|
||||
}
|
||||
|
||||
return out
|
||||
}
|
||||
|
||||
// Categories implements the CategoriesProvider interface. Returns a list of categories a resource is part of.
|
||||
func (r *REST) Categories() []string {
|
||||
return r.categories
|
||||
}
|
||||
|
||||
// StatusREST implements the REST endpoint for changing the status of a CustomResource
|
||||
type StatusREST struct {
|
||||
store *genericregistry.Store
|
||||
}
|
||||
|
||||
var _ = rest.Patcher(&StatusREST{})
|
||||
|
||||
func (r *StatusREST) New() runtime.Object {
|
||||
return &unstructured.Unstructured{}
|
||||
}
|
||||
|
||||
// Get retrieves the object from the storage. It is required to support Patch.
|
||||
func (r *StatusREST) Get(ctx context.Context, name string, options *metav1.GetOptions) (runtime.Object, error) {
|
||||
return r.store.Get(ctx, name, options)
|
||||
}
|
||||
|
||||
// Update alters the status subset of an object.
|
||||
func (r *StatusREST) Update(ctx context.Context, name string, objInfo rest.UpdatedObjectInfo, createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc, forceAllowCreate bool) (runtime.Object, bool, error) {
|
||||
// We are explicitly setting forceAllowCreate to false in the call to the underlying storage because
|
||||
// subresources should never allow create on update.
|
||||
return r.store.Update(ctx, name, objInfo, createValidation, updateValidation, false)
|
||||
}
|
||||
|
||||
type ScaleREST struct {
|
||||
registry Registry
|
||||
specReplicasPath string
|
||||
statusReplicasPath string
|
||||
labelSelectorPath string
|
||||
}
|
||||
|
||||
// ScaleREST implements Patcher
|
||||
var _ = rest.Patcher(&ScaleREST{})
|
||||
var _ = rest.GroupVersionKindProvider(&ScaleREST{})
|
||||
|
||||
func (r *ScaleREST) GroupVersionKind(containingGV schema.GroupVersion) schema.GroupVersionKind {
|
||||
return autoscalingv1.SchemeGroupVersion.WithKind("Scale")
|
||||
}
|
||||
|
||||
// New creates a new Scale object
|
||||
func (r *ScaleREST) New() runtime.Object {
|
||||
return &autoscalingv1.Scale{}
|
||||
}
|
||||
|
||||
func (r *ScaleREST) Get(ctx context.Context, name string, options *metav1.GetOptions) (runtime.Object, error) {
|
||||
cr, err := r.registry.GetCustomResource(ctx, name, options)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
scaleObject, replicasFound, err := scaleFromCustomResource(cr, r.specReplicasPath, r.statusReplicasPath, r.labelSelectorPath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !replicasFound {
|
||||
return nil, apierrors.NewInternalError(fmt.Errorf("the spec replicas field %q does not exist", r.specReplicasPath))
|
||||
}
|
||||
return scaleObject, err
|
||||
}
|
||||
|
||||
func (r *ScaleREST) Update(ctx context.Context, name string, objInfo rest.UpdatedObjectInfo, createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc, forceAllowCreate bool) (runtime.Object, bool, error) {
|
||||
cr, err := r.registry.GetCustomResource(ctx, name, &metav1.GetOptions{})
|
||||
if err != nil {
|
||||
return nil, false, err
|
||||
}
|
||||
|
||||
const invalidSpecReplicas = -2147483648 // smallest int32
|
||||
oldScale, replicasFound, err := scaleFromCustomResource(cr, r.specReplicasPath, r.statusReplicasPath, r.labelSelectorPath)
|
||||
if err != nil {
|
||||
return nil, false, err
|
||||
}
|
||||
if !replicasFound {
|
||||
oldScale.Spec.Replicas = invalidSpecReplicas // signal that this was not set before
|
||||
}
|
||||
|
||||
obj, err := objInfo.UpdatedObject(ctx, oldScale)
|
||||
if err != nil {
|
||||
return nil, false, err
|
||||
}
|
||||
if obj == nil {
|
||||
return nil, false, apierrors.NewBadRequest(fmt.Sprintf("nil update passed to Scale"))
|
||||
}
|
||||
|
||||
scale, ok := obj.(*autoscalingv1.Scale)
|
||||
if !ok {
|
||||
return nil, false, apierrors.NewBadRequest(fmt.Sprintf("wrong object passed to Scale update: %v", obj))
|
||||
}
|
||||
|
||||
if scale.Spec.Replicas == invalidSpecReplicas {
|
||||
return nil, false, apierrors.NewBadRequest(fmt.Sprintf("the spec replicas field %q cannot be empty", r.specReplicasPath))
|
||||
}
|
||||
|
||||
specReplicasPath := strings.TrimPrefix(r.specReplicasPath, ".") // ignore leading period
|
||||
if err = unstructured.SetNestedField(cr.Object, int64(scale.Spec.Replicas), strings.Split(specReplicasPath, ".")...); err != nil {
|
||||
return nil, false, err
|
||||
}
|
||||
cr.SetResourceVersion(scale.ResourceVersion)
|
||||
|
||||
cr, err = r.registry.UpdateCustomResource(ctx, cr, createValidation, updateValidation)
|
||||
if err != nil {
|
||||
return nil, false, err
|
||||
}
|
||||
|
||||
newScale, _, err := scaleFromCustomResource(cr, r.specReplicasPath, r.statusReplicasPath, r.labelSelectorPath)
|
||||
if err != nil {
|
||||
return nil, false, apierrors.NewBadRequest(err.Error())
|
||||
}
|
||||
return newScale, false, err
|
||||
}
|
||||
|
||||
// scaleFromCustomResource returns a scale subresource for a customresource and a bool signalling wether
|
||||
// the specReplicas value was found.
|
||||
func scaleFromCustomResource(cr *unstructured.Unstructured, specReplicasPath, statusReplicasPath, labelSelectorPath string) (*autoscalingv1.Scale, bool, error) {
|
||||
specReplicasPath = strings.TrimPrefix(specReplicasPath, ".") // ignore leading period
|
||||
specReplicas, foundSpecReplicas, err := unstructured.NestedInt64(cr.UnstructuredContent(), strings.Split(specReplicasPath, ".")...)
|
||||
if err != nil {
|
||||
return nil, false, err
|
||||
} else if !foundSpecReplicas {
|
||||
specReplicas = 0
|
||||
}
|
||||
|
||||
statusReplicasPath = strings.TrimPrefix(statusReplicasPath, ".") // ignore leading period
|
||||
statusReplicas, found, err := unstructured.NestedInt64(cr.UnstructuredContent(), strings.Split(statusReplicasPath, ".")...)
|
||||
if err != nil {
|
||||
return nil, false, err
|
||||
} else if !found {
|
||||
statusReplicas = 0
|
||||
}
|
||||
|
||||
var labelSelector string
|
||||
if len(labelSelectorPath) > 0 {
|
||||
labelSelectorPath = strings.TrimPrefix(labelSelectorPath, ".") // ignore leading period
|
||||
labelSelector, found, err = unstructured.NestedString(cr.UnstructuredContent(), strings.Split(labelSelectorPath, ".")...)
|
||||
if err != nil {
|
||||
return nil, false, err
|
||||
}
|
||||
}
|
||||
|
||||
scale := &autoscalingv1.Scale{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: cr.GetName(),
|
||||
Namespace: cr.GetNamespace(),
|
||||
UID: cr.GetUID(),
|
||||
ResourceVersion: cr.GetResourceVersion(),
|
||||
CreationTimestamp: cr.GetCreationTimestamp(),
|
||||
},
|
||||
Spec: autoscalingv1.ScaleSpec{
|
||||
Replicas: int32(specReplicas),
|
||||
},
|
||||
Status: autoscalingv1.ScaleStatus{
|
||||
Replicas: int32(statusReplicas),
|
||||
Selector: labelSelector,
|
||||
},
|
||||
}
|
||||
|
||||
return scale, foundSpecReplicas, nil
|
||||
}
|
||||
575
vendor/k8s.io/apiextensions-apiserver/pkg/registry/customresource/etcd_test.go
generated
vendored
Normal file
575
vendor/k8s.io/apiextensions-apiserver/pkg/registry/customresource/etcd_test.go
generated
vendored
Normal file
@@ -0,0 +1,575 @@
|
||||
/*
|
||||
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 customresource_test
|
||||
|
||||
import (
|
||||
"io"
|
||||
"reflect"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
autoscalingv1 "k8s.io/api/autoscaling/v1"
|
||||
apiequality "k8s.io/apimachinery/pkg/api/equality"
|
||||
"k8s.io/apimachinery/pkg/api/errors"
|
||||
metainternal "k8s.io/apimachinery/pkg/apis/meta/internalversion"
|
||||
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/util/diff"
|
||||
genericapirequest "k8s.io/apiserver/pkg/endpoints/request"
|
||||
"k8s.io/apiserver/pkg/registry/generic"
|
||||
registrytest "k8s.io/apiserver/pkg/registry/generic/testing"
|
||||
"k8s.io/apiserver/pkg/registry/rest"
|
||||
etcdtesting "k8s.io/apiserver/pkg/storage/etcd/testing"
|
||||
|
||||
"k8s.io/apiextensions-apiserver/pkg/apis/apiextensions"
|
||||
"k8s.io/apiextensions-apiserver/pkg/apiserver"
|
||||
"k8s.io/apiextensions-apiserver/pkg/crdserverscheme"
|
||||
"k8s.io/apiextensions-apiserver/pkg/registry/customresource"
|
||||
"k8s.io/apiextensions-apiserver/pkg/registry/customresource/tableconvertor"
|
||||
)
|
||||
|
||||
func newStorage(t *testing.T) (customresource.CustomResourceStorage, *etcdtesting.EtcdTestServer) {
|
||||
server, etcdStorage := etcdtesting.NewUnsecuredEtcd3TestClientServer(t)
|
||||
etcdStorage.Codec = unstructuredJsonCodec{}
|
||||
restOptions := generic.RESTOptions{StorageConfig: etcdStorage, Decorator: generic.UndecoratedStorage, DeleteCollectionWorkers: 1, ResourcePrefix: "noxus"}
|
||||
|
||||
parameterScheme := runtime.NewScheme()
|
||||
parameterScheme.AddUnversionedTypes(schema.GroupVersion{Group: "mygroup.example.com", Version: "v1beta1"},
|
||||
&metav1.ListOptions{},
|
||||
&metav1.ExportOptions{},
|
||||
&metav1.GetOptions{},
|
||||
&metav1.DeleteOptions{},
|
||||
)
|
||||
|
||||
typer := apiserver.UnstructuredObjectTyper{
|
||||
Delegate: parameterScheme,
|
||||
UnstructuredTyper: crdserverscheme.NewUnstructuredObjectTyper(),
|
||||
}
|
||||
|
||||
kind := schema.GroupVersionKind{Group: "mygroup.example.com", Version: "v1beta1", Kind: "Noxu"}
|
||||
|
||||
labelSelectorPath := ".status.labelSelector"
|
||||
scale := &apiextensions.CustomResourceSubresourceScale{
|
||||
SpecReplicasPath: ".spec.replicas",
|
||||
StatusReplicasPath: ".status.replicas",
|
||||
LabelSelectorPath: &labelSelectorPath,
|
||||
}
|
||||
|
||||
status := &apiextensions.CustomResourceSubresourceStatus{}
|
||||
|
||||
headers := []apiextensions.CustomResourceColumnDefinition{
|
||||
{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(
|
||||
schema.GroupResource{Group: "mygroup.example.com", Resource: "noxus"},
|
||||
schema.GroupVersionKind{Group: "mygroup.example.com", Version: "v1beta1", Kind: "NoxuItemList"},
|
||||
customresource.NewStrategy(
|
||||
typer,
|
||||
true,
|
||||
kind,
|
||||
nil,
|
||||
nil,
|
||||
status,
|
||||
scale,
|
||||
),
|
||||
restOptions,
|
||||
[]string{"all"},
|
||||
table,
|
||||
)
|
||||
|
||||
return storage, server
|
||||
}
|
||||
|
||||
// createCustomResource is a helper function that returns a CustomResource with the updated resource version.
|
||||
func createCustomResource(storage *customresource.REST, cr unstructured.Unstructured, t *testing.T) (unstructured.Unstructured, error) {
|
||||
ctx := genericapirequest.WithNamespace(genericapirequest.NewContext(), cr.GetNamespace())
|
||||
obj, err := storage.Create(ctx, &cr, rest.ValidateAllObjectFunc, false)
|
||||
if err != nil {
|
||||
t.Errorf("Failed to create CustomResource, %v", err)
|
||||
}
|
||||
newCR := obj.(*unstructured.Unstructured)
|
||||
return *newCR, nil
|
||||
}
|
||||
|
||||
func validNewCustomResource() *unstructured.Unstructured {
|
||||
return &unstructured.Unstructured{
|
||||
Object: map[string]interface{}{
|
||||
"apiVersion": "mygroup.example.com/v1beta1",
|
||||
"kind": "Noxu",
|
||||
"metadata": map[string]interface{}{
|
||||
"namespace": "default",
|
||||
"name": "foo",
|
||||
"creationTimestamp": time.Now().Add(-time.Hour*12 - 30*time.Minute).UTC().Format(time.RFC3339),
|
||||
},
|
||||
"spec": map[string]interface{}{
|
||||
"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)}},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
var validCustomResource = *validNewCustomResource()
|
||||
|
||||
func TestCreate(t *testing.T) {
|
||||
storage, server := newStorage(t)
|
||||
defer server.Terminate(t)
|
||||
defer storage.CustomResource.Store.DestroyFunc()
|
||||
test := registrytest.New(t, storage.CustomResource.Store)
|
||||
cr := validNewCustomResource()
|
||||
cr.SetNamespace("")
|
||||
test.TestCreate(
|
||||
cr,
|
||||
)
|
||||
}
|
||||
|
||||
func TestGet(t *testing.T) {
|
||||
storage, server := newStorage(t)
|
||||
defer server.Terminate(t)
|
||||
defer storage.CustomResource.Store.DestroyFunc()
|
||||
test := registrytest.New(t, storage.CustomResource.Store)
|
||||
test.TestGet(validNewCustomResource())
|
||||
}
|
||||
|
||||
func TestList(t *testing.T) {
|
||||
storage, server := newStorage(t)
|
||||
defer server.Terminate(t)
|
||||
defer storage.CustomResource.Store.DestroyFunc()
|
||||
test := registrytest.New(t, storage.CustomResource.Store)
|
||||
test.TestList(validNewCustomResource())
|
||||
}
|
||||
|
||||
func TestDelete(t *testing.T) {
|
||||
storage, server := newStorage(t)
|
||||
defer server.Terminate(t)
|
||||
defer storage.CustomResource.Store.DestroyFunc()
|
||||
test := registrytest.New(t, storage.CustomResource.Store)
|
||||
test.TestDelete(validNewCustomResource())
|
||||
}
|
||||
|
||||
func TestGenerationNumber(t *testing.T) {
|
||||
storage, server := newStorage(t)
|
||||
defer server.Terminate(t)
|
||||
defer storage.CustomResource.Store.DestroyFunc()
|
||||
modifiedRno := *validNewCustomResource()
|
||||
modifiedRno.SetGeneration(10)
|
||||
ctx := genericapirequest.NewDefaultContext()
|
||||
cr, err := createCustomResource(storage.CustomResource, modifiedRno, t)
|
||||
if err != nil {
|
||||
t.Errorf("unexpected error: %v", err)
|
||||
}
|
||||
etcdCR, err := storage.CustomResource.Get(ctx, cr.GetName(), &metav1.GetOptions{})
|
||||
if err != nil {
|
||||
t.Errorf("unexpected error: %v", err)
|
||||
}
|
||||
storedCR, _ := etcdCR.(*unstructured.Unstructured)
|
||||
|
||||
// Generation initialization
|
||||
if storedCR.GetGeneration() != 1 {
|
||||
t.Fatalf("Unexpected generation number %v", storedCR.GetGeneration())
|
||||
}
|
||||
|
||||
// Updates to spec should increment the generation number
|
||||
setSpecReplicas(storedCR, getSpecReplicas(storedCR)+1)
|
||||
if _, _, err := storage.CustomResource.Update(ctx, storedCR.GetName(), rest.DefaultUpdatedObjectInfo(storedCR), rest.ValidateAllObjectFunc, rest.ValidateAllObjectUpdateFunc, false); err != nil {
|
||||
t.Errorf("unexpected error: %v", err)
|
||||
}
|
||||
etcdCR, err = storage.CustomResource.Get(ctx, cr.GetName(), &metav1.GetOptions{})
|
||||
if err != nil {
|
||||
t.Errorf("unexpected error: %v", err)
|
||||
}
|
||||
storedCR, _ = etcdCR.(*unstructured.Unstructured)
|
||||
if storedCR.GetGeneration() != 2 {
|
||||
t.Fatalf("Unexpected generation, spec: %v", storedCR.GetGeneration())
|
||||
}
|
||||
|
||||
// Updates to status should not increment the generation number
|
||||
setStatusReplicas(storedCR, getStatusReplicas(storedCR)+1)
|
||||
if _, _, err := storage.CustomResource.Update(ctx, storedCR.GetName(), rest.DefaultUpdatedObjectInfo(storedCR), rest.ValidateAllObjectFunc, rest.ValidateAllObjectUpdateFunc, false); err != nil {
|
||||
t.Errorf("unexpected error: %v", err)
|
||||
}
|
||||
etcdCR, err = storage.CustomResource.Get(ctx, cr.GetName(), &metav1.GetOptions{})
|
||||
if err != nil {
|
||||
t.Errorf("unexpected error: %v", err)
|
||||
}
|
||||
storedCR, _ = etcdCR.(*unstructured.Unstructured)
|
||||
if storedCR.GetGeneration() != 2 {
|
||||
t.Fatalf("Unexpected generation, spec: %v", storedCR.GetGeneration())
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestCategories(t *testing.T) {
|
||||
storage, server := newStorage(t)
|
||||
defer server.Terminate(t)
|
||||
defer storage.CustomResource.Store.DestroyFunc()
|
||||
|
||||
expected := []string{"all"}
|
||||
actual := storage.CustomResource.Categories()
|
||||
ok := reflect.DeepEqual(actual, expected)
|
||||
if !ok {
|
||||
t.Errorf("categories are not equal. expected = %v actual = %v", expected, actual)
|
||||
}
|
||||
}
|
||||
|
||||
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) {
|
||||
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)
|
||||
}
|
||||
|
||||
gottenObj, err := storage.CustomResource.Get(ctx, "foo", &metav1.GetOptions{})
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
|
||||
update := gottenObj.(*unstructured.Unstructured)
|
||||
updateContent := update.Object
|
||||
updateContent["status"] = map[string]interface{}{
|
||||
"replicas": int64(7),
|
||||
}
|
||||
|
||||
if _, _, err := storage.Status.Update(ctx, update.GetName(), rest.DefaultUpdatedObjectInfo(update), rest.ValidateAllObjectFunc, rest.ValidateAllObjectUpdateFunc, false); err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
|
||||
obj, err := storage.CustomResource.Get(ctx, "foo", &metav1.GetOptions{})
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
|
||||
cr, ok := obj.(*unstructured.Unstructured)
|
||||
if !ok {
|
||||
t.Fatal("unexpected error: custom resource should be of type Unstructured")
|
||||
}
|
||||
content := cr.UnstructuredContent()
|
||||
|
||||
spec := content["spec"].(map[string]interface{})
|
||||
status := content["status"].(map[string]interface{})
|
||||
|
||||
if spec["replicas"].(int64) != 7 {
|
||||
t.Errorf("we expected .spec.replicas to not be updated but it was updated to %v", spec["replicas"].(int64))
|
||||
}
|
||||
if status["replicas"].(int64) != 7 {
|
||||
t.Errorf("we expected .status.replicas to be updated to %d but it was %v", 7, status["replicas"].(int64))
|
||||
}
|
||||
}
|
||||
|
||||
func TestScaleGet(t *testing.T) {
|
||||
storage, server := newStorage(t)
|
||||
defer server.Terminate(t)
|
||||
defer storage.CustomResource.Store.DestroyFunc()
|
||||
|
||||
name := "foo"
|
||||
|
||||
var cr unstructured.Unstructured
|
||||
ctx := genericapirequest.WithNamespace(genericapirequest.NewContext(), metav1.NamespaceDefault)
|
||||
key := "/noxus/" + metav1.NamespaceDefault + "/" + name
|
||||
if err := storage.CustomResource.Storage.Create(ctx, key, &validCustomResource, &cr, 0); err != nil {
|
||||
t.Fatalf("error setting new custom resource (key: %s) %v: %v", key, validCustomResource, err)
|
||||
}
|
||||
|
||||
want := &autoscalingv1.Scale{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: cr.GetName(),
|
||||
Namespace: metav1.NamespaceDefault,
|
||||
UID: cr.GetUID(),
|
||||
ResourceVersion: cr.GetResourceVersion(),
|
||||
CreationTimestamp: cr.GetCreationTimestamp(),
|
||||
},
|
||||
Spec: autoscalingv1.ScaleSpec{
|
||||
Replicas: int32(7),
|
||||
},
|
||||
}
|
||||
|
||||
obj, err := storage.Scale.Get(ctx, name, &metav1.GetOptions{})
|
||||
if err != nil {
|
||||
t.Fatalf("error fetching scale for %s: %v", name, err)
|
||||
}
|
||||
|
||||
got := obj.(*autoscalingv1.Scale)
|
||||
if !apiequality.Semantic.DeepEqual(got, want) {
|
||||
t.Errorf("unexpected scale: %s", diff.ObjectDiff(got, want))
|
||||
}
|
||||
}
|
||||
|
||||
func TestScaleGetWithoutSpecReplicas(t *testing.T) {
|
||||
storage, server := newStorage(t)
|
||||
defer server.Terminate(t)
|
||||
defer storage.CustomResource.Store.DestroyFunc()
|
||||
|
||||
name := "foo"
|
||||
|
||||
var cr unstructured.Unstructured
|
||||
ctx := genericapirequest.WithNamespace(genericapirequest.NewContext(), metav1.NamespaceDefault)
|
||||
key := "/noxus/" + metav1.NamespaceDefault + "/" + name
|
||||
withoutSpecReplicas := validCustomResource.DeepCopy()
|
||||
unstructured.RemoveNestedField(withoutSpecReplicas.Object, "spec", "replicas")
|
||||
if err := storage.CustomResource.Storage.Create(ctx, key, withoutSpecReplicas, &cr, 0); err != nil {
|
||||
t.Fatalf("error setting new custom resource (key: %s) %v: %v", key, withoutSpecReplicas, err)
|
||||
}
|
||||
|
||||
_, err := storage.Scale.Get(ctx, name, &metav1.GetOptions{})
|
||||
if err == nil {
|
||||
t.Fatalf("error expected for %s", name)
|
||||
}
|
||||
if expected := `the spec replicas field ".spec.replicas" does not exist`; !strings.Contains(err.Error(), expected) {
|
||||
t.Fatalf("expected error string %q, got: %v", expected, err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestScaleUpdate(t *testing.T) {
|
||||
storage, server := newStorage(t)
|
||||
defer server.Terminate(t)
|
||||
defer storage.CustomResource.Store.DestroyFunc()
|
||||
|
||||
name := "foo"
|
||||
|
||||
var cr unstructured.Unstructured
|
||||
ctx := genericapirequest.WithNamespace(genericapirequest.NewContext(), metav1.NamespaceDefault)
|
||||
key := "/noxus/" + metav1.NamespaceDefault + "/" + name
|
||||
if err := storage.CustomResource.Storage.Create(ctx, key, &validCustomResource, &cr, 0); err != nil {
|
||||
t.Fatalf("error setting new custom resource (key: %s) %v: %v", key, validCustomResource, err)
|
||||
}
|
||||
|
||||
obj, err := storage.Scale.Get(ctx, name, &metav1.GetOptions{})
|
||||
if err != nil {
|
||||
t.Fatalf("error fetching scale for %s: %v", name, err)
|
||||
}
|
||||
scale, ok := obj.(*autoscalingv1.Scale)
|
||||
if !ok {
|
||||
t.Fatalf("%v is not of the type autoscalingv1.Scale", scale)
|
||||
}
|
||||
|
||||
replicas := 12
|
||||
update := autoscalingv1.Scale{
|
||||
ObjectMeta: scale.ObjectMeta,
|
||||
Spec: autoscalingv1.ScaleSpec{
|
||||
Replicas: int32(replicas),
|
||||
},
|
||||
}
|
||||
|
||||
if _, _, err := storage.Scale.Update(ctx, update.Name, rest.DefaultUpdatedObjectInfo(&update), rest.ValidateAllObjectFunc, rest.ValidateAllObjectUpdateFunc, false); err != nil {
|
||||
t.Fatalf("error updating scale %v: %v", update, err)
|
||||
}
|
||||
|
||||
obj, err = storage.Scale.Get(ctx, name, &metav1.GetOptions{})
|
||||
if err != nil {
|
||||
t.Fatalf("error fetching scale for %s: %v", name, err)
|
||||
}
|
||||
scale = obj.(*autoscalingv1.Scale)
|
||||
if scale.Spec.Replicas != int32(replicas) {
|
||||
t.Errorf("wrong replicas count: expected: %d got: %d", replicas, scale.Spec.Replicas)
|
||||
}
|
||||
|
||||
update.ResourceVersion = scale.ResourceVersion
|
||||
update.Spec.Replicas = 15
|
||||
|
||||
if _, _, err = storage.Scale.Update(ctx, update.Name, rest.DefaultUpdatedObjectInfo(&update), rest.ValidateAllObjectFunc, rest.ValidateAllObjectUpdateFunc, false); err != nil && !errors.IsConflict(err) {
|
||||
t.Fatalf("unexpected error, expecting an update conflict but got %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestScaleUpdateWithoutSpecReplicas(t *testing.T) {
|
||||
storage, server := newStorage(t)
|
||||
defer server.Terminate(t)
|
||||
defer storage.CustomResource.Store.DestroyFunc()
|
||||
|
||||
name := "foo"
|
||||
|
||||
var cr unstructured.Unstructured
|
||||
ctx := genericapirequest.WithNamespace(genericapirequest.NewContext(), metav1.NamespaceDefault)
|
||||
key := "/noxus/" + metav1.NamespaceDefault + "/" + name
|
||||
withoutSpecReplicas := validCustomResource.DeepCopy()
|
||||
unstructured.RemoveNestedField(withoutSpecReplicas.Object, "spec", "replicas")
|
||||
if err := storage.CustomResource.Storage.Create(ctx, key, withoutSpecReplicas, &cr, 0); err != nil {
|
||||
t.Fatalf("error setting new custom resource (key: %s) %v: %v", key, withoutSpecReplicas, err)
|
||||
}
|
||||
|
||||
replicas := 12
|
||||
update := autoscalingv1.Scale{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: name,
|
||||
ResourceVersion: cr.GetResourceVersion(),
|
||||
},
|
||||
Spec: autoscalingv1.ScaleSpec{
|
||||
Replicas: int32(replicas),
|
||||
},
|
||||
}
|
||||
|
||||
if _, _, err := storage.Scale.Update(ctx, update.Name, rest.DefaultUpdatedObjectInfo(&update), rest.ValidateAllObjectFunc, rest.ValidateAllObjectUpdateFunc, false); err != nil {
|
||||
t.Fatalf("error updating scale %v: %v", update, err)
|
||||
}
|
||||
|
||||
obj, err := storage.Scale.Get(ctx, name, &metav1.GetOptions{})
|
||||
if err != nil {
|
||||
t.Fatalf("error fetching scale for %s: %v", name, err)
|
||||
}
|
||||
scale := obj.(*autoscalingv1.Scale)
|
||||
if scale.Spec.Replicas != int32(replicas) {
|
||||
t.Errorf("wrong replicas count: expected: %d got: %d", replicas, scale.Spec.Replicas)
|
||||
}
|
||||
}
|
||||
|
||||
type unstructuredJsonCodec struct{}
|
||||
|
||||
func (c unstructuredJsonCodec) Decode(data []byte, defaults *schema.GroupVersionKind, into runtime.Object) (runtime.Object, *schema.GroupVersionKind, error) {
|
||||
obj := into.(*unstructured.Unstructured)
|
||||
err := obj.UnmarshalJSON(data)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
gvk := obj.GroupVersionKind()
|
||||
return obj, &gvk, nil
|
||||
}
|
||||
|
||||
func (c unstructuredJsonCodec) Encode(obj runtime.Object, w io.Writer) error {
|
||||
u := obj.(*unstructured.Unstructured)
|
||||
bs, err := u.MarshalJSON()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
w.Write(bs)
|
||||
return nil
|
||||
}
|
||||
|
||||
func setSpecReplicas(u *unstructured.Unstructured, replicas int64) {
|
||||
setNestedField(u, replicas, "spec", "replicas")
|
||||
}
|
||||
|
||||
func getSpecReplicas(u *unstructured.Unstructured) int64 {
|
||||
val, found, err := unstructured.NestedInt64(u.Object, "spec", "replicas")
|
||||
if !found || err != nil {
|
||||
return 0
|
||||
}
|
||||
return val
|
||||
}
|
||||
|
||||
func setStatusReplicas(u *unstructured.Unstructured, replicas int64) {
|
||||
setNestedField(u, replicas, "status", "replicas")
|
||||
}
|
||||
|
||||
func getStatusReplicas(u *unstructured.Unstructured) int64 {
|
||||
val, found, err := unstructured.NestedInt64(u.Object, "status", "replicas")
|
||||
if !found || err != nil {
|
||||
return 0
|
||||
}
|
||||
return val
|
||||
}
|
||||
|
||||
func setNestedField(u *unstructured.Unstructured, value interface{}, fields ...string) {
|
||||
if u.Object == nil {
|
||||
u.Object = make(map[string]interface{})
|
||||
}
|
||||
unstructured.SetNestedField(u.Object, value, fields...)
|
||||
}
|
||||
104
vendor/k8s.io/apiextensions-apiserver/pkg/registry/customresource/registry.go
generated
vendored
Normal file
104
vendor/k8s.io/apiextensions-apiserver/pkg/registry/customresource/registry.go
generated
vendored
Normal file
@@ -0,0 +1,104 @@
|
||||
/*
|
||||
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 customresource
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"k8s.io/apimachinery/pkg/api/errors"
|
||||
metainternalversion "k8s.io/apimachinery/pkg/apis/meta/internalversion"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"k8s.io/apimachinery/pkg/watch"
|
||||
"k8s.io/apiserver/pkg/registry/rest"
|
||||
)
|
||||
|
||||
// Registry is an interface for things that know how to store CustomResources.
|
||||
type Registry interface {
|
||||
ListCustomResources(ctx context.Context, options *metainternalversion.ListOptions) (*unstructured.UnstructuredList, error)
|
||||
WatchCustomResources(ctx context.Context, options *metainternalversion.ListOptions) (watch.Interface, error)
|
||||
GetCustomResource(ctx context.Context, customResourceID string, options *metav1.GetOptions) (*unstructured.Unstructured, error)
|
||||
CreateCustomResource(ctx context.Context, customResource *unstructured.Unstructured, createValidation rest.ValidateObjectFunc) (*unstructured.Unstructured, error)
|
||||
UpdateCustomResource(ctx context.Context, customResource *unstructured.Unstructured, createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc) (*unstructured.Unstructured, error)
|
||||
DeleteCustomResource(ctx context.Context, customResourceID string) error
|
||||
}
|
||||
|
||||
// storage puts strong typing around storage calls
|
||||
type storage struct {
|
||||
rest.StandardStorage
|
||||
}
|
||||
|
||||
// NewRegistry returns a new Registry interface for the given Storage. Any mismatched
|
||||
// types will panic.
|
||||
func NewRegistry(s rest.StandardStorage) Registry {
|
||||
return &storage{s}
|
||||
}
|
||||
|
||||
func (s *storage) ListCustomResources(ctx context.Context, options *metainternalversion.ListOptions) (*unstructured.UnstructuredList, error) {
|
||||
if options != nil && options.FieldSelector != nil && !options.FieldSelector.Empty() {
|
||||
return nil, fmt.Errorf("field selector not supported yet")
|
||||
}
|
||||
obj, err := s.List(ctx, options)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*unstructured.UnstructuredList), err
|
||||
}
|
||||
|
||||
func (s *storage) WatchCustomResources(ctx context.Context, options *metainternalversion.ListOptions) (watch.Interface, error) {
|
||||
return s.Watch(ctx, options)
|
||||
}
|
||||
|
||||
func (s *storage) GetCustomResource(ctx context.Context, customResourceID string, options *metav1.GetOptions) (*unstructured.Unstructured, error) {
|
||||
obj, err := s.Get(ctx, customResourceID, options)
|
||||
customResource, ok := obj.(*unstructured.Unstructured)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("custom resource must be of type Unstructured")
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
apiVersion := customResource.GetAPIVersion()
|
||||
groupVersion := strings.Split(apiVersion, "/")
|
||||
group := groupVersion[0]
|
||||
return nil, errors.NewNotFound(schema.GroupResource{Group: group, Resource: "scale"}, customResourceID)
|
||||
}
|
||||
return customResource, nil
|
||||
}
|
||||
|
||||
func (s *storage) CreateCustomResource(ctx context.Context, customResource *unstructured.Unstructured, createValidation rest.ValidateObjectFunc) (*unstructured.Unstructured, error) {
|
||||
obj, err := s.Create(ctx, customResource, rest.ValidateAllObjectFunc, false)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*unstructured.Unstructured), nil
|
||||
}
|
||||
|
||||
func (s *storage) UpdateCustomResource(ctx context.Context, customResource *unstructured.Unstructured, createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc) (*unstructured.Unstructured, error) {
|
||||
obj, _, err := s.Update(ctx, customResource.GetName(), rest.DefaultUpdatedObjectInfo(customResource), createValidation, updateValidation, false)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*unstructured.Unstructured), nil
|
||||
}
|
||||
|
||||
func (s *storage) DeleteCustomResource(ctx context.Context, customResourceID string) error {
|
||||
_, _, err := s.Delete(ctx, customResourceID, nil)
|
||||
return err
|
||||
}
|
||||
59
vendor/k8s.io/apiextensions-apiserver/pkg/registry/customresource/status_strategy.go
generated
vendored
Normal file
59
vendor/k8s.io/apiextensions-apiserver/pkg/registry/customresource/status_strategy.go
generated
vendored
Normal file
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
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 customresource
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/util/validation/field"
|
||||
)
|
||||
|
||||
type statusStrategy struct {
|
||||
customResourceStrategy
|
||||
}
|
||||
|
||||
func NewStatusStrategy(strategy customResourceStrategy) statusStrategy {
|
||||
return statusStrategy{strategy}
|
||||
}
|
||||
|
||||
func (a statusStrategy) PrepareForUpdate(ctx context.Context, obj, old runtime.Object) {
|
||||
// update is only allowed to set status
|
||||
newCustomResourceObject := obj.(*unstructured.Unstructured)
|
||||
newCustomResource := newCustomResourceObject.UnstructuredContent()
|
||||
status, ok := newCustomResource["status"]
|
||||
|
||||
// copy old object into new object
|
||||
oldCustomResourceObject := old.(*unstructured.Unstructured)
|
||||
// overridding the resourceVersion in metadata is safe here, we have already checked that
|
||||
// new object and old object have the same resourceVersion.
|
||||
*newCustomResourceObject = *oldCustomResourceObject.DeepCopy()
|
||||
|
||||
// set status
|
||||
newCustomResource = newCustomResourceObject.UnstructuredContent()
|
||||
if ok {
|
||||
newCustomResource["status"] = status
|
||||
} else {
|
||||
delete(newCustomResource, "status")
|
||||
}
|
||||
}
|
||||
|
||||
// ValidateUpdate is the default update validation for an end user updating status.
|
||||
func (a statusStrategy) ValidateUpdate(ctx context.Context, obj, old runtime.Object) field.ErrorList {
|
||||
return a.customResourceStrategy.validator.ValidateStatusUpdate(ctx, obj, old, a.scale)
|
||||
}
|
||||
138
vendor/k8s.io/apiextensions-apiserver/pkg/registry/customresource/status_strategy_test.go
generated
vendored
Normal file
138
vendor/k8s.io/apiextensions-apiserver/pkg/registry/customresource/status_strategy_test.go
generated
vendored
Normal file
@@ -0,0 +1,138 @@
|
||||
/*
|
||||
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 customresource
|
||||
|
||||
import (
|
||||
"context"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
)
|
||||
|
||||
func TestPrepareForUpdate(t *testing.T) {
|
||||
strategy := statusStrategy{}
|
||||
tcs := []struct {
|
||||
old *unstructured.Unstructured
|
||||
obj *unstructured.Unstructured
|
||||
expected *unstructured.Unstructured
|
||||
}{
|
||||
{
|
||||
// changes to spec are ignored
|
||||
old: &unstructured.Unstructured{
|
||||
Object: map[string]interface{}{
|
||||
"spec": "old",
|
||||
},
|
||||
},
|
||||
obj: &unstructured.Unstructured{
|
||||
Object: map[string]interface{}{
|
||||
"spec": "new",
|
||||
},
|
||||
},
|
||||
expected: &unstructured.Unstructured{
|
||||
Object: map[string]interface{}{
|
||||
"spec": "old",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
// changes to other places are also ignored
|
||||
old: &unstructured.Unstructured{
|
||||
Object: map[string]interface{}{
|
||||
"spec": "old",
|
||||
},
|
||||
},
|
||||
obj: &unstructured.Unstructured{
|
||||
Object: map[string]interface{}{
|
||||
"new": "new",
|
||||
},
|
||||
},
|
||||
expected: &unstructured.Unstructured{
|
||||
Object: map[string]interface{}{
|
||||
"spec": "old",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
// delete status
|
||||
old: &unstructured.Unstructured{
|
||||
Object: map[string]interface{}{
|
||||
"spec": "old",
|
||||
"status": "old",
|
||||
},
|
||||
},
|
||||
obj: &unstructured.Unstructured{
|
||||
Object: map[string]interface{}{
|
||||
"spec": "old",
|
||||
},
|
||||
},
|
||||
expected: &unstructured.Unstructured{
|
||||
Object: map[string]interface{}{
|
||||
"spec": "old",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
// update status
|
||||
old: &unstructured.Unstructured{
|
||||
Object: map[string]interface{}{
|
||||
"spec": "old",
|
||||
"status": "old",
|
||||
},
|
||||
},
|
||||
obj: &unstructured.Unstructured{
|
||||
Object: map[string]interface{}{
|
||||
"status": "new",
|
||||
},
|
||||
},
|
||||
expected: &unstructured.Unstructured{
|
||||
Object: map[string]interface{}{
|
||||
"spec": "old",
|
||||
"status": "new",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
// update status and other parts
|
||||
old: &unstructured.Unstructured{
|
||||
Object: map[string]interface{}{
|
||||
"spec": "old",
|
||||
"status": "old",
|
||||
},
|
||||
},
|
||||
obj: &unstructured.Unstructured{
|
||||
Object: map[string]interface{}{
|
||||
"spec": "new",
|
||||
"new": "new",
|
||||
"status": "new",
|
||||
},
|
||||
},
|
||||
expected: &unstructured.Unstructured{
|
||||
Object: map[string]interface{}{
|
||||
"spec": "old",
|
||||
"status": "new",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
for index, tc := range tcs {
|
||||
strategy.PrepareForUpdate(context.TODO(), tc.obj, tc.old)
|
||||
if !reflect.DeepEqual(tc.obj, tc.expected) {
|
||||
t.Errorf("test %d failed: expected: %v, got %v", index, tc.expected, tc.obj)
|
||||
}
|
||||
}
|
||||
}
|
||||
185
vendor/k8s.io/apiextensions-apiserver/pkg/registry/customresource/strategy.go
generated
vendored
Normal file
185
vendor/k8s.io/apiextensions-apiserver/pkg/registry/customresource/strategy.go
generated
vendored
Normal 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 customresource
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/go-openapi/validate"
|
||||
|
||||
apiequality "k8s.io/apimachinery/pkg/api/equality"
|
||||
"k8s.io/apimachinery/pkg/api/meta"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
"k8s.io/apimachinery/pkg/fields"
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"k8s.io/apimachinery/pkg/util/validation/field"
|
||||
apiserverstorage "k8s.io/apiserver/pkg/storage"
|
||||
"k8s.io/apiserver/pkg/storage/names"
|
||||
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||
|
||||
"k8s.io/apiextensions-apiserver/pkg/apis/apiextensions"
|
||||
apiextensionsfeatures "k8s.io/apiextensions-apiserver/pkg/features"
|
||||
)
|
||||
|
||||
// customResourceStrategy implements behavior for CustomResources.
|
||||
type customResourceStrategy struct {
|
||||
runtime.ObjectTyper
|
||||
names.NameGenerator
|
||||
|
||||
namespaceScoped bool
|
||||
validator customResourceValidator
|
||||
status *apiextensions.CustomResourceSubresourceStatus
|
||||
scale *apiextensions.CustomResourceSubresourceScale
|
||||
}
|
||||
|
||||
func NewStrategy(typer runtime.ObjectTyper, namespaceScoped bool, kind schema.GroupVersionKind, schemaValidator, statusSchemaValidator *validate.SchemaValidator, status *apiextensions.CustomResourceSubresourceStatus, scale *apiextensions.CustomResourceSubresourceScale) customResourceStrategy {
|
||||
return customResourceStrategy{
|
||||
ObjectTyper: typer,
|
||||
NameGenerator: names.SimpleNameGenerator,
|
||||
namespaceScoped: namespaceScoped,
|
||||
status: status,
|
||||
scale: scale,
|
||||
validator: customResourceValidator{
|
||||
namespaceScoped: namespaceScoped,
|
||||
kind: kind,
|
||||
schemaValidator: schemaValidator,
|
||||
statusSchemaValidator: statusSchemaValidator,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (a customResourceStrategy) NamespaceScoped() bool {
|
||||
return a.namespaceScoped
|
||||
}
|
||||
|
||||
// PrepareForCreate clears the status of a CustomResource before creation.
|
||||
func (a customResourceStrategy) PrepareForCreate(ctx context.Context, obj runtime.Object) {
|
||||
if utilfeature.DefaultFeatureGate.Enabled(apiextensionsfeatures.CustomResourceSubresources) && a.status != nil {
|
||||
customResourceObject := obj.(*unstructured.Unstructured)
|
||||
customResource := customResourceObject.UnstructuredContent()
|
||||
|
||||
// create cannot set status
|
||||
if _, ok := customResource["status"]; ok {
|
||||
delete(customResource, "status")
|
||||
}
|
||||
}
|
||||
|
||||
accessor, _ := meta.Accessor(obj)
|
||||
accessor.SetGeneration(1)
|
||||
}
|
||||
|
||||
// PrepareForUpdate clears fields that are not allowed to be set by end users on update.
|
||||
func (a customResourceStrategy) PrepareForUpdate(ctx context.Context, obj, old runtime.Object) {
|
||||
if !utilfeature.DefaultFeatureGate.Enabled(apiextensionsfeatures.CustomResourceSubresources) || a.status == nil {
|
||||
return
|
||||
}
|
||||
|
||||
newCustomResourceObject := obj.(*unstructured.Unstructured)
|
||||
oldCustomResourceObject := old.(*unstructured.Unstructured)
|
||||
|
||||
newCustomResource := newCustomResourceObject.UnstructuredContent()
|
||||
oldCustomResource := oldCustomResourceObject.UnstructuredContent()
|
||||
|
||||
// update is not allowed to set status
|
||||
_, ok1 := newCustomResource["status"]
|
||||
_, ok2 := oldCustomResource["status"]
|
||||
switch {
|
||||
case ok2:
|
||||
newCustomResource["status"] = oldCustomResource["status"]
|
||||
case ok1:
|
||||
delete(newCustomResource, "status")
|
||||
}
|
||||
|
||||
// Any changes to the spec increment the generation number, any changes to the
|
||||
// status should reflect the generation number of the corresponding object. We push
|
||||
// the burden of managing the status onto the clients because we can't (in general)
|
||||
// know here what version of spec the writer of the status has seen. It may seem like
|
||||
// we can at first -- since obj contains spec -- but in the future we will probably make
|
||||
// status its own object, and even if we don't, writes may be the result of a
|
||||
// read-update-write loop, so the contents of spec may not actually be the spec that
|
||||
// the CustomResource has *seen*.
|
||||
newSpec, ok1 := newCustomResource["spec"]
|
||||
oldSpec, ok2 := oldCustomResource["spec"]
|
||||
|
||||
// spec is changed, created or deleted
|
||||
if (ok1 && ok2 && !apiequality.Semantic.DeepEqual(oldSpec, newSpec)) || (ok1 && !ok2) || (!ok1 && ok2) {
|
||||
oldAccessor, _ := meta.Accessor(oldCustomResourceObject)
|
||||
newAccessor, _ := meta.Accessor(newCustomResourceObject)
|
||||
newAccessor.SetGeneration(oldAccessor.GetGeneration() + 1)
|
||||
}
|
||||
}
|
||||
|
||||
// Validate validates a new CustomResource.
|
||||
func (a customResourceStrategy) Validate(ctx context.Context, obj runtime.Object) field.ErrorList {
|
||||
return a.validator.Validate(ctx, obj, a.scale)
|
||||
}
|
||||
|
||||
// Canonicalize normalizes the object after validation.
|
||||
func (customResourceStrategy) Canonicalize(obj runtime.Object) {
|
||||
}
|
||||
|
||||
// AllowCreateOnUpdate is false for CustomResources; this means a POST is
|
||||
// needed to create one.
|
||||
func (customResourceStrategy) AllowCreateOnUpdate() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// AllowUnconditionalUpdate is the default update policy for CustomResource objects.
|
||||
func (customResourceStrategy) AllowUnconditionalUpdate() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// ValidateUpdate is the default update validation for an end user updating status.
|
||||
func (a customResourceStrategy) ValidateUpdate(ctx context.Context, obj, old runtime.Object) field.ErrorList {
|
||||
return a.validator.ValidateUpdate(ctx, obj, old, a.scale)
|
||||
}
|
||||
|
||||
// GetAttrs returns labels and fields of a given object for filtering purposes.
|
||||
func (a customResourceStrategy) GetAttrs(obj runtime.Object) (labels.Set, fields.Set, bool, error) {
|
||||
accessor, err := meta.Accessor(obj)
|
||||
if err != nil {
|
||||
return nil, nil, false, err
|
||||
}
|
||||
return labels.Set(accessor.GetLabels()), objectMetaFieldsSet(accessor, a.namespaceScoped), accessor.GetInitializers() != nil, nil
|
||||
}
|
||||
|
||||
// objectMetaFieldsSet returns a fields that represent the ObjectMeta.
|
||||
func objectMetaFieldsSet(objectMeta metav1.Object, namespaceScoped bool) fields.Set {
|
||||
if namespaceScoped {
|
||||
return fields.Set{
|
||||
"metadata.name": objectMeta.GetName(),
|
||||
"metadata.namespace": objectMeta.GetNamespace(),
|
||||
}
|
||||
}
|
||||
return fields.Set{
|
||||
"metadata.name": objectMeta.GetName(),
|
||||
}
|
||||
}
|
||||
|
||||
// MatchCustomResourceDefinitionStorage is the filter used by the generic etcd backend to route
|
||||
// watch events from etcd to clients of the apiserver only interested in specific
|
||||
// labels/fields.
|
||||
func (a customResourceStrategy) MatchCustomResourceDefinitionStorage(label labels.Selector, field fields.Selector) apiserverstorage.SelectionPredicate {
|
||||
return apiserverstorage.SelectionPredicate{
|
||||
Label: label,
|
||||
Field: field,
|
||||
GetAttrs: a.GetAttrs,
|
||||
}
|
||||
}
|
||||
172
vendor/k8s.io/apiextensions-apiserver/pkg/registry/customresource/tableconvertor/tableconvertor.go
generated
vendored
Normal file
172
vendor/k8s.io/apiextensions-apiserver/pkg/registry/customresource/tableconvertor/tableconvertor.go
generated
vendored
Normal file
@@ -0,0 +1,172 @@
|
||||
/*
|
||||
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 (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"reflect"
|
||||
|
||||
"k8s.io/apiextensions-apiserver/pkg/apis/apiextensions"
|
||||
"k8s.io/apimachinery/pkg/api/meta"
|
||||
metatable "k8s.io/apimachinery/pkg/api/meta/table"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
metav1beta1 "k8s.io/apimachinery/pkg/apis/meta/v1beta1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apiserver/pkg/registry/rest"
|
||||
"k8s.io/client-go/util/jsonpath"
|
||||
)
|
||||
|
||||
var swaggerMetadataDescriptions = metav1.ObjectMeta{}.SwaggerDoc()
|
||||
|
||||
// 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.
|
||||
func New(crdColumns []apiextensions.CustomResourceColumnDefinition) (rest.TableConvertor, error) {
|
||||
headers := []metav1beta1.TableColumnDefinition{
|
||||
{Name: "Name", Type: "string", Format: "name", Description: swaggerMetadataDescriptions["name"]},
|
||||
}
|
||||
c := &convertor{
|
||||
headers: headers,
|
||||
}
|
||||
|
||||
for _, col := range crdColumns {
|
||||
path := jsonpath.New(col.Name)
|
||||
if err := path.Parse(fmt.Sprintf("{%s}", col.JSONPath)); err != nil {
|
||||
return c, fmt.Errorf("unrecognized column definition %q", col.JSONPath)
|
||||
}
|
||||
path.AllowMissingKeys(true)
|
||||
|
||||
desc := fmt.Sprintf("Custom resource definition column (in JSONPath format): %s", col.JSONPath)
|
||||
if len(col.Description) > 0 {
|
||||
desc = col.Description
|
||||
}
|
||||
|
||||
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,
|
||||
})
|
||||
}
|
||||
|
||||
return c, nil
|
||||
}
|
||||
|
||||
type convertor struct {
|
||||
headers []metav1beta1.TableColumnDefinition
|
||||
additionalColumns []*jsonpath.JSONPath
|
||||
}
|
||||
|
||||
func (c *convertor) ConvertToTable(ctx context.Context, obj runtime.Object, tableOptions runtime.Object) (*metav1beta1.Table, error) {
|
||||
table := &metav1beta1.Table{
|
||||
ColumnDefinitions: c.headers,
|
||||
}
|
||||
if m, err := meta.ListAccessor(obj); err == nil {
|
||||
table.ResourceVersion = m.GetResourceVersion()
|
||||
table.SelfLink = m.GetSelfLink()
|
||||
table.Continue = m.GetContinue()
|
||||
} else {
|
||||
if m, err := meta.CommonAccessor(obj); err == nil {
|
||||
table.ResourceVersion = m.GetResourceVersion()
|
||||
table.SelfLink = m.GetSelfLink()
|
||||
}
|
||||
}
|
||||
|
||||
var err error
|
||||
buf := &bytes.Buffer{}
|
||||
table.Rows, err = metatable.MetaToTableRow(obj, func(obj runtime.Object, m metav1.Object, name, age string) ([]interface{}, error) {
|
||||
cells := make([]interface{}, 1, 1+len(c.additionalColumns))
|
||||
cells[0] = name
|
||||
customHeaders := c.headers[1:]
|
||||
for i, column := range c.additionalColumns {
|
||||
results, err := column.FindResults(obj.(runtime.Unstructured).UnstructuredContent())
|
||||
if err != nil || len(results) == 0 || len(results[0]) == 0 {
|
||||
cells = append(cells, nil)
|
||||
continue
|
||||
}
|
||||
|
||||
// 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 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
|
||||
}
|
||||
68
vendor/k8s.io/apiextensions-apiserver/pkg/registry/customresource/tableconvertor/tableconvertor_test.go
generated
vendored
Normal file
68
vendor/k8s.io/apiextensions-apiserver/pkg/registry/customresource/tableconvertor/tableconvertor_test.go
generated
vendored
Normal 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)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user