mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-24 12:15:52 +00:00
Add extract apply function generation
This commit is contained in:
parent
5bc72f37a4
commit
987657a80f
@ -26,11 +26,13 @@ source "${KUBE_ROOT}/hack/lib/init.sh"
|
||||
|
||||
kube::golang::setup_env
|
||||
|
||||
go install k8s.io/kubernetes/pkg/generated/openapi/cmd/models-schema
|
||||
go install k8s.io/kubernetes/vendor/k8s.io/code-generator/cmd/client-gen
|
||||
go install k8s.io/kubernetes/vendor/k8s.io/code-generator/cmd/lister-gen
|
||||
go install k8s.io/kubernetes/vendor/k8s.io/code-generator/cmd/informer-gen
|
||||
go install k8s.io/kubernetes/vendor/k8s.io/code-generator/cmd/applyconfiguration-gen
|
||||
|
||||
modelsschema=$(kube::util::find-binary "models-schema")
|
||||
clientgen=$(kube::util::find-binary "client-gen")
|
||||
listergen=$(kube::util::find-binary "lister-gen")
|
||||
informergen=$(kube::util::find-binary "informer-gen")
|
||||
@ -66,6 +68,7 @@ applyconfigurationgen_external_apis+=("k8s.io/apimachinery/pkg/apis/meta/v1")
|
||||
applyconfigurationgen_external_apis_csv=$(IFS=,; echo "${applyconfigurationgen_external_apis[*]}")
|
||||
applyconfigurations_package="k8s.io/client-go/applyconfigurations"
|
||||
${applyconfigurationgen} \
|
||||
--openapi-schema <(${modelsschema}) \
|
||||
--output-base "${KUBE_ROOT}/vendor" \
|
||||
--output-package "${applyconfigurations_package}" \
|
||||
--input-dirs "${applyconfigurationgen_external_apis_csv}" \
|
||||
|
79
pkg/generated/openapi/cmd/models-schema/main.go
Normal file
79
pkg/generated/openapi/cmd/models-schema/main.go
Normal file
@ -0,0 +1,79 @@
|
||||
/*
|
||||
Copyright 2021 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 main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/go-openapi/spec"
|
||||
|
||||
"k8s.io/kubernetes/pkg/generated/openapi"
|
||||
)
|
||||
|
||||
// Outputs openAPI schema JSON containing the schema definitions in zz_generated.openapi.go.
|
||||
func main() {
|
||||
err := output()
|
||||
if err != nil {
|
||||
os.Stderr.WriteString(fmt.Sprintf("Failed: %v", err))
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
func output() error {
|
||||
refFunc := func(name string) spec.Ref {
|
||||
return spec.MustCreateRef(fmt.Sprintf("#/definitions/%s", friendlyName(name)))
|
||||
}
|
||||
defs := openapi.GetOpenAPIDefinitions(refFunc)
|
||||
schemaDefs := make(map[string]spec.Schema, len(defs))
|
||||
for k, v := range defs {
|
||||
schemaDefs[friendlyName(k)] = v.Schema
|
||||
}
|
||||
data, err := json.Marshal(&spec.Swagger{
|
||||
SwaggerProps: spec.SwaggerProps{
|
||||
Definitions: schemaDefs,
|
||||
Info: &spec.Info{
|
||||
InfoProps: spec.InfoProps{
|
||||
Title: "Kubernetes",
|
||||
Version: "unversioned",
|
||||
},
|
||||
},
|
||||
Swagger: "2.0",
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
return fmt.Errorf("error serializing api definitions: %w", err)
|
||||
}
|
||||
_, err = os.Stdout.Write(data)
|
||||
return nil
|
||||
}
|
||||
|
||||
// From vendor/k8s.io/apiserver/pkg/endpoints/openapi/openapi.go
|
||||
func friendlyName(name string) string {
|
||||
nameParts := strings.Split(name, "/")
|
||||
// Reverse first part. e.g., io.k8s... instead of k8s.io...
|
||||
if len(nameParts) > 0 && strings.Contains(nameParts[0], ".") {
|
||||
parts := strings.Split(nameParts[0], ".")
|
||||
for i, j := 0, len(parts)-1; i < j; i, j = i+1, j-1 {
|
||||
parts[i], parts[j] = parts[j], parts[i]
|
||||
}
|
||||
nameParts[0] = strings.Join(parts, ".")
|
||||
}
|
||||
return strings.Join(nameParts, ".")
|
||||
}
|
@ -0,0 +1,86 @@
|
||||
/*
|
||||
Copyright 2021 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 managedfields
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
|
||||
"sigs.k8s.io/structured-merge-diff/v4/fieldpath"
|
||||
"sigs.k8s.io/structured-merge-diff/v4/typed"
|
||||
|
||||
"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/runtime"
|
||||
)
|
||||
|
||||
// ExtractInto extracts the applied configuration state from object for fieldManager
|
||||
// into applyConfiguration. If no managed fields are found for the given fieldManager,
|
||||
// no error is returned, but applyConfiguration is left unpopulated. It is possible
|
||||
// that no managed fields were found for the fieldManager because other field managers
|
||||
// have taken ownership of all the fields previously owned by the fieldManager. It is
|
||||
// also possible the fieldManager never owned fields.
|
||||
func ExtractInto(object runtime.Object, objectType typed.ParseableType, fieldManager string, applyConfiguration interface{}) error {
|
||||
typedObj, err := toTyped(object, objectType)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error converting obj to typed: %w", err)
|
||||
}
|
||||
|
||||
accessor, err := meta.Accessor(object)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error accessing metadata: %w", err)
|
||||
}
|
||||
fieldsEntry, ok := findManagedFields(accessor, fieldManager)
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
fieldset := &fieldpath.Set{}
|
||||
err = fieldset.FromJSON(bytes.NewReader(fieldsEntry.FieldsV1.Raw))
|
||||
if err != nil {
|
||||
return fmt.Errorf("error marshalling FieldsV1 to JSON: %w", err)
|
||||
}
|
||||
|
||||
u := typedObj.ExtractItems(fieldset.Leaves()).AsValue().Unstructured()
|
||||
m, ok := u.(map[string]interface{})
|
||||
if !ok {
|
||||
return fmt.Errorf("unable to convert managed fields for %s to unstructured, expected map, got %T", fieldManager, u)
|
||||
}
|
||||
if err := runtime.DefaultUnstructuredConverter.FromUnstructured(m, applyConfiguration); err != nil {
|
||||
return fmt.Errorf("error extracting into obj from unstructured: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func findManagedFields(accessor metav1.Object, fieldManager string) (metav1.ManagedFieldsEntry, bool) {
|
||||
objManagedFields := accessor.GetManagedFields()
|
||||
for _, mf := range objManagedFields {
|
||||
if mf.Manager == fieldManager && mf.Operation == metav1.ManagedFieldsOperationApply {
|
||||
return mf, true
|
||||
}
|
||||
}
|
||||
return metav1.ManagedFieldsEntry{}, false
|
||||
}
|
||||
|
||||
func toTyped(obj runtime.Object, objectType typed.ParseableType) (*typed.TypedValue, error) {
|
||||
switch o := obj.(type) {
|
||||
case *unstructured.Unstructured:
|
||||
return objectType.FromUnstructured(o.Object)
|
||||
default:
|
||||
return objectType.FromStructured(o)
|
||||
}
|
||||
}
|
@ -0,0 +1,242 @@
|
||||
/*
|
||||
Copyright 2021 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 managedfields
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/google/go-cmp/cmp"
|
||||
"sigs.k8s.io/structured-merge-diff/v4/typed"
|
||||
|
||||
"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/runtime"
|
||||
runtimeschema "k8s.io/apimachinery/pkg/runtime/schema"
|
||||
)
|
||||
|
||||
func TestExtractInto(t *testing.T) {
|
||||
one := int32(1)
|
||||
parser, err := typed.NewParser(schemaYAML)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to parse schema: %v", err)
|
||||
}
|
||||
cases := []struct {
|
||||
name string
|
||||
obj runtime.Object
|
||||
objType typed.ParseableType
|
||||
managedFields []metav1.ManagedFieldsEntry // written to object before test is run
|
||||
fieldManager string
|
||||
expectedOut interface{}
|
||||
}{
|
||||
{
|
||||
name: "unstructured, no matching manager",
|
||||
obj: &unstructured.Unstructured{Object: map[string]interface{}{"spec": map[string]interface{}{"replicas": 1}}},
|
||||
objType: parser.Type("io.k8s.api.apps.v1.Deployment"),
|
||||
managedFields: []metav1.ManagedFieldsEntry{
|
||||
applyFieldsEntry("mgr999", `{ "f:spec": { "f:replicas": {}}}`),
|
||||
},
|
||||
fieldManager: "mgr1",
|
||||
expectedOut: map[string]interface{}{},
|
||||
},
|
||||
{
|
||||
name: "unstructured, one manager",
|
||||
obj: &unstructured.Unstructured{Object: map[string]interface{}{"spec": map[string]interface{}{"replicas": 1}}},
|
||||
objType: parser.Type("io.k8s.api.apps.v1.Deployment"),
|
||||
managedFields: []metav1.ManagedFieldsEntry{
|
||||
applyFieldsEntry("mgr1", `{ "f:spec": { "f:replicas": {}}}`),
|
||||
},
|
||||
fieldManager: "mgr1",
|
||||
expectedOut: map[string]interface{}{"spec": map[string]interface{}{"replicas": 1}},
|
||||
},
|
||||
{
|
||||
name: "unstructured, multiple manager",
|
||||
obj: &unstructured.Unstructured{Object: map[string]interface{}{"spec": map[string]interface{}{"paused": true}}},
|
||||
objType: parser.Type("io.k8s.api.apps.v1.Deployment"),
|
||||
managedFields: []metav1.ManagedFieldsEntry{
|
||||
applyFieldsEntry("mgr1", `{ "f:spec": { "f:replicas": {}}}`),
|
||||
applyFieldsEntry("mgr2", `{ "f:spec": { "f:paused": {}}}`),
|
||||
},
|
||||
fieldManager: "mgr2",
|
||||
expectedOut: map[string]interface{}{"spec": map[string]interface{}{"paused": true}},
|
||||
},
|
||||
{
|
||||
name: "structured, no matching manager",
|
||||
obj: &fakeDeployment{Spec: fakeDeploymentSpec{Replicas: &one}},
|
||||
objType: parser.Type("io.k8s.api.apps.v1.Deployment"),
|
||||
managedFields: []metav1.ManagedFieldsEntry{
|
||||
applyFieldsEntry("mgr999", `{ "f:spec": { "f:replicas": {}}}`),
|
||||
},
|
||||
fieldManager: "mgr1",
|
||||
expectedOut: map[string]interface{}{},
|
||||
},
|
||||
{
|
||||
name: "structured, one manager",
|
||||
obj: &fakeDeployment{Spec: fakeDeploymentSpec{Replicas: &one}},
|
||||
objType: parser.Type("io.k8s.api.apps.v1.Deployment"),
|
||||
managedFields: []metav1.ManagedFieldsEntry{
|
||||
applyFieldsEntry("mgr1", `{ "f:spec": { "f:replicas": {}}}`),
|
||||
},
|
||||
fieldManager: "mgr1",
|
||||
expectedOut: map[string]interface{}{"spec": map[string]interface{}{"replicas": int64(1)}},
|
||||
},
|
||||
{
|
||||
name: "structured, multiple manager",
|
||||
obj: &fakeDeployment{Spec: fakeDeploymentSpec{Replicas: &one, Paused: true}},
|
||||
objType: parser.Type("io.k8s.api.apps.v1.Deployment"),
|
||||
managedFields: []metav1.ManagedFieldsEntry{
|
||||
applyFieldsEntry("mgr1", `{ "f:spec": { "f:replicas": {}}}`),
|
||||
applyFieldsEntry("mgr2", `{ "f:spec": { "f:paused": {}}}`),
|
||||
},
|
||||
fieldManager: "mgr2",
|
||||
expectedOut: map[string]interface{}{"spec": map[string]interface{}{"paused": true}},
|
||||
},
|
||||
}
|
||||
for _, tc := range cases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
out := map[string]interface{}{}
|
||||
accessor, err := meta.Accessor(tc.obj)
|
||||
if err != nil {
|
||||
t.Fatalf("Error accessing object: %v", err)
|
||||
}
|
||||
accessor.SetManagedFields(tc.managedFields)
|
||||
err = ExtractInto(tc.obj, tc.objType, tc.fieldManager, &out)
|
||||
if err != nil {
|
||||
t.Fatalf("Unexpected extract error: %v", err)
|
||||
}
|
||||
if !equality.Semantic.DeepEqual(out, tc.expectedOut) {
|
||||
t.Fatalf("Expected output did not match actual output: %s", cmp.Diff(out, tc.expectedOut))
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func applyFieldsEntry(fieldManager string, fieldsJSON string) metav1.ManagedFieldsEntry {
|
||||
return metav1.ManagedFieldsEntry{
|
||||
Manager: fieldManager,
|
||||
Operation: metav1.ManagedFieldsOperationApply,
|
||||
APIVersion: "v1",
|
||||
FieldsType: "FieldsV1",
|
||||
FieldsV1: &metav1.FieldsV1{Raw: []byte(fieldsJSON)},
|
||||
}
|
||||
}
|
||||
|
||||
type fakeDeployment struct {
|
||||
metav1.ObjectMeta `json:"metadata,omitempty"`
|
||||
Spec fakeDeploymentSpec `json:"spec"`
|
||||
}
|
||||
|
||||
type fakeDeploymentSpec struct {
|
||||
Replicas *int32 `json:"replicas"`
|
||||
Paused bool `json:"paused,omitempty"`
|
||||
}
|
||||
|
||||
func (o *fakeDeployment) GetObjectMeta() metav1.ObjectMeta {
|
||||
return o.ObjectMeta
|
||||
}
|
||||
func (o *fakeDeployment) GetObjectKind() runtimeschema.ObjectKind {
|
||||
return runtimeschema.EmptyObjectKind
|
||||
}
|
||||
func (o *fakeDeployment) DeepCopyObject() runtime.Object {
|
||||
return o
|
||||
}
|
||||
|
||||
// trimmed up schema for test purposes
|
||||
const schemaYAML = typed.YAMLObject(`types:
|
||||
- name: io.k8s.api.apps.v1.Deployment
|
||||
map:
|
||||
fields:
|
||||
- name: apiVersion
|
||||
type:
|
||||
scalar: string
|
||||
- name: kind
|
||||
type:
|
||||
scalar: string
|
||||
- name: metadata
|
||||
type:
|
||||
namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta
|
||||
- name: spec
|
||||
type:
|
||||
namedType: io.k8s.api.apps.v1.DeploymentSpec
|
||||
- name: io.k8s.api.apps.v1.DeploymentSpec
|
||||
map:
|
||||
fields:
|
||||
- name: paused
|
||||
type:
|
||||
scalar: boolean
|
||||
- name: replicas
|
||||
type:
|
||||
scalar: numeric
|
||||
- name: io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta
|
||||
map:
|
||||
fields:
|
||||
- name: creationTimestamp
|
||||
type:
|
||||
namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Time
|
||||
- name: managedFields
|
||||
type:
|
||||
list:
|
||||
elementType:
|
||||
namedType: io.k8s.apimachinery.pkg.apis.meta.v1.ManagedFieldsEntry
|
||||
elementRelationship: atomic
|
||||
- name: io.k8s.apimachinery.pkg.apis.meta.v1.ManagedFieldsEntry
|
||||
map:
|
||||
fields:
|
||||
- name: apiVersion
|
||||
type:
|
||||
scalar: string
|
||||
- name: fieldsType
|
||||
type:
|
||||
scalar: string
|
||||
- name: fieldsV1
|
||||
type:
|
||||
namedType: io.k8s.apimachinery.pkg.apis.meta.v1.FieldsV1
|
||||
- name: manager
|
||||
type:
|
||||
scalar: string
|
||||
- name: operation
|
||||
type:
|
||||
scalar: string
|
||||
- name: time
|
||||
type:
|
||||
namedType: io.k8s.apimachinery.pkg.apis.meta.v1.Time
|
||||
- name: io.k8s.apimachinery.pkg.apis.meta.v1.FieldsV1
|
||||
map:
|
||||
elementType:
|
||||
scalar: untyped
|
||||
list:
|
||||
elementType:
|
||||
namedType: __untyped_atomic_
|
||||
elementRelationship: atomic
|
||||
map:
|
||||
elementType:
|
||||
namedType: __untyped_atomic_
|
||||
elementRelationship: atomic
|
||||
- name: io.k8s.apimachinery.pkg.apis.meta.v1.Time
|
||||
scalar: untyped
|
||||
- name: __untyped_atomic_
|
||||
scalar: untyped
|
||||
list:
|
||||
elementType:
|
||||
namedType: __untyped_atomic_
|
||||
elementRelationship: atomic
|
||||
map:
|
||||
elementType:
|
||||
namedType: __untyped_atomic_
|
||||
elementRelationship: atomic
|
||||
`)
|
@ -31,6 +31,7 @@ require (
|
||||
k8s.io/apimachinery v0.0.0
|
||||
k8s.io/klog/v2 v2.5.0
|
||||
k8s.io/utils v0.0.0-20201110183641-67b214c5f920
|
||||
sigs.k8s.io/structured-merge-diff/v4 v4.1.0
|
||||
sigs.k8s.io/yaml v1.2.0
|
||||
)
|
||||
|
||||
|
@ -40,6 +40,8 @@ type CustomArgs struct {
|
||||
//
|
||||
// meta/v1 types (TypeMeta and ObjectMeta) are always included and do not need to be passed in.
|
||||
ExternalApplyConfigurations map[types.Name]string
|
||||
|
||||
OpenAPISchemaFilePath string
|
||||
}
|
||||
|
||||
// NewDefaults returns default arguments for the generator.
|
||||
@ -65,6 +67,8 @@ func (ca *CustomArgs) AddFlags(fs *pflag.FlagSet, inputBase string) {
|
||||
pflag.Var(NewExternalApplyConfigurationValue(&ca.ExternalApplyConfigurations, nil), "external-applyconfigurations",
|
||||
"list of comma separated external apply configurations locations in <type-package>.<type-name>:<applyconfiguration-package> form."+
|
||||
"For example: k8s.io/api/apps/v1.Deployment:k8s.io/client-go/applyconfigurations/apps/v1")
|
||||
pflag.StringVar(&ca.OpenAPISchemaFilePath, "openapi-schema", "",
|
||||
"path to the openapi schema containing all the types that apply configurations will be generated for")
|
||||
}
|
||||
|
||||
// Validate checks the given arguments.
|
||||
|
@ -37,6 +37,7 @@ type applyConfigurationGenerator struct {
|
||||
applyConfig applyConfig
|
||||
imports namer.ImportTracker
|
||||
refGraph refGraph
|
||||
openAPIType *string // if absent, extraction function cannot be generated
|
||||
}
|
||||
|
||||
var _ generator.Generator = &applyConfigurationGenerator{}
|
||||
@ -64,6 +65,9 @@ type TypeParams struct {
|
||||
ApplyConfig applyConfig
|
||||
Tags util.Tags
|
||||
APIVersion string
|
||||
ExtractInto *types.Type
|
||||
ParserFunc *types.Type
|
||||
OpenAPIType *string
|
||||
}
|
||||
|
||||
type memberParams struct {
|
||||
@ -84,6 +88,9 @@ func (g *applyConfigurationGenerator) GenerateType(c *generator.Context, t *type
|
||||
ApplyConfig: g.applyConfig,
|
||||
Tags: genclientTags(t),
|
||||
APIVersion: g.groupVersion.ToAPIVersion(),
|
||||
ExtractInto: extractInto,
|
||||
ParserFunc: types.Ref(g.outputPackage+"/internal", "Parser"),
|
||||
OpenAPIType: g.openAPIType,
|
||||
}
|
||||
|
||||
g.generateStruct(sw, typeParams)
|
||||
@ -94,6 +101,9 @@ func (g *applyConfigurationGenerator) GenerateType(c *generator.Context, t *type
|
||||
} else {
|
||||
sw.Do(clientgenTypeConstructorNamespaced, typeParams)
|
||||
}
|
||||
if typeParams.OpenAPIType != nil {
|
||||
g.generateClientgenExtract(sw, typeParams)
|
||||
}
|
||||
} else {
|
||||
sw.Do(constructor, typeParams)
|
||||
}
|
||||
@ -306,3 +316,35 @@ func $.ApplyConfig.Type|public$() *$.ApplyConfig.ApplyConfiguration|public$ {
|
||||
return &$.ApplyConfig.ApplyConfiguration|public${}
|
||||
}
|
||||
`
|
||||
|
||||
func (g *applyConfigurationGenerator) generateClientgenExtract(sw *generator.SnippetWriter, typeParams TypeParams) {
|
||||
sw.Do(`
|
||||
// Extract$.ApplyConfig.Type|public$ extracts the applied configuration owned by fieldManager from
|
||||
// $.Struct|private$. If no managedFields are found in $.Struct|private$ for fieldManager, a
|
||||
// $.ApplyConfig.ApplyConfiguration|public$ is returned with only the Name, Namespace (if applicable),
|
||||
// APIVersion and Kind populated. Is is possible that no managed fields were found for because other
|
||||
// field managers have taken ownership of all the fields previously owned by fieldManager, or because
|
||||
// the fieldManager never owned fields any fields.
|
||||
// $.Struct|private$ must be a unmodified $.Struct|public$ API object that was retrieved from the Kubernetes API.
|
||||
// Extract$.ApplyConfig.Type|public$ provides a way to perform a extract/modify-in-place/apply workflow.
|
||||
// Note that an extracted apply configuration will contain fewer fields than what the fieldManager previously
|
||||
// applied if another fieldManager has updated or force applied any of the previously applied fields.
|
||||
// Experimental!
|
||||
func Extract$.ApplyConfig.Type|public$($.Struct|private$ *$.Struct|raw$, fieldManager string) (*$.ApplyConfig.ApplyConfiguration|public$ , error) {
|
||||
b := &$.ApplyConfig.ApplyConfiguration|public${}
|
||||
err := $.ExtractInto|raw$($.Struct|private$, $.ParserFunc|raw$().Type("$.OpenAPIType$"), fieldManager, b)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
b.WithName($.Struct|private$.Name)
|
||||
`, typeParams)
|
||||
if !typeParams.Tags.NonNamespaced {
|
||||
sw.Do("b.WithNamespace($.Struct|private$.Namespace)\n", typeParams)
|
||||
}
|
||||
sw.Do(`
|
||||
b.WithKind("$.ApplyConfig.Type|singularKind$")
|
||||
b.WithAPIVersion("$.APIVersion$")
|
||||
return b, nil
|
||||
}
|
||||
`, typeParams)
|
||||
}
|
||||
|
@ -0,0 +1,99 @@
|
||||
/*
|
||||
Copyright 2021 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 generators
|
||||
|
||||
import (
|
||||
"io"
|
||||
|
||||
"gopkg.in/yaml.v2"
|
||||
|
||||
"k8s.io/kube-openapi/pkg/schemaconv"
|
||||
|
||||
"k8s.io/gengo/generator"
|
||||
"k8s.io/gengo/namer"
|
||||
"k8s.io/gengo/types"
|
||||
)
|
||||
|
||||
// utilGenerator generates the ForKind() utility function.
|
||||
type internalGenerator struct {
|
||||
generator.DefaultGen
|
||||
outputPackage string
|
||||
imports namer.ImportTracker
|
||||
typeModels *typeModels
|
||||
filtered bool
|
||||
}
|
||||
|
||||
var _ generator.Generator = &internalGenerator{}
|
||||
|
||||
func (g *internalGenerator) Filter(*generator.Context, *types.Type) bool {
|
||||
// generate file exactly once
|
||||
if !g.filtered {
|
||||
g.filtered = true
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (g *internalGenerator) Namers(*generator.Context) namer.NameSystems {
|
||||
return namer.NameSystems{
|
||||
"raw": namer.NewRawNamer(g.outputPackage, g.imports),
|
||||
"singularKind": namer.NewPublicNamer(0),
|
||||
}
|
||||
}
|
||||
|
||||
func (g *internalGenerator) Imports(*generator.Context) (imports []string) {
|
||||
return g.imports.ImportLines()
|
||||
}
|
||||
|
||||
func (g *internalGenerator) GenerateType(c *generator.Context, _ *types.Type, w io.Writer) error {
|
||||
sw := generator.NewSnippetWriter(w, c, "{{", "}}")
|
||||
|
||||
schema, err := schemaconv.ToSchema(g.typeModels.models)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
schemaYAML, err := yaml.Marshal(schema)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
sw.Do(schemaBlock, map[string]interface{}{
|
||||
"schemaYAML": string(schemaYAML),
|
||||
"smdParser": smdParser,
|
||||
"smdNewParser": smdNewParser,
|
||||
"yamlObject": yamlObject,
|
||||
"yamlUnmarshal": yamlUnmarshal,
|
||||
})
|
||||
|
||||
return sw.Error()
|
||||
}
|
||||
|
||||
var schemaBlock = `
|
||||
func Parser() *{{.smdParser|raw}} {
|
||||
parserOnce.Do(func() {
|
||||
var err error
|
||||
parser, err = {{.smdNewParser|raw}}(schemaYAML)
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("Failed to parse schema: %v", err))
|
||||
}
|
||||
})
|
||||
return parser
|
||||
}
|
||||
|
||||
var parserOnce sync.Once
|
||||
var parser *{{.smdParser|raw}}
|
||||
var schemaYAML = {{.yamlObject|raw}}(` + "`{{.schemaYAML}}`" + `)
|
||||
`
|
@ -0,0 +1,204 @@
|
||||
/*
|
||||
Copyright 2021 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 generators
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"strings"
|
||||
|
||||
"github.com/go-openapi/spec"
|
||||
"github.com/googleapis/gnostic/compiler"
|
||||
openapiv2 "github.com/googleapis/gnostic/openapiv2"
|
||||
"gopkg.in/yaml.v2"
|
||||
"k8s.io/gengo/types"
|
||||
utilproto "k8s.io/kube-openapi/pkg/util/proto"
|
||||
)
|
||||
|
||||
type typeModels struct {
|
||||
models utilproto.Models
|
||||
gvkToOpenAPIType map[gvk]string
|
||||
}
|
||||
|
||||
type gvk struct {
|
||||
group, version, kind string
|
||||
}
|
||||
|
||||
func newTypeModels(openAPISchemaFilePath string, pkgTypes map[string]*types.Package) (*typeModels, error) {
|
||||
if len(openAPISchemaFilePath) == 0 {
|
||||
return emptyModels, nil // No Extract<type>() functions will be generated.
|
||||
}
|
||||
|
||||
rawOpenAPISchema, err := ioutil.ReadFile(openAPISchemaFilePath)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to read openapi-schema file: %w", err)
|
||||
}
|
||||
|
||||
// Read in the provided openAPI schema.
|
||||
openAPISchema := &spec.Swagger{}
|
||||
err = json.Unmarshal(rawOpenAPISchema, openAPISchema)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to unmarshal typeModels JSON: %w", err)
|
||||
}
|
||||
|
||||
// Build a mapping from openAPI type name to GVK.
|
||||
// Find the root types needed by by client-go for apply.
|
||||
gvkToOpenAPIType := map[gvk]string{}
|
||||
rootDefs := map[string]spec.Schema{}
|
||||
for _, p := range pkgTypes {
|
||||
gv := groupVersion(p)
|
||||
for _, t := range p.Types {
|
||||
tags := genclientTags(t)
|
||||
hasApply := tags.HasVerb("apply") || tags.HasVerb("applyStatus")
|
||||
if tags.GenerateClient && hasApply {
|
||||
openAPIType := friendlyName(typeName(t))
|
||||
gvk := gvk{
|
||||
group: gv.Group.String(),
|
||||
version: gv.Version.String(),
|
||||
kind: t.Name.Name,
|
||||
}
|
||||
rootDefs[openAPIType] = openAPISchema.Definitions[openAPIType]
|
||||
gvkToOpenAPIType[gvk] = openAPIType
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Trim the schema down to just the types needed by client-go for apply.
|
||||
requiredDefs := make(map[string]spec.Schema)
|
||||
for name, def := range rootDefs {
|
||||
requiredDefs[name] = def
|
||||
findReferenced(&def, openAPISchema.Definitions, requiredDefs)
|
||||
}
|
||||
openAPISchema.Definitions = requiredDefs
|
||||
|
||||
// Convert the openAPI schema to the models format and validate it.
|
||||
models, err := toValidatedModels(openAPISchema)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &typeModels{models: models, gvkToOpenAPIType: gvkToOpenAPIType}, nil
|
||||
}
|
||||
|
||||
var emptyModels = &typeModels{
|
||||
models: &utilproto.Definitions{},
|
||||
gvkToOpenAPIType: map[gvk]string{},
|
||||
}
|
||||
|
||||
func toValidatedModels(openAPISchema *spec.Swagger) (utilproto.Models, error) {
|
||||
// openapi_v2.NewDocument only accepts a yaml.MapSlice
|
||||
// so we do an inefficient marshal back to json and then read it back in as yaml
|
||||
// but get the benefit of running the models through utilproto.NewOpenAPIData to
|
||||
// validate all the references between types
|
||||
rawMinimalOpenAPISchema, err := json.Marshal(openAPISchema)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to unmarshal openAPI as JSON: %w", err)
|
||||
}
|
||||
var info yaml.MapSlice
|
||||
err = yaml.Unmarshal(rawMinimalOpenAPISchema, &info)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to parse OpenAPI file: %w", err)
|
||||
}
|
||||
document, err := openapiv2.NewDocument(info, compiler.NewContext("$root", nil))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to OpenAPI document for file: %w", err)
|
||||
}
|
||||
// Construct the models and validate all references are valid.
|
||||
models, err := utilproto.NewOpenAPIData(document)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to create OpenAPI models for file: %w", err)
|
||||
}
|
||||
return models, nil
|
||||
}
|
||||
|
||||
// findReferenced recursively finds all schemas referenced from the given def.
|
||||
// toValidatedModels makes sure no references get missed.
|
||||
func findReferenced(def *spec.Schema, allSchemas, referencedOut map[string]spec.Schema) {
|
||||
// follow $ref, if any
|
||||
refPtr := def.Ref.GetPointer()
|
||||
if refPtr != nil && !refPtr.IsEmpty() {
|
||||
name := refPtr.String()
|
||||
if !strings.HasPrefix(name, "/definitions/") {
|
||||
return
|
||||
}
|
||||
name = strings.TrimPrefix(name, "/definitions/")
|
||||
schema, ok := allSchemas[name]
|
||||
if !ok {
|
||||
panic(fmt.Sprintf("allSchemas schema is missing referenced type: %s", name))
|
||||
}
|
||||
if _, ok := referencedOut[name]; !ok {
|
||||
referencedOut[name] = schema
|
||||
findReferenced(&schema, allSchemas, referencedOut)
|
||||
}
|
||||
}
|
||||
|
||||
// follow any nested schemas
|
||||
if def.Items != nil {
|
||||
if def.Items.Schema != nil {
|
||||
findReferenced(def.Items.Schema, allSchemas, referencedOut)
|
||||
}
|
||||
for _, item := range def.Items.Schemas {
|
||||
findReferenced(&item, allSchemas, referencedOut)
|
||||
}
|
||||
}
|
||||
if def.AllOf != nil {
|
||||
for _, s := range def.AllOf {
|
||||
findReferenced(&s, allSchemas, referencedOut)
|
||||
}
|
||||
}
|
||||
if def.AnyOf != nil {
|
||||
for _, s := range def.AnyOf {
|
||||
findReferenced(&s, allSchemas, referencedOut)
|
||||
}
|
||||
}
|
||||
if def.OneOf != nil {
|
||||
for _, s := range def.OneOf {
|
||||
findReferenced(&s, allSchemas, referencedOut)
|
||||
}
|
||||
}
|
||||
if def.Not != nil {
|
||||
findReferenced(def.Not, allSchemas, referencedOut)
|
||||
}
|
||||
if def.Properties != nil {
|
||||
for _, prop := range def.Properties {
|
||||
findReferenced(&prop, allSchemas, referencedOut)
|
||||
}
|
||||
}
|
||||
if def.AdditionalProperties != nil && def.AdditionalProperties.Schema != nil {
|
||||
findReferenced(def.AdditionalProperties.Schema, allSchemas, referencedOut)
|
||||
}
|
||||
if def.PatternProperties != nil {
|
||||
for _, s := range def.PatternProperties {
|
||||
findReferenced(&s, allSchemas, referencedOut)
|
||||
}
|
||||
}
|
||||
if def.Dependencies != nil {
|
||||
for _, d := range def.Dependencies {
|
||||
if d.Schema != nil {
|
||||
findReferenced(d.Schema, allSchemas, referencedOut)
|
||||
}
|
||||
}
|
||||
}
|
||||
if def.AdditionalItems != nil && def.AdditionalItems.Schema != nil {
|
||||
findReferenced(def.AdditionalItems.Schema, allSchemas, referencedOut)
|
||||
}
|
||||
if def.Definitions != nil {
|
||||
for _, s := range def.Definitions {
|
||||
findReferenced(&s, allSchemas, referencedOut)
|
||||
}
|
||||
}
|
||||
}
|
@ -17,6 +17,7 @@ limitations under the License.
|
||||
package generators
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"sort"
|
||||
@ -60,9 +61,13 @@ func Packages(context *generator.Context, arguments *args.GeneratorArgs) generat
|
||||
}
|
||||
|
||||
pkgTypes := packageTypesForInputDirs(context, arguments.InputDirs, arguments.OutputPackagePath)
|
||||
initialTypes := arguments.CustomArgs.(*applygenargs.CustomArgs).ExternalApplyConfigurations
|
||||
customArgs := arguments.CustomArgs.(*applygenargs.CustomArgs)
|
||||
initialTypes := customArgs.ExternalApplyConfigurations
|
||||
refs := refGraphForReachableTypes(pkgTypes, initialTypes)
|
||||
|
||||
typeModels, err := newTypeModels(customArgs.OpenAPISchemaFilePath, pkgTypes)
|
||||
if err != nil {
|
||||
klog.Fatalf("Failed build type models from typeModels %s: %v", customArgs.OpenAPISchemaFilePath, err)
|
||||
}
|
||||
groupVersions := make(map[string]clientgentypes.GroupVersions)
|
||||
groupGoNames := make(map[string]string)
|
||||
applyConfigsForGroupVersion := make(map[clientgentypes.GroupVersion][]applyConfig)
|
||||
@ -88,7 +93,7 @@ func Packages(context *generator.Context, arguments *args.GeneratorArgs) generat
|
||||
sort.Sort(applyConfigSort(toGenerate))
|
||||
|
||||
// generate the apply configurations
|
||||
packageList = append(packageList, generatorForApplyConfigurationsPackage(arguments.OutputPackagePath, boilerplate, pkgType, gv, toGenerate, refs))
|
||||
packageList = append(packageList, generatorForApplyConfigurationsPackage(arguments.OutputPackagePath, boilerplate, pkgType, gv, toGenerate, refs, typeModels))
|
||||
|
||||
// group all the generated apply configurations by gv so ForKind() can be generated
|
||||
groupPackageName := gv.Group.NonEmpty()
|
||||
@ -111,17 +116,50 @@ func Packages(context *generator.Context, arguments *args.GeneratorArgs) generat
|
||||
|
||||
// generate ForKind() utility function
|
||||
packageList = append(packageList, generatorForUtils(arguments.OutputPackagePath, boilerplate, groupVersions, applyConfigsForGroupVersion, groupGoNames))
|
||||
// generate internal embedded schema, required for generated Extract functions
|
||||
packageList = append(packageList, generatorForInternal(filepath.Join(arguments.OutputPackagePath, "internal"), boilerplate, typeModels))
|
||||
|
||||
return packageList
|
||||
}
|
||||
|
||||
func generatorForApplyConfigurationsPackage(outputPackagePath string, boilerplate []byte, packageName types.Name, gv clientgentypes.GroupVersion, typesToGenerate []applyConfig, refs refGraph) *generator.DefaultPackage {
|
||||
func friendlyName(name string) string {
|
||||
nameParts := strings.Split(name, "/")
|
||||
// Reverse first part. e.g., io.k8s... instead of k8s.io...
|
||||
if len(nameParts) > 0 && strings.Contains(nameParts[0], ".") {
|
||||
parts := strings.Split(nameParts[0], ".")
|
||||
for i, j := 0, len(parts)-1; i < j; i, j = i+1, j-1 {
|
||||
parts[i], parts[j] = parts[j], parts[i]
|
||||
}
|
||||
nameParts[0] = strings.Join(parts, ".")
|
||||
}
|
||||
return strings.Join(nameParts, ".")
|
||||
}
|
||||
|
||||
func typeName(t *types.Type) string {
|
||||
typePackage := t.Name.Package
|
||||
if strings.Contains(typePackage, "/vendor/") {
|
||||
typePackage = typePackage[strings.Index(typePackage, "/vendor/")+len("/vendor/"):]
|
||||
}
|
||||
return fmt.Sprintf("%s.%s", typePackage, t.Name.Name)
|
||||
}
|
||||
|
||||
func generatorForApplyConfigurationsPackage(outputPackagePath string, boilerplate []byte, packageName types.Name, gv clientgentypes.GroupVersion, typesToGenerate []applyConfig, refs refGraph, models *typeModels) *generator.DefaultPackage {
|
||||
return &generator.DefaultPackage{
|
||||
PackageName: gv.Version.PackageName(),
|
||||
PackagePath: packageName.Package,
|
||||
HeaderText: boilerplate,
|
||||
GeneratorFunc: func(c *generator.Context) (generators []generator.Generator) {
|
||||
for _, toGenerate := range typesToGenerate {
|
||||
var openAPIType *string
|
||||
gvk := gvk{
|
||||
group: gv.Group.String(),
|
||||
version: gv.Version.String(),
|
||||
kind: toGenerate.Type.Name.Name,
|
||||
}
|
||||
if v, ok := models.gvkToOpenAPIType[gvk]; ok {
|
||||
openAPIType = &v
|
||||
}
|
||||
|
||||
generators = append(generators, &applyConfigurationGenerator{
|
||||
DefaultGen: generator.DefaultGen{
|
||||
OptionalName: strings.ToLower(toGenerate.Type.Name.Name),
|
||||
@ -132,6 +170,7 @@ func generatorForApplyConfigurationsPackage(outputPackagePath string, boilerplat
|
||||
applyConfig: toGenerate,
|
||||
imports: generator.NewImportTracker(),
|
||||
refGraph: refs,
|
||||
openAPIType: openAPIType,
|
||||
})
|
||||
}
|
||||
return generators
|
||||
@ -160,6 +199,25 @@ func generatorForUtils(outPackagePath string, boilerplate []byte, groupVersions
|
||||
}
|
||||
}
|
||||
|
||||
func generatorForInternal(outPackagePath string, boilerplate []byte, models *typeModels) *generator.DefaultPackage {
|
||||
return &generator.DefaultPackage{
|
||||
PackageName: filepath.Base(outPackagePath),
|
||||
PackagePath: outPackagePath,
|
||||
HeaderText: boilerplate,
|
||||
GeneratorFunc: func(c *generator.Context) (generators []generator.Generator) {
|
||||
generators = append(generators, &internalGenerator{
|
||||
DefaultGen: generator.DefaultGen{
|
||||
OptionalName: "internal",
|
||||
},
|
||||
outputPackage: outPackagePath,
|
||||
imports: generator.NewImportTracker(),
|
||||
typeModels: models,
|
||||
})
|
||||
return generators
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func goName(gv clientgentypes.GroupVersion, p *types.Package) string {
|
||||
goName := namer.IC(strings.Split(gv.Group.NonEmpty(), ".")[0])
|
||||
if override := types.ExtractCommentTags("+", p.Comments)["groupGoName"]; override != nil {
|
||||
|
@ -24,4 +24,9 @@ var (
|
||||
objectMeta = types.Ref("k8s.io/apimachinery/pkg/apis/meta/v1", "ObjectMeta")
|
||||
rawExtension = types.Ref("k8s.io/apimachinery/pkg/runtime", "RawExtension")
|
||||
unknown = types.Ref("k8s.io/apimachinery/pkg/runtime", "Unknown")
|
||||
extractInto = types.Ref("k8s.io/apimachinery/pkg/util/managedfields", "ExtractInto")
|
||||
smdNewParser = types.Ref("sigs.k8s.io/structured-merge-diff/v4/typed", "NewParser")
|
||||
smdParser = types.Ref("sigs.k8s.io/structured-merge-diff/v4/typed", "Parser")
|
||||
yamlObject = types.Ref("sigs.k8s.io/structured-merge-diff/v4/typed", "YAMLObject")
|
||||
yamlUnmarshal = types.Ref("gopkg.in/yaml.v2", "Unmarshal")
|
||||
)
|
||||
|
@ -435,7 +435,7 @@ rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8
|
||||
rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
|
||||
rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
|
||||
sigs.k8s.io/structured-merge-diff/v4 v4.0.2/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw=
|
||||
sigs.k8s.io/structured-merge-diff/v4 v4.0.3 h1:4oyYo8NREp49LBBhKxEqCulFjg26rawYKrnCmg+Sr6c=
|
||||
sigs.k8s.io/structured-merge-diff/v4 v4.0.3/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw=
|
||||
sigs.k8s.io/structured-merge-diff/v4 v4.1.0 h1:C4r9BgJ98vrKnnVCjwCSXcWjWe0NKcUQkmzDXZXGwH8=
|
||||
sigs.k8s.io/structured-merge-diff/v4 v4.1.0/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw=
|
||||
sigs.k8s.io/yaml v1.2.0 h1:kr/MCeFWJWTwyaHoR9c8EjH9OumOmoF9YGiZd7lFm/Q=
|
||||
sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc=
|
||||
|
@ -6,13 +6,17 @@ go 1.16
|
||||
|
||||
require (
|
||||
github.com/emicklei/go-restful v2.9.5+incompatible // indirect
|
||||
github.com/go-openapi/spec v0.19.5 // indirect
|
||||
github.com/go-openapi/spec v0.19.5
|
||||
github.com/gogo/protobuf v1.3.2
|
||||
github.com/golang/protobuf v1.4.3 // indirect
|
||||
github.com/google/go-cmp v0.5.2 // indirect
|
||||
github.com/googleapis/gnostic v0.4.1
|
||||
github.com/json-iterator/go v1.1.10 // indirect
|
||||
github.com/kr/text v0.2.0 // indirect
|
||||
github.com/mailru/easyjson v0.7.0 // indirect
|
||||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e // indirect
|
||||
github.com/onsi/ginkgo v1.11.0 // indirect
|
||||
github.com/onsi/gomega v1.7.0 // indirect
|
||||
github.com/spf13/pflag v1.0.5
|
||||
github.com/stretchr/testify v1.6.1 // indirect
|
||||
golang.org/x/mod v0.3.1-0.20200828183125-ce943fd02449 // indirect
|
||||
@ -20,11 +24,13 @@ require (
|
||||
golang.org/x/sys v0.0.0-20210225134936-a50acf3fe073 // indirect
|
||||
golang.org/x/text v0.3.4 // indirect
|
||||
golang.org/x/tools v0.1.0 // indirect
|
||||
google.golang.org/protobuf v1.25.0 // indirect
|
||||
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f // indirect
|
||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||
gopkg.in/yaml.v2 v2.4.0
|
||||
k8s.io/gengo v0.0.0-20201214224949-b6c5ce23f027
|
||||
k8s.io/klog/v2 v2.5.0
|
||||
k8s.io/kube-openapi v0.0.0-20210305001622-591a79e4bda7
|
||||
sigs.k8s.io/structured-merge-diff/v4 v4.1.0 // indirect
|
||||
)
|
||||
|
||||
replace k8s.io/code-generator => ../code-generator
|
||||
|
76
staging/src/k8s.io/code-generator/go.sum
generated
76
staging/src/k8s.io/code-generator/go.sum
generated
@ -1,9 +1,13 @@
|
||||
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ=
|
||||
github.com/PuerkitoBio/purell v1.1.1 h1:WEQqlqaGbrPkxLJWfBwQmfEAE1Z7ONdDLqrN38tNFfI=
|
||||
github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
|
||||
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 h1:d+Bc7a5rLufV/sSk/8dngufqelfh6jnri85riMAaF/M=
|
||||
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
|
||||
github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY=
|
||||
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
||||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
@ -12,6 +16,9 @@ github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3
|
||||
github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs=
|
||||
github.com/emicklei/go-restful v2.9.5+incompatible h1:spTtZBk5DYEvbxMVutUuTyh1Ao2r4iyvLdACqsl/Ljk=
|
||||
github.com/emicklei/go-restful v2.9.5+incompatible/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs=
|
||||
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||
github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas=
|
||||
github.com/go-logr/logr v0.2.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU=
|
||||
github.com/go-logr/logr v0.4.0 h1:K7/B1jt6fIBQVd4Owv2MqGQClcgf0R266+7C/QjRcLc=
|
||||
@ -30,14 +37,34 @@ github.com/go-openapi/swag v0.19.5 h1:lTz6Ys4CmqqCQmZPBlbQENR1/GucA2bzYTE12Pw4tF
|
||||
github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=
|
||||
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
|
||||
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
|
||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
||||
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
|
||||
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
|
||||
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
|
||||
github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
|
||||
github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
|
||||
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
|
||||
github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
|
||||
github.com/golang/protobuf v1.4.3 h1:JjCZWpVbqXDqFVmTfYWEVTMIYrL/NPdPSCHPJ0T/raM=
|
||||
github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
||||
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
||||
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.2 h1:X2ev0eStA3AbceY54o37/0PQ/UWqKEiiO2dKL5OPaFM=
|
||||
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
github.com/google/gofuzz v1.1.0 h1:Hsa8mG0dQ46ij8Sl2AYJDUv1oA9/d6Vk+3LG99Oe02g=
|
||||
github.com/google/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/googleapis/gnostic v0.4.1 h1:DLJCy1n/vrD4HPjOvYcT8aYQXpPIzoRZONaYwyycI+I=
|
||||
github.com/googleapis/gnostic v0.4.1/go.mod h1:LRhVm6pbyptWbWbuZ38d1eyptfvIytN3ir6b65WBswg=
|
||||
github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI=
|
||||
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
||||
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
|
||||
github.com/json-iterator/go v1.1.10 h1:Kz6Cvnvv2wGdaG/V8yMvfkmNiXq9Ya2KUv4rouJJr68=
|
||||
github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||
@ -65,9 +92,15 @@ github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8m
|
||||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
|
||||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
|
||||
github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/ginkgo v1.11.0 h1:JAKSXpt1YjtLA7YpPiqO9ss6sNXEsPfSGdwN0UHqzrw=
|
||||
github.com/onsi/ginkgo v1.11.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA=
|
||||
github.com/onsi/gomega v1.7.0 h1:XPnZz8VVBHjVsy1vzJmRwIcSwiUO+JFfrv/xGiigmME=
|
||||
github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||
github.com/spf13/pflag v0.0.0-20170130214245-9ff6c6923cff/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
|
||||
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
|
||||
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||
@ -82,10 +115,18 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk
|
||||
golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
|
||||
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.3.1-0.20200828183125-ce943fd02449 h1:xUIPaMhvROX9dhPvRCenIJtU78+lbEenGbgqB5hfHCQ=
|
||||
golang.org/x/mod v0.3.1-0.20200828183125-ce943fd02449/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
@ -96,9 +137,14 @@ golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/
|
||||
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.0.0-20210224082022-3d97a244fca7 h1:OgUuv8lsRpBibGNbSizVwKWlysjaNzmC9gYMhPVfqFM=
|
||||
golang.org/x/net v0.0.0-20210224082022-3d97a244fca7/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190616124812-15dcb6c0061f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
@ -115,6 +161,10 @@ golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.4 h1:0YWbFKbhXG/wIiuHDSKpS0Iy7FSA+u45VtBMfQcFTTc=
|
||||
golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
|
||||
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||
golang.org/x/tools v0.0.0-20190614205625-5aca471b1d59/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20200505023115-26f46d2f7ef8/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||
@ -127,11 +177,33 @@ golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8T
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
||||
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
||||
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
|
||||
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
|
||||
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
||||
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
|
||||
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
||||
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
||||
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
|
||||
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
|
||||
google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
|
||||
google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
|
||||
google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||
google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||
google.golang.org/protobuf v1.25.0 h1:Ejskq+SyPohKW+1uil0JJMtmHCgJPJ/qWTxr8qp+R4c=
|
||||
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU=
|
||||
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4=
|
||||
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
|
||||
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
@ -140,6 +212,8 @@ gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
||||
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
k8s.io/gengo v0.0.0-20200413195148-3a45101e95ac/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0=
|
||||
k8s.io/gengo v0.0.0-20201214224949-b6c5ce23f027 h1:Uusb3oh8XcdzDF/ndlI4ToKTYVlkCSJP39SRY2mfRAw=
|
||||
k8s.io/gengo v0.0.0-20201214224949-b6c5ce23f027/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E=
|
||||
@ -150,5 +224,7 @@ k8s.io/klog/v2 v2.5.0/go.mod h1:hy9LJ/NvuK+iVyP4Ehqva4HxZG/oXyIS3n3Jmire4Ec=
|
||||
k8s.io/kube-openapi v0.0.0-20210305001622-591a79e4bda7 h1:vEx13qjvaZ4yfObSSXW7BrMc/KQBBT/Jyee8XtLf4x0=
|
||||
k8s.io/kube-openapi v0.0.0-20210305001622-591a79e4bda7/go.mod h1:wXW5VT87nVfh/iLV8FpR2uDvrFyomxbtb1KivDbvPTE=
|
||||
sigs.k8s.io/structured-merge-diff/v4 v4.0.2/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw=
|
||||
sigs.k8s.io/structured-merge-diff/v4 v4.1.0 h1:C4r9BgJ98vrKnnVCjwCSXcWjWe0NKcUQkmzDXZXGwH8=
|
||||
sigs.k8s.io/structured-merge-diff/v4 v4.1.0/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw=
|
||||
sigs.k8s.io/yaml v1.2.0 h1:kr/MCeFWJWTwyaHoR9c8EjH9OumOmoF9YGiZd7lFm/Q=
|
||||
sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc=
|
||||
|
@ -26,8 +26,10 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/google/go-cmp/cmp"
|
||||
appsv1 "k8s.io/api/apps/v1"
|
||||
v1 "k8s.io/api/core/v1"
|
||||
"k8s.io/apimachinery/pkg/api/equality"
|
||||
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
||||
"k8s.io/apimachinery/pkg/api/resource"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
@ -882,3 +884,302 @@ func TestApplyWithApplyConfiguration(t *testing.T) {
|
||||
t.Error("expected status to contain DeploymentReplicaFailure condition set by apply")
|
||||
}
|
||||
}
|
||||
|
||||
func TestExtractModifyApply(t *testing.T) {
|
||||
testCases := []struct {
|
||||
name string
|
||||
// modifyFunc modifies deployApply, defined below, after it is applied and "extracted"
|
||||
// apply is skipped if this func is nil
|
||||
modifyFunc func(apply *appsv1ac.DeploymentApplyConfiguration)
|
||||
modifyStatusFunc func(apply *appsv1ac.DeploymentApplyConfiguration) // same but for status
|
||||
// verifyAppliedFunc verifies the results of applying the applied
|
||||
// configuration after modifyFunc modifies it. Only called if modifyFunc is provided.
|
||||
verifyAppliedFunc func(applied *appsv1ac.DeploymentApplyConfiguration)
|
||||
verifyStatusAppliedFunc func(applied *appsv1ac.DeploymentApplyConfiguration) // same but for status
|
||||
}{
|
||||
{
|
||||
// With<fieldname>() on a scalar field replaces it with the given value
|
||||
name: "modify-scalar",
|
||||
modifyFunc: func(apply *appsv1ac.DeploymentApplyConfiguration) {
|
||||
apply.Spec.WithReplicas(2)
|
||||
},
|
||||
verifyAppliedFunc: func(applied *appsv1ac.DeploymentApplyConfiguration) {
|
||||
if *applied.Spec.Replicas != 2 {
|
||||
t.Errorf("Expected 2 replicas but got: %d", *applied.Spec.Replicas)
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
// With<fieldname>() on a non-empty struct field replaces the entire struct
|
||||
name: "modify-struct",
|
||||
modifyFunc: func(apply *appsv1ac.DeploymentApplyConfiguration) {
|
||||
apply.Spec.Template.WithSpec(corev1ac.PodSpec(). // replace the Spec of the existing Template
|
||||
WithContainers(
|
||||
corev1ac.Container().
|
||||
WithName("modify-struct").
|
||||
WithImage("nginx:1.14.3"),
|
||||
),
|
||||
)
|
||||
},
|
||||
verifyAppliedFunc: func(applied *appsv1ac.DeploymentApplyConfiguration) {
|
||||
containers := applied.Spec.Template.Spec.Containers
|
||||
if len(containers) != 1 {
|
||||
t.Errorf("Expected 1 container but got %d", len(containers))
|
||||
}
|
||||
if *containers[0].Name != "modify-struct" {
|
||||
t.Errorf("Expected container name modify-struct but got: %s", *containers[0].Name)
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
// With<fieldname>() on a non-empty map field puts all the given entries into the existing map
|
||||
name: "modify-map",
|
||||
modifyFunc: func(apply *appsv1ac.DeploymentApplyConfiguration) {
|
||||
apply.WithLabels(map[string]string{"label2": "value2"})
|
||||
},
|
||||
verifyAppliedFunc: func(applied *appsv1ac.DeploymentApplyConfiguration) {
|
||||
labels := applied.Labels
|
||||
if len(labels) != 2 {
|
||||
t.Errorf("Expected 2 label but got %d", len(labels))
|
||||
}
|
||||
if labels["label2"] != "value2" {
|
||||
t.Errorf("Expected container name value2 but got: %s", labels["label2"])
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
// With<fieldname>() on a non-empty slice field appends all the given items to the existing slice
|
||||
name: "modify-slice",
|
||||
modifyFunc: func(apply *appsv1ac.DeploymentApplyConfiguration) {
|
||||
apply.Spec.Template.Spec.WithContainers(corev1ac.Container().
|
||||
WithName("modify-slice").
|
||||
WithImage("nginx:1.14.2"),
|
||||
)
|
||||
},
|
||||
verifyAppliedFunc: func(applied *appsv1ac.DeploymentApplyConfiguration) {
|
||||
containers := applied.Spec.Template.Spec.Containers
|
||||
if len(containers) != 2 {
|
||||
t.Errorf("Expected 2 containers but got %d", len(containers))
|
||||
}
|
||||
if *containers[0].Name != "initial-container" {
|
||||
t.Errorf("Expected container name initial-container but got: %s", *containers[0].Name)
|
||||
}
|
||||
if *containers[1].Name != "modify-slice" {
|
||||
t.Errorf("Expected container name modify-slice but got: %s", *containers[1].Name)
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
// Append a condition to the status if the object
|
||||
name: "modify-status-conditions",
|
||||
modifyStatusFunc: func(apply *appsv1ac.DeploymentApplyConfiguration) {
|
||||
apply.WithStatus(appsv1ac.DeploymentStatus().
|
||||
WithConditions(appsv1ac.DeploymentCondition().
|
||||
WithType(appsv1.DeploymentProgressing).
|
||||
WithStatus(v1.ConditionUnknown).
|
||||
WithLastTransitionTime(metav1.Now()).
|
||||
WithLastUpdateTime(metav1.Now()).
|
||||
WithMessage("progressing").
|
||||
WithReason("TestExtractModifyApply_Status"),
|
||||
),
|
||||
)
|
||||
},
|
||||
verifyStatusAppliedFunc: func(applied *appsv1ac.DeploymentApplyConfiguration) {
|
||||
conditions := applied.Status.Conditions
|
||||
if len(conditions) != 1 {
|
||||
t.Errorf("Expected 1 conditions but got %d", len(conditions))
|
||||
}
|
||||
if *conditions[0].Type != appsv1.DeploymentProgressing {
|
||||
t.Errorf("Expected condition name DeploymentProgressing but got: %s", *conditions[0].Type)
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
testServer := kubeapiservertesting.StartTestServerOrDie(t, nil, []string{"--disable-admission-plugins", "ServiceAccount"}, framework.SharedEtcd())
|
||||
defer testServer.TearDownFn()
|
||||
c := clientset.NewForConfigOrDie(testServer.ClientConfig)
|
||||
deploymentClient := c.AppsV1().Deployments("default")
|
||||
fieldMgr := "test-mgr"
|
||||
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
// Applied at the started of each test
|
||||
deployApply := appsv1ac.Deployment(tc.name, "default").
|
||||
WithLabels(map[string]string{"label1": "value1"}).
|
||||
WithSpec(appsv1ac.DeploymentSpec().
|
||||
WithSelector(metav1ac.LabelSelector().
|
||||
WithMatchLabels(map[string]string{"app": tc.name}),
|
||||
).
|
||||
WithTemplate(corev1ac.PodTemplateSpec().
|
||||
WithLabels(map[string]string{"app": tc.name}).
|
||||
WithSpec(corev1ac.PodSpec().
|
||||
WithContainers(
|
||||
corev1ac.Container().
|
||||
WithName("initial-container").
|
||||
WithImage("nginx:1.14.2"),
|
||||
),
|
||||
),
|
||||
),
|
||||
)
|
||||
actual, err := deploymentClient.Apply(context.TODO(), deployApply, metav1.ApplyOptions{FieldManager: fieldMgr})
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to apply: %v", err)
|
||||
}
|
||||
|
||||
extractedDeployment, err := appsv1ac.ExtractDeployment(actual, fieldMgr)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to extract: %v", err)
|
||||
}
|
||||
|
||||
if tc.modifyFunc != nil {
|
||||
tc.modifyFunc(extractedDeployment)
|
||||
result, err := deploymentClient.Apply(context.TODO(), extractedDeployment, metav1.ApplyOptions{FieldManager: fieldMgr})
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to apply extracted apply configuration: %v", err)
|
||||
}
|
||||
extractedResult, err := appsv1ac.ExtractDeployment(result, fieldMgr)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to extract: %v", err)
|
||||
}
|
||||
if tc.verifyAppliedFunc != nil {
|
||||
tc.verifyAppliedFunc(extractedResult)
|
||||
}
|
||||
}
|
||||
|
||||
if tc.modifyStatusFunc != nil {
|
||||
tc.modifyStatusFunc(extractedDeployment)
|
||||
result, err := deploymentClient.ApplyStatus(context.TODO(), extractedDeployment, metav1.ApplyOptions{FieldManager: fieldMgr})
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to apply extracted apply configuration to status: %v", err)
|
||||
}
|
||||
extractedResult, err := appsv1ac.ExtractDeployment(result, fieldMgr)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to extract: %v", err)
|
||||
}
|
||||
if tc.verifyStatusAppliedFunc != nil {
|
||||
tc.verifyStatusAppliedFunc(extractedResult)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestExtractModifyApply_ForceOwnership(t *testing.T) {
|
||||
testServer := kubeapiservertesting.StartTestServerOrDie(t, nil, []string{"--disable-admission-plugins", "ServiceAccount"}, framework.SharedEtcd())
|
||||
defer testServer.TearDownFn()
|
||||
c := clientset.NewForConfigOrDie(testServer.ClientConfig)
|
||||
deploymentClient := c.AppsV1().Deployments("default")
|
||||
|
||||
// apply an initial state with one field manager
|
||||
createApply := appsv1ac.Deployment("nginx-apply", "default").
|
||||
WithSpec(appsv1ac.DeploymentSpec().
|
||||
WithSelector(metav1ac.LabelSelector().
|
||||
WithMatchLabels(map[string]string{"app": "nginx"}),
|
||||
).
|
||||
WithTemplate(corev1ac.PodTemplateSpec().
|
||||
WithLabels(map[string]string{"app": "nginx"}).
|
||||
WithSpec(corev1ac.PodSpec().
|
||||
WithContainers(
|
||||
corev1ac.Container().
|
||||
WithName("nginx").
|
||||
WithImage("nginx:1.14.2").
|
||||
WithWorkingDir("/tmp/v1"),
|
||||
),
|
||||
),
|
||||
),
|
||||
)
|
||||
|
||||
_, err := deploymentClient.Apply(context.TODO(), createApply, metav1.ApplyOptions{FieldManager: "create-mgr", Force: true})
|
||||
if err != nil {
|
||||
t.Fatalf("Error creating createApply: %v", err)
|
||||
}
|
||||
|
||||
// apply some non-overlapping fields with another field manager
|
||||
sidecarApply := appsv1ac.Deployment("nginx-apply", "default").
|
||||
WithSpec(appsv1ac.DeploymentSpec().
|
||||
WithTemplate(corev1ac.PodTemplateSpec().
|
||||
WithSpec(corev1ac.PodSpec().
|
||||
WithContainers(
|
||||
corev1ac.Container().
|
||||
WithName("sidecar").
|
||||
WithImage("nginx:1.14.2"),
|
||||
),
|
||||
),
|
||||
),
|
||||
)
|
||||
|
||||
applied, err := deploymentClient.Apply(context.TODO(), sidecarApply, metav1.ApplyOptions{FieldManager: "sidecar-mgr", Force: true})
|
||||
if err != nil {
|
||||
t.Fatalf("Error applying createApply: %v", err)
|
||||
}
|
||||
sidecarExtracted, err := appsv1ac.ExtractDeployment(applied, "sidecar-mgr")
|
||||
if err != nil {
|
||||
t.Fatalf("Error extracting createApply apply configuration: %v", err)
|
||||
}
|
||||
if !equality.Semantic.DeepEqual(sidecarApply, sidecarExtracted) {
|
||||
t.Errorf("Expected sidecarExtracted apply configuration to match original, but got:\n%s\n", cmp.Diff(sidecarApply, sidecarExtracted))
|
||||
}
|
||||
|
||||
// modify the extracted apply configuration that was just applied and add some fields that overlap
|
||||
// with the fields owned by the other field manager to force ownership of them
|
||||
sidecarExtracted.Spec.Template.Spec.Containers[0].WithImage("nginx:1.14.3")
|
||||
sidecarExtracted.Spec.Template.Spec.WithContainers(corev1ac.Container().
|
||||
WithName("nginx").
|
||||
WithWorkingDir("/tmp/v2"),
|
||||
)
|
||||
reapplied, err := deploymentClient.Apply(context.TODO(), sidecarExtracted, metav1.ApplyOptions{FieldManager: "sidecar-mgr", Force: true})
|
||||
if err != nil {
|
||||
t.Fatalf("Unexpected error when applying manifest for Deployment: %v", err)
|
||||
}
|
||||
|
||||
// extract apply configurations for both field managers and check that they are what we expect
|
||||
reappliedExtracted, err := appsv1ac.ExtractDeployment(reapplied, "sidecar-mgr")
|
||||
if err != nil {
|
||||
t.Fatalf("Error extracting sidecarExtracted apply configuration: %v", err)
|
||||
}
|
||||
|
||||
expectedReappliedExtracted := appsv1ac.Deployment("nginx-apply", "default").
|
||||
WithSpec(appsv1ac.DeploymentSpec().
|
||||
WithTemplate(corev1ac.PodTemplateSpec().
|
||||
WithSpec(corev1ac.PodSpec().
|
||||
WithContainers(
|
||||
corev1ac.Container().
|
||||
WithName("nginx").
|
||||
WithWorkingDir("/tmp/v2"),
|
||||
corev1ac.Container().
|
||||
WithName("sidecar").
|
||||
WithImage("nginx:1.14.3"),
|
||||
),
|
||||
),
|
||||
),
|
||||
)
|
||||
if !equality.Semantic.DeepEqual(expectedReappliedExtracted, reappliedExtracted) {
|
||||
t.Errorf("Reapplied apply configuration did not match expected, got:\n%s\n", cmp.Diff(expectedReappliedExtracted, reappliedExtracted))
|
||||
}
|
||||
|
||||
createMgrExtracted, err := appsv1ac.ExtractDeployment(reapplied, "create-mgr")
|
||||
if err != nil {
|
||||
t.Fatalf("Error extracting createApply apply configuration: %v", err)
|
||||
}
|
||||
|
||||
expectedCreateExtracted := appsv1ac.Deployment("nginx-apply", "default").
|
||||
WithSpec(appsv1ac.DeploymentSpec().
|
||||
WithSelector(metav1ac.LabelSelector().
|
||||
WithMatchLabels(map[string]string{"app": "nginx"}),
|
||||
).
|
||||
WithTemplate(corev1ac.PodTemplateSpec().
|
||||
WithLabels(map[string]string{"app": "nginx"}).
|
||||
WithSpec(corev1ac.PodSpec().
|
||||
WithContainers(
|
||||
corev1ac.Container().
|
||||
WithName("nginx").
|
||||
WithImage("nginx:1.14.2"),
|
||||
),
|
||||
),
|
||||
),
|
||||
)
|
||||
if !equality.Semantic.DeepEqual(expectedCreateExtracted, createMgrExtracted) {
|
||||
t.Errorf("createMgrExtracted apply configuration did not match expected, got:\n%s\n", cmp.Diff(expectedCreateExtracted, createMgrExtracted))
|
||||
}
|
||||
}
|
||||
|
2
vendor/modules.txt
vendored
2
vendor/modules.txt
vendored
@ -1722,6 +1722,7 @@ k8s.io/apimachinery/pkg/util/httpstream/spdy
|
||||
k8s.io/apimachinery/pkg/util/intstr
|
||||
k8s.io/apimachinery/pkg/util/json
|
||||
k8s.io/apimachinery/pkg/util/jsonmergepatch
|
||||
k8s.io/apimachinery/pkg/util/managedfields
|
||||
k8s.io/apimachinery/pkg/util/mergepatch
|
||||
k8s.io/apimachinery/pkg/util/naming
|
||||
k8s.io/apimachinery/pkg/util/net
|
||||
@ -1927,6 +1928,7 @@ k8s.io/client-go/applyconfigurations/extensions/v1beta1
|
||||
k8s.io/client-go/applyconfigurations/flowcontrol/v1alpha1
|
||||
k8s.io/client-go/applyconfigurations/flowcontrol/v1beta1
|
||||
k8s.io/client-go/applyconfigurations/imagepolicy/v1alpha1
|
||||
k8s.io/client-go/applyconfigurations/internal
|
||||
k8s.io/client-go/applyconfigurations/meta/v1
|
||||
k8s.io/client-go/applyconfigurations/networking/v1
|
||||
k8s.io/client-go/applyconfigurations/networking/v1beta1
|
||||
|
Loading…
Reference in New Issue
Block a user