mirror of
https://github.com/kubernetes-sigs/kustomize.git
synced 2026-07-18 02:01:29 +00:00
Merge branch 'master' into transformer-no-create-arrays
This commit is contained in:
@@ -1,42 +0,0 @@
|
||||
/*
|
||||
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 config
|
||||
|
||||
// Annotation is to mark a field as annotations.
|
||||
// "x-kubernetes-annotation": ""
|
||||
const Annotation = "x-kubernetes-annotation"
|
||||
|
||||
// LabelSelector is to mark a field as LabelSelector
|
||||
// "x-kubernetes-label-selector": ""
|
||||
const LabelSelector = "x-kubernetes-label-selector"
|
||||
|
||||
// Identity is to mark a field as Identity
|
||||
// "x-kubernetes-identity": ""
|
||||
const Identity = "x-kubernetes-identity"
|
||||
|
||||
// Version marks the type version of an object ref field
|
||||
// "x-kubernetes-object-ref-api-version": <apiVersion name>
|
||||
const Version = "x-kubernetes-object-ref-api-version"
|
||||
|
||||
// Kind marks the type name of an object ref field
|
||||
// "x-kubernetes-object-ref-kind": <kind name>
|
||||
const Kind = "x-kubernetes-object-ref-kind"
|
||||
|
||||
// NameKey marks the field key that refers to an object of an object ref field
|
||||
// "x-kubernetes-object-ref-name-key": "name"
|
||||
// default is "name"
|
||||
const NameKey = "x-kubernetes-object-ref-name-key"
|
||||
@@ -130,6 +130,11 @@ commonLabels:
|
||||
group: batch
|
||||
kind: CronJob
|
||||
|
||||
- path: spec/jobTemplate/metadata/labels
|
||||
create: true
|
||||
group: batch
|
||||
kind: CronJob
|
||||
|
||||
- path: spec/jobTemplate/spec/template/metadata/labels
|
||||
create: true
|
||||
group: batch
|
||||
|
||||
@@ -31,6 +31,7 @@ func GetDefaultFieldSpecs() []byte {
|
||||
[]byte(namespaceFieldSpecs),
|
||||
[]byte(varReferenceFieldSpecs),
|
||||
[]byte(nameReferenceFieldSpecs),
|
||||
[]byte(imagesFieldSpecs),
|
||||
}
|
||||
return bytes.Join(configData, []byte("\n"))
|
||||
}
|
||||
@@ -45,5 +46,6 @@ func GetDefaultFieldSpecsAsMap() map[string]string {
|
||||
result["namespace"] = namespaceFieldSpecs
|
||||
result["varreference"] = varReferenceFieldSpecs
|
||||
result["namereference"] = nameReferenceFieldSpecs
|
||||
result["images"] = imagesFieldSpecs
|
||||
return result
|
||||
}
|
||||
|
||||
23
pkg/transformers/config/defaultconfig/images.go
Normal file
23
pkg/transformers/config/defaultconfig/images.go
Normal file
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
Copyright 2019 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 defaultconfig
|
||||
|
||||
const (
|
||||
// imageFieldSpecs is left empty since `containers` and `initContainers`
|
||||
// of *ANY* kind in *ANY* path are builtin supported in code
|
||||
imagesFieldSpecs = ``
|
||||
)
|
||||
@@ -108,13 +108,15 @@ nameReference:
|
||||
kind: Job
|
||||
- path: spec/jobTemplate/spec/template/spec/volumes/configMap/name
|
||||
kind: CronJob
|
||||
- path: spec/jobTemplate/spec/template/spec/volumes/projected/sources/configMap/name
|
||||
kind: CronJob
|
||||
- path: spec/jobTemplate/spec/template/spec/containers/env/valueFrom/configMapKeyRef/name
|
||||
kind: CronJob
|
||||
- path: spec/jobTemplate/spec/template/spec/initContainers/env/valueFrom/configMapKeyRef/name
|
||||
kind: CronJob
|
||||
- path: spec/jobTemplate/spec/template/spec/containers/envFrom/configMapRef/name
|
||||
kind: CronJob
|
||||
- path: spec/jobTemplate/spec/template/spec/initContainers/envFrom/configmapRef/name
|
||||
- path: spec/jobTemplate/spec/template/spec/initContainers/envFrom/configMapRef/name
|
||||
kind: CronJob
|
||||
|
||||
- kind: Secret
|
||||
@@ -150,6 +152,8 @@ nameReference:
|
||||
kind: Deployment
|
||||
- path: spec/template/spec/imagePullSecrets/name
|
||||
kind: Deployment
|
||||
- path: spec/template/spec/volumes/projected/sources/secret/name
|
||||
kind: Deployment
|
||||
- path: spec/template/spec/volumes/secret/secretName
|
||||
kind: ReplicaSet
|
||||
- path: spec/template/spec/containers/env/valueFrom/secretKeyRef/name
|
||||
@@ -186,6 +190,8 @@ nameReference:
|
||||
kind: StatefulSet
|
||||
- path: spec/template/spec/imagePullSecrets/name
|
||||
kind: StatefulSet
|
||||
- path: spec/template/spec/volumes/projected/sources/secret/name
|
||||
kind: StatefulSet
|
||||
- path: spec/template/spec/volumes/secret/secretName
|
||||
kind: Job
|
||||
- path: spec/template/spec/containers/env/valueFrom/secretKeyRef/name
|
||||
@@ -200,6 +206,8 @@ nameReference:
|
||||
kind: Job
|
||||
- path: spec/jobTemplate/spec/template/spec/volumes/secret/secretName
|
||||
kind: CronJob
|
||||
- path: spec/jobTemplate/spec/template/spec/volumes/projected/sources/secret/name
|
||||
kind: CronJob
|
||||
- path: spec/jobTemplate/spec/template/spec/containers/env/valueFrom/secretKeyRef/name
|
||||
kind: CronJob
|
||||
- path: spec/jobTemplate/spec/template/spec/initContainers/env/valueFrom/secretKeyRef/name
|
||||
@@ -241,6 +249,9 @@ nameReference:
|
||||
kind: Ingress
|
||||
- path: spec/backend/serviceName
|
||||
kind: Ingress
|
||||
- path: spec/service/name
|
||||
kind: APIService
|
||||
group: apiregistration.k8s.io
|
||||
|
||||
- kind: Role
|
||||
group: rbac.authorization.k8s.io
|
||||
@@ -279,7 +290,7 @@ nameReference:
|
||||
- path: spec/jobTemplate/spec/template/spec/serviceAccountName
|
||||
kind: CronJob
|
||||
- path: spec/template/spec/serviceAccountName
|
||||
kind: job
|
||||
kind: Job
|
||||
- path: spec/template/spec/serviceAccountName
|
||||
kind: DaemonSet
|
||||
|
||||
@@ -306,5 +317,14 @@ nameReference:
|
||||
fieldSpecs:
|
||||
- path: spec/volumeName
|
||||
kind: PersistentVolumeClaim
|
||||
|
||||
- kind: StorageClass
|
||||
version: v1
|
||||
group: storage.k8s.io
|
||||
fieldSpecs:
|
||||
- path: spec/storageClassName
|
||||
kind: PersistentVolume
|
||||
- path: spec/storageClassName
|
||||
kind: PersistentVolumeClaim
|
||||
`
|
||||
)
|
||||
|
||||
@@ -19,73 +19,183 @@ package defaultconfig
|
||||
const (
|
||||
varReferenceFieldSpecs = `
|
||||
varReference:
|
||||
- path: spec/template/spec/initContainers/command
|
||||
kind: StatefulSet
|
||||
|
||||
- path: spec/template/spec/containers/command
|
||||
kind: StatefulSet
|
||||
|
||||
- path: spec/template/spec/initContainers/command
|
||||
kind: Deployment
|
||||
|
||||
- path: spec/template/spec/containers/command
|
||||
kind: Deployment
|
||||
|
||||
- path: spec/template/spec/containers/command
|
||||
kind: Job
|
||||
- path: spec/jobTemplate/spec/template/spec/containers/args
|
||||
kind: CronJob
|
||||
|
||||
- path: spec/jobTemplate/spec/template/spec/containers/command
|
||||
kind: CronJob
|
||||
|
||||
- path: spec/template/spec/initContainers/args
|
||||
kind: StatefulSet
|
||||
|
||||
- path: spec/template/spec/containers/args
|
||||
kind: StatefulSet
|
||||
|
||||
- path: spec/template/spec/initContainers/args
|
||||
kind: Deployment
|
||||
|
||||
- path: spec/template/spec/containers/args
|
||||
kind: Deployment
|
||||
|
||||
- path: spec/template/spec/containers/args
|
||||
kind: Job
|
||||
|
||||
- path: spec/jobTemplate/spec/template/spec/containers/args
|
||||
kind: CronJob
|
||||
|
||||
- path: spec/template/spec/initContainers/env/value
|
||||
kind: StatefulSet
|
||||
|
||||
- path: spec/template/spec/containers/env/value
|
||||
kind: StatefulSet
|
||||
|
||||
- path: spec/template/spec/initContainers/env/value
|
||||
kind: Deployment
|
||||
|
||||
- path: spec/template/spec/containers/env/value
|
||||
kind: Deployment
|
||||
|
||||
- path: spec/template/spec/containers/env/value
|
||||
kind: Job
|
||||
|
||||
- path: spec/jobTemplate/spec/template/spec/containers/env/value
|
||||
kind: CronJob
|
||||
|
||||
- path: spec/containers/command
|
||||
kind: Pod
|
||||
- path: spec/jobTemplate/spec/template/spec/containers/volumeMounts/mountPath
|
||||
kind: CronJob
|
||||
|
||||
- path: spec/containers/args
|
||||
kind: Pod
|
||||
- path: spec/jobTemplate/spec/template/spec/initContainers/args
|
||||
kind: CronJob
|
||||
|
||||
- path: spec/containers/env/value
|
||||
kind: Pod
|
||||
- path: spec/jobTemplate/spec/template/spec/initContainers/command
|
||||
kind: CronJob
|
||||
|
||||
- path: spec/jobTemplate/spec/template/spec/initContainers/env/value
|
||||
kind: CronJob
|
||||
|
||||
- path: spec/jobTemplate/spec/template/spec/initContainers/volumeMounts/mountPath
|
||||
kind: CronJob
|
||||
|
||||
- path: spec/template/spec/containers/args
|
||||
kind: DaemonSet
|
||||
|
||||
- path: spec/template/spec/containers/command
|
||||
kind: DaemonSet
|
||||
|
||||
- path: spec/template/spec/containers/env/value
|
||||
kind: DaemonSet
|
||||
|
||||
- path: spec/template/spec/containers/volumeMounts/mountPath
|
||||
kind: DaemonSet
|
||||
|
||||
- path: spec/template/spec/initContainers/args
|
||||
kind: DaemonSet
|
||||
|
||||
- path: spec/template/spec/initContainers/command
|
||||
kind: DaemonSet
|
||||
|
||||
- path: spec/template/spec/initContainers/env/value
|
||||
kind: DaemonSet
|
||||
|
||||
- path: spec/template/spec/initContainers/volumeMounts/mountPath
|
||||
kind: DaemonSet
|
||||
|
||||
- path: spec/template/spec/containers/args
|
||||
kind: Deployment
|
||||
|
||||
- path: spec/template/spec/containers/command
|
||||
kind: Deployment
|
||||
|
||||
- path: spec/template/spec/containers/env/value
|
||||
kind: Deployment
|
||||
|
||||
- path: spec/template/spec/containers/volumeMounts/mountPath
|
||||
kind: Deployment
|
||||
|
||||
- path: spec/template/spec/initContainers/args
|
||||
kind: Deployment
|
||||
|
||||
- path: spec/template/spec/initContainers/command
|
||||
kind: Deployment
|
||||
|
||||
- path: spec/template/spec/initContainers/env/value
|
||||
kind: Deployment
|
||||
|
||||
- path: spec/template/spec/initContainers/volumeMounts/mountPath
|
||||
kind: Deployment
|
||||
|
||||
- path: spec/rules/host
|
||||
kind: Ingress
|
||||
|
||||
- path: spec/tls/hosts
|
||||
kind: Ingress
|
||||
|
||||
- path: spec/tls/secretName
|
||||
kind: Ingress
|
||||
|
||||
- path: spec/template/spec/containers/args
|
||||
kind: Job
|
||||
|
||||
- path: spec/template/spec/containers/command
|
||||
kind: Job
|
||||
|
||||
- path: spec/template/spec/containers/env/value
|
||||
kind: Job
|
||||
|
||||
- path: spec/template/spec/containers/volumeMounts/mountPath
|
||||
kind: Job
|
||||
|
||||
- path: spec/template/spec/initContainers/args
|
||||
kind: Job
|
||||
|
||||
- path: spec/template/spec/initContainers/command
|
||||
kind: Job
|
||||
|
||||
- path: spec/template/spec/initContainers/env/value
|
||||
kind: Job
|
||||
|
||||
- path: spec/template/spec/initContainers/volumeMounts/mountPath
|
||||
kind: Job
|
||||
|
||||
- path: spec/containers/args
|
||||
kind: Pod
|
||||
|
||||
- path: spec/containers/command
|
||||
kind: Pod
|
||||
|
||||
- path: spec/containers/env/value
|
||||
kind: Pod
|
||||
|
||||
- path: spec/containers/volumeMounts/mountPath
|
||||
kind: Pod
|
||||
|
||||
- path: spec/initContainers/args
|
||||
kind: Pod
|
||||
|
||||
- path: spec/initContainers/command
|
||||
kind: Pod
|
||||
|
||||
- path: spec/initContainers/env/value
|
||||
kind: Pod
|
||||
|
||||
- path: spec/initContainers/volumeMounts/mountPath
|
||||
kind: Pod
|
||||
|
||||
- path: spec/template/spec/containers/args
|
||||
kind: ReplicaSet
|
||||
|
||||
- path: spec/template/spec/containers/command
|
||||
kind: ReplicaSet
|
||||
|
||||
- path: spec/template/spec/containers/env/value
|
||||
kind: ReplicaSet
|
||||
|
||||
- path: spec/template/spec/containers/volumeMounts/mountPath
|
||||
kind: ReplicaSet
|
||||
|
||||
- path: spec/template/spec/initContainers/args
|
||||
kind: ReplicaSet
|
||||
|
||||
- path: spec/template/spec/initContainers/command
|
||||
kind: ReplicaSet
|
||||
|
||||
- path: spec/template/spec/initContainers/env/value
|
||||
kind: ReplicaSet
|
||||
|
||||
- path: spec/template/spec/initContainers/volumeMounts/mountPath
|
||||
kind: ReplicaSet
|
||||
|
||||
- path: spec/template/spec/containers/args
|
||||
kind: StatefulSet
|
||||
|
||||
- path: spec/template/spec/containers/command
|
||||
kind: StatefulSet
|
||||
|
||||
- path: spec/template/spec/containers/env/value
|
||||
kind: StatefulSet
|
||||
|
||||
- path: spec/template/spec/containers/volumeMounts/mountPath
|
||||
kind: StatefulSet
|
||||
|
||||
- path: spec/template/spec/initContainers/args
|
||||
kind: StatefulSet
|
||||
|
||||
- path: spec/template/spec/initContainers/command
|
||||
kind: StatefulSet
|
||||
|
||||
- path: spec/template/spec/initContainers/env/value
|
||||
kind: StatefulSet
|
||||
|
||||
- path: spec/template/spec/initContainers/volumeMounts/mountPath
|
||||
kind: StatefulSet
|
||||
|
||||
- path: metadata/labels
|
||||
`
|
||||
)
|
||||
|
||||
@@ -19,9 +19,8 @@ package config
|
||||
import (
|
||||
"log"
|
||||
|
||||
"github.com/ghodss/yaml"
|
||||
"sigs.k8s.io/kustomize/pkg/ifc"
|
||||
"sigs.k8s.io/kustomize/pkg/transformers/config/defaultconfig"
|
||||
"sigs.k8s.io/yaml"
|
||||
)
|
||||
|
||||
// Factory makes instances of TransformerConfig.
|
||||
@@ -29,6 +28,21 @@ type Factory struct {
|
||||
ldr ifc.Loader
|
||||
}
|
||||
|
||||
// MakeTransformerConfig returns a merger of custom config,
|
||||
// if any, with default config.
|
||||
func MakeTransformerConfig(
|
||||
ldr ifc.Loader, paths []string) (*TransformerConfig, error) {
|
||||
t1 := MakeDefaultConfig()
|
||||
if len(paths) == 0 {
|
||||
return t1, nil
|
||||
}
|
||||
t2, err := NewFactory(ldr).FromFiles(paths)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return t1.Merge(t2)
|
||||
}
|
||||
|
||||
func NewFactory(l ifc.Loader) *Factory {
|
||||
return &Factory{ldr: l}
|
||||
}
|
||||
@@ -53,7 +67,10 @@ func (tf *Factory) FromFiles(
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
result = result.Merge(t)
|
||||
result, err = result.Merge(t)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
@@ -68,19 +85,3 @@ func makeTransformerConfigFromBytes(data []byte) (*TransformerConfig, error) {
|
||||
t.sortFields()
|
||||
return &t, nil
|
||||
}
|
||||
|
||||
// EmptyConfig returns an empty TransformerConfig object
|
||||
func (tf *Factory) EmptyConfig() *TransformerConfig {
|
||||
return &TransformerConfig{}
|
||||
}
|
||||
|
||||
// DefaultConfig returns a default TransformerConfig.
|
||||
// This should never fail, hence the Fatal panic.
|
||||
func (tf *Factory) DefaultConfig() *TransformerConfig {
|
||||
c, err := makeTransformerConfigFromBytes(
|
||||
defaultconfig.GetDefaultFieldSpecs())
|
||||
if err != nil {
|
||||
log.Fatalf("Unable to make default transformconfig: %v", err)
|
||||
}
|
||||
return c
|
||||
}
|
||||
|
||||
@@ -1,45 +1,33 @@
|
||||
/*
|
||||
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.
|
||||
*/
|
||||
// Copyright 2019 The Kubernetes Authors.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package config
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"sigs.k8s.io/kustomize/pkg/fs"
|
||||
"sigs.k8s.io/kustomize/pkg/gvk"
|
||||
"sigs.k8s.io/kustomize/pkg/ifc"
|
||||
"sigs.k8s.io/kustomize/pkg/loader"
|
||||
"testing"
|
||||
|
||||
"sigs.k8s.io/kustomize/internal/loadertest"
|
||||
"sigs.k8s.io/kustomize/pkg/gvk"
|
||||
)
|
||||
|
||||
func TestMakeDefaultTransformerConfig(t *testing.T) {
|
||||
func TestMakeDefaultConfig(t *testing.T) {
|
||||
// Confirm default can be made without fatal error inside call.
|
||||
l, _, _ := makeFakeLoaderAndOutput()
|
||||
_ = NewFactory(l).DefaultConfig()
|
||||
_ = MakeDefaultConfig()
|
||||
}
|
||||
|
||||
func makeFakeLoaderAndOutput() (ifc.Loader, *TransformerConfig, *TransformerConfig) {
|
||||
transformerConfig := `
|
||||
func TestFromFiles(t *testing.T) {
|
||||
|
||||
ldr := loadertest.NewFakeLoader("/app")
|
||||
ldr.AddFile("/app/config.yaml", []byte(`
|
||||
namePrefix:
|
||||
- path: nameprefix/path
|
||||
kind: SomeKind
|
||||
`
|
||||
fakeFS := fs.MakeFakeFS()
|
||||
fakeFS.WriteFile("/transformerconfig/test/config.yaml", []byte(transformerConfig))
|
||||
ldr := loader.NewFileLoaderAtRoot(fakeFS)
|
||||
`))
|
||||
tcfg, err := NewFactory(ldr).FromFiles([]string{"/app/config.yaml"})
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
expected := &TransformerConfig{
|
||||
NamePrefix: []FieldSpec{
|
||||
{
|
||||
@@ -48,16 +36,6 @@ namePrefix:
|
||||
},
|
||||
},
|
||||
}
|
||||
return ldr, expected, NewFactory(ldr).DefaultConfig()
|
||||
}
|
||||
|
||||
func TestMakeTransformerConfigFromFiles(t *testing.T) {
|
||||
ldr, expected, _ := makeFakeLoaderAndOutput()
|
||||
tcfg, err := NewFactory(ldr).FromFiles([]string{"transformerconfig/test/config.yaml"})
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(tcfg, expected) {
|
||||
t.Fatalf("expected %v\n but go6t %v\n", expected, tcfg)
|
||||
}
|
||||
|
||||
@@ -20,140 +20,182 @@ import (
|
||||
"encoding/json"
|
||||
"strings"
|
||||
|
||||
"github.com/ghodss/yaml"
|
||||
"github.com/go-openapi/spec"
|
||||
"github.com/pkg/errors"
|
||||
"k8s.io/kube-openapi/pkg/common"
|
||||
"sigs.k8s.io/kustomize/pkg/gvk"
|
||||
"sigs.k8s.io/kustomize/pkg/ifc"
|
||||
"sigs.k8s.io/yaml"
|
||||
)
|
||||
|
||||
// LoadCRDs parse CRD schemas from paths into a TransformerConfig
|
||||
func (tf *Factory) LoadCRDs(paths []string) (*TransformerConfig, error) {
|
||||
tc := tf.EmptyConfig()
|
||||
type myProperties map[string]spec.Schema
|
||||
type nameToApiMap map[string]common.OpenAPIDefinition
|
||||
|
||||
// LoadConfigFromCRDs parse CRD schemas from paths into a TransformerConfig
|
||||
func LoadConfigFromCRDs(
|
||||
ldr ifc.Loader, paths []string) (*TransformerConfig, error) {
|
||||
tc := MakeEmptyConfig()
|
||||
for _, path := range paths {
|
||||
otherTc, err := tf.loadCRD(path)
|
||||
content, err := ldr.Load(path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
m, err := makeNameToApiMap(content)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "unable to parse open API definition from '%s'", path)
|
||||
}
|
||||
otherTc, err := makeConfigFromApiMap(m)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
tc, err = tc.Merge(otherTc)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
tc = tc.Merge(otherTc)
|
||||
}
|
||||
return tc, nil
|
||||
}
|
||||
|
||||
func (tf *Factory) loadCRD(path string) (*TransformerConfig, error) {
|
||||
result := tf.EmptyConfig()
|
||||
content, err := tf.loader().Load(path)
|
||||
if err != nil {
|
||||
return result, err
|
||||
}
|
||||
|
||||
var types map[string]common.OpenAPIDefinition
|
||||
func makeNameToApiMap(content []byte) (result nameToApiMap, err error) {
|
||||
if content[0] == '{' {
|
||||
err = json.Unmarshal(content, &types)
|
||||
err = json.Unmarshal(content, &result)
|
||||
} else {
|
||||
err = yaml.Unmarshal(content, &types)
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
err = yaml.Unmarshal(content, &result)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
crds := getCRDs(types)
|
||||
for crd, k := range crds {
|
||||
tc := tf.EmptyConfig()
|
||||
err = loadCrdIntoConfig(
|
||||
types, crd, crd, k, []string{}, tc)
|
||||
func makeConfigFromApiMap(m nameToApiMap) (*TransformerConfig, error) {
|
||||
result := MakeEmptyConfig()
|
||||
for name, api := range m {
|
||||
if !looksLikeAk8sType(api.Schema.SchemaProps.Properties) {
|
||||
continue
|
||||
}
|
||||
tc := MakeEmptyConfig()
|
||||
err := loadCrdIntoConfig(
|
||||
tc, makeGvkFromTypeName(name), m, name, []string{})
|
||||
if err != nil {
|
||||
return result, err
|
||||
}
|
||||
result, err = result.Merge(tc)
|
||||
if err != nil {
|
||||
return result, err
|
||||
}
|
||||
result = result.Merge(tc)
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// getCRDs get all CRD types
|
||||
func getCRDs(types map[string]common.OpenAPIDefinition) map[string]gvk.Gvk {
|
||||
crds := map[string]gvk.Gvk{}
|
||||
|
||||
for typename, t := range types {
|
||||
properties := t.Schema.SchemaProps.Properties
|
||||
_, foundKind := properties["kind"]
|
||||
_, foundAPIVersion := properties["apiVersion"]
|
||||
_, foundMetadata := properties["metadata"]
|
||||
if foundKind && foundAPIVersion && foundMetadata {
|
||||
// TODO: Get Group and Version for CRD from the openAPI definition once
|
||||
// "x-kubernetes-group-version-kind" is available in CRD
|
||||
kind := strings.Split(typename, ".")[len(strings.Split(typename, "."))-1]
|
||||
crds[typename] = gvk.Gvk{Kind: kind}
|
||||
}
|
||||
}
|
||||
return crds
|
||||
// TODO: Get Group and Version for CRD from the
|
||||
// openAPI definition once
|
||||
// "x-kubernetes-group-version-kind" is available in CRD
|
||||
func makeGvkFromTypeName(n string) gvk.Gvk {
|
||||
names := strings.Split(n, ".")
|
||||
kind := names[len(names)-1]
|
||||
return gvk.Gvk{Kind: kind}
|
||||
}
|
||||
|
||||
func looksLikeAk8sType(properties myProperties) bool {
|
||||
_, ok := properties["kind"]
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
_, ok = properties["apiVersion"]
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
_, ok = properties["metadata"]
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
const (
|
||||
// "x-kubernetes-annotation": ""
|
||||
xAnnotation = "x-kubernetes-annotation"
|
||||
|
||||
// "x-kubernetes-label-selector": ""
|
||||
xLabelSelector = "x-kubernetes-label-selector"
|
||||
|
||||
// "x-kubernetes-identity": ""
|
||||
xIdentity = "x-kubernetes-identity"
|
||||
|
||||
// "x-kubernetes-object-ref-api-version": <apiVersion name>
|
||||
xVersion = "x-kubernetes-object-ref-api-version"
|
||||
|
||||
// "x-kubernetes-object-ref-kind": <kind name>
|
||||
xKind = "x-kubernetes-object-ref-kind"
|
||||
|
||||
// "x-kubernetes-object-ref-name-key": "name"
|
||||
// default is "name"
|
||||
xNameKey = "x-kubernetes-object-ref-name-key"
|
||||
)
|
||||
|
||||
// loadCrdIntoConfig loads a CRD spec into a TransformerConfig
|
||||
func loadCrdIntoConfig(
|
||||
types map[string]common.OpenAPIDefinition,
|
||||
atype string, crd string, in gvk.Gvk,
|
||||
path []string, config *TransformerConfig) error {
|
||||
if _, ok := types[crd]; !ok {
|
||||
theConfig *TransformerConfig, theGvk gvk.Gvk, theMap nameToApiMap,
|
||||
typeName string, path []string) (err error) {
|
||||
api, ok := theMap[typeName]
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
|
||||
for propname, property := range types[atype].Schema.SchemaProps.Properties {
|
||||
_, annotate := property.Extensions.GetString(Annotation)
|
||||
for propName, property := range api.Schema.SchemaProps.Properties {
|
||||
_, annotate := property.Extensions.GetString(xAnnotation)
|
||||
if annotate {
|
||||
config.AddAnnotationFieldSpec(
|
||||
FieldSpec{
|
||||
CreateIfNotPresent: false,
|
||||
Gvk: in,
|
||||
Path: strings.Join(append(path, propname), "/"),
|
||||
},
|
||||
)
|
||||
err = theConfig.AddAnnotationFieldSpec(
|
||||
makeFs(theGvk, append(path, propName)))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
_, label := property.Extensions.GetString(LabelSelector)
|
||||
_, label := property.Extensions.GetString(xLabelSelector)
|
||||
if label {
|
||||
config.AddLabelFieldSpec(
|
||||
FieldSpec{
|
||||
CreateIfNotPresent: false,
|
||||
Gvk: in,
|
||||
Path: strings.Join(append(path, propname), "/"),
|
||||
},
|
||||
)
|
||||
err = theConfig.AddLabelFieldSpec(
|
||||
makeFs(theGvk, append(path, propName)))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
_, identity := property.Extensions.GetString(Identity)
|
||||
_, identity := property.Extensions.GetString(xIdentity)
|
||||
if identity {
|
||||
config.AddPrefixFieldSpec(
|
||||
FieldSpec{
|
||||
CreateIfNotPresent: false,
|
||||
Gvk: in,
|
||||
Path: strings.Join(append(path, propname), "/"),
|
||||
},
|
||||
)
|
||||
err = theConfig.AddPrefixFieldSpec(
|
||||
makeFs(theGvk, append(path, propName)))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
version, ok := property.Extensions.GetString(Version)
|
||||
version, ok := property.Extensions.GetString(xVersion)
|
||||
if ok {
|
||||
kind, ok := property.Extensions.GetString(Kind)
|
||||
kind, ok := property.Extensions.GetString(xKind)
|
||||
if ok {
|
||||
nameKey, ok := property.Extensions.GetString(NameKey)
|
||||
nameKey, ok := property.Extensions.GetString(xNameKey)
|
||||
if !ok {
|
||||
nameKey = "name"
|
||||
}
|
||||
config.AddNamereferenceFieldSpec(NameBackReferences{
|
||||
Gvk: gvk.Gvk{Kind: kind, Version: version},
|
||||
FieldSpecs: []FieldSpec{
|
||||
{
|
||||
CreateIfNotPresent: false,
|
||||
Gvk: in,
|
||||
Path: strings.Join(append(path, propname, nameKey), "/"),
|
||||
},
|
||||
},
|
||||
})
|
||||
err = theConfig.AddNamereferenceFieldSpec(
|
||||
NameBackReferences{
|
||||
Gvk: gvk.Gvk{Kind: kind, Version: version},
|
||||
FieldSpecs: []FieldSpec{
|
||||
makeFs(theGvk, append(path, propName, nameKey))},
|
||||
})
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if property.Ref.GetURL() != nil {
|
||||
loadCrdIntoConfig(
|
||||
types, property.Ref.String(), crd, in,
|
||||
append(path, propname), config)
|
||||
theConfig, theGvk, theMap,
|
||||
property.Ref.String(), append(path, propName))
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func makeFs(in gvk.Gvk, path []string) FieldSpec {
|
||||
return FieldSpec{
|
||||
CreateIfNotPresent: false,
|
||||
Gvk: in,
|
||||
Path: strings.Join(path, "/"),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,9 +20,9 @@ import (
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"sigs.k8s.io/kustomize/internal/loadertest"
|
||||
"sigs.k8s.io/kustomize/pkg/gvk"
|
||||
"sigs.k8s.io/kustomize/pkg/ifc"
|
||||
"sigs.k8s.io/kustomize/pkg/internal/loadertest"
|
||||
)
|
||||
|
||||
// This defines two CRD's: Bee and MyKind.
|
||||
@@ -182,8 +182,7 @@ func TestLoadCRDs(t *testing.T) {
|
||||
NameReference: nbrs,
|
||||
}
|
||||
|
||||
actualTc, err := NewFactory(makeLoader(t)).LoadCRDs(
|
||||
[]string{"crd.json"})
|
||||
actualTc, err := LoadConfigFromCRDs(makeLoader(t), []string{"crd.json"})
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error:%v", err)
|
||||
}
|
||||
|
||||
@@ -57,6 +57,11 @@ func (fs FieldSpec) String() string {
|
||||
"%s:%v:%s", fs.Gvk.String(), fs.CreateIfNotPresent, fs.Path)
|
||||
}
|
||||
|
||||
// If true, the primary key is the same, but other fields might not be.
|
||||
func (fs FieldSpec) effectivelyEquals(other FieldSpec) bool {
|
||||
return fs.IsSelected(&other.Gvk) && fs.Path == other.Path
|
||||
}
|
||||
|
||||
// PathSlice converts the path string to a slice of strings,
|
||||
// separated by a '/'. Forward slash can be contained in a
|
||||
// fieldname. such as ingress.kubernetes.io/auth-secret in
|
||||
@@ -76,7 +81,6 @@ func (fs FieldSpec) PathSlice() []string {
|
||||
if !strings.Contains(fs.Path, escapedForwardSlash) {
|
||||
return strings.Split(fs.Path, "/")
|
||||
}
|
||||
|
||||
s := strings.Replace(fs.Path, escapedForwardSlash, tempSlashReplacement, -1)
|
||||
paths := strings.Split(s, "/")
|
||||
var result []string
|
||||
@@ -93,3 +97,43 @@ func (s fsSlice) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
|
||||
func (s fsSlice) Less(i, j int) bool {
|
||||
return s[i].Gvk.IsLessThan(s[j].Gvk)
|
||||
}
|
||||
|
||||
// mergeAll merges the argument into this, returning the result.
|
||||
// Items already present are ignored.
|
||||
// Items that conflict (primary key matches, but remain data differs)
|
||||
// result in an error.
|
||||
func (s fsSlice) mergeAll(incoming fsSlice) (result fsSlice, err error) {
|
||||
result = s
|
||||
for _, x := range incoming {
|
||||
result, err = result.mergeOne(x)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// mergeOne merges the argument into this, returning the result.
|
||||
// If the item's primary key is already present, and there are no
|
||||
// conflicts, it is ignored (we don't want duplicates).
|
||||
// If there is a conflict, the merge fails.
|
||||
func (s fsSlice) mergeOne(x FieldSpec) (fsSlice, error) {
|
||||
i := s.index(x)
|
||||
if i > -1 {
|
||||
// It's already there.
|
||||
if s[i].CreateIfNotPresent != x.CreateIfNotPresent {
|
||||
return nil, fmt.Errorf("conflicting fieldspecs")
|
||||
}
|
||||
return s, nil
|
||||
}
|
||||
return append(s, x), nil
|
||||
}
|
||||
|
||||
func (s fsSlice) index(fs FieldSpec) int {
|
||||
for i, x := range s {
|
||||
if x.effectivelyEquals(fs) {
|
||||
return i
|
||||
}
|
||||
}
|
||||
return -1
|
||||
}
|
||||
|
||||
@@ -17,8 +17,12 @@ limitations under the License.
|
||||
package config
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"sigs.k8s.io/kustomize/pkg/gvk"
|
||||
)
|
||||
|
||||
func TestPathSlice(t *testing.T) {
|
||||
@@ -44,3 +48,133 @@ func TestPathSlice(t *testing.T) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var mergeTests = []struct {
|
||||
name string
|
||||
original fsSlice
|
||||
incoming fsSlice
|
||||
err error
|
||||
result fsSlice
|
||||
}{
|
||||
{
|
||||
"normal",
|
||||
fsSlice{
|
||||
{
|
||||
Path: "whatever",
|
||||
Gvk: gvk.Gvk{Group: "apple"},
|
||||
CreateIfNotPresent: false,
|
||||
},
|
||||
{
|
||||
Path: "whatever",
|
||||
Gvk: gvk.Gvk{Group: "pear"},
|
||||
CreateIfNotPresent: false,
|
||||
},
|
||||
},
|
||||
fsSlice{
|
||||
{
|
||||
Path: "home",
|
||||
Gvk: gvk.Gvk{Group: "beans"},
|
||||
CreateIfNotPresent: false,
|
||||
},
|
||||
},
|
||||
nil,
|
||||
fsSlice{
|
||||
{
|
||||
Path: "whatever",
|
||||
Gvk: gvk.Gvk{Group: "apple"},
|
||||
CreateIfNotPresent: false,
|
||||
},
|
||||
{
|
||||
Path: "whatever",
|
||||
Gvk: gvk.Gvk{Group: "pear"},
|
||||
CreateIfNotPresent: false,
|
||||
},
|
||||
{
|
||||
Path: "home",
|
||||
Gvk: gvk.Gvk{Group: "beans"},
|
||||
CreateIfNotPresent: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
"ignore copy",
|
||||
fsSlice{
|
||||
{
|
||||
Path: "whatever",
|
||||
Gvk: gvk.Gvk{Group: "apple"},
|
||||
CreateIfNotPresent: false,
|
||||
},
|
||||
{
|
||||
Path: "whatever",
|
||||
Gvk: gvk.Gvk{Group: "pear"},
|
||||
CreateIfNotPresent: false,
|
||||
},
|
||||
},
|
||||
fsSlice{
|
||||
{
|
||||
Path: "whatever",
|
||||
Gvk: gvk.Gvk{Group: "apple"},
|
||||
CreateIfNotPresent: false,
|
||||
},
|
||||
},
|
||||
nil,
|
||||
fsSlice{
|
||||
{
|
||||
Path: "whatever",
|
||||
Gvk: gvk.Gvk{Group: "apple"},
|
||||
CreateIfNotPresent: false,
|
||||
},
|
||||
{
|
||||
Path: "whatever",
|
||||
Gvk: gvk.Gvk{Group: "pear"},
|
||||
CreateIfNotPresent: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
"error on conflict",
|
||||
fsSlice{
|
||||
{
|
||||
Path: "whatever",
|
||||
Gvk: gvk.Gvk{Group: "apple"},
|
||||
CreateIfNotPresent: false,
|
||||
},
|
||||
{
|
||||
Path: "whatever",
|
||||
Gvk: gvk.Gvk{Group: "pear"},
|
||||
CreateIfNotPresent: false,
|
||||
},
|
||||
},
|
||||
fsSlice{
|
||||
{
|
||||
Path: "whatever",
|
||||
Gvk: gvk.Gvk{Group: "apple"},
|
||||
CreateIfNotPresent: true,
|
||||
},
|
||||
},
|
||||
fmt.Errorf("hey"),
|
||||
fsSlice{},
|
||||
},
|
||||
}
|
||||
|
||||
func TestFsSlice_MergeAll(t *testing.T) {
|
||||
for _, item := range mergeTests {
|
||||
result, err := item.original.mergeAll(item.incoming)
|
||||
if item.err == nil {
|
||||
if err != nil {
|
||||
t.Fatalf("test %s: unexpected err %v", item.name, err)
|
||||
}
|
||||
if !reflect.DeepEqual(item.result, result) {
|
||||
t.Fatalf("test %s: expected: %v\n but got: %v\n",
|
||||
item.name, item.result, result)
|
||||
}
|
||||
} else {
|
||||
if err == nil {
|
||||
t.Fatalf("test %s: expected err: %v", item.name, err)
|
||||
}
|
||||
if !strings.Contains(err.Error(), "conflicting fieldspecs") {
|
||||
t.Fatalf("test %s: unexpected err: %v", item.name, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -52,7 +52,7 @@ import (
|
||||
// }
|
||||
type NameBackReferences struct {
|
||||
gvk.Gvk `json:",inline,omitempty" yaml:",inline,omitempty"`
|
||||
FieldSpecs []FieldSpec `json:"FieldSpecs,omitempty" yaml:"FieldSpecs,omitempty"`
|
||||
FieldSpecs fsSlice `json:"FieldSpecs,omitempty" yaml:"FieldSpecs,omitempty"`
|
||||
}
|
||||
|
||||
func (n NameBackReferences) String() string {
|
||||
@@ -72,20 +72,27 @@ func (s nbrSlice) Less(i, j int) bool {
|
||||
return s[i].Gvk.IsLessThan(s[j].Gvk)
|
||||
}
|
||||
|
||||
func (s nbrSlice) mergeAll(o nbrSlice) nbrSlice {
|
||||
result := s
|
||||
func (s nbrSlice) mergeAll(o nbrSlice) (result nbrSlice, err error) {
|
||||
result = s
|
||||
for _, r := range o {
|
||||
result = result.mergeOne(r)
|
||||
result, err = result.mergeOne(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return result
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func (s nbrSlice) mergeOne(other NameBackReferences) nbrSlice {
|
||||
func (s nbrSlice) mergeOne(other NameBackReferences) (nbrSlice, error) {
|
||||
var result nbrSlice
|
||||
var err error
|
||||
found := false
|
||||
for _, c := range s {
|
||||
if c.Gvk.Equals(other.Gvk) {
|
||||
c.FieldSpecs = append(c.FieldSpecs, other.FieldSpecs...)
|
||||
c.FieldSpecs, err = c.FieldSpecs.mergeAll(other.FieldSpecs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
found = true
|
||||
}
|
||||
result = append(result, c)
|
||||
@@ -94,5 +101,5 @@ func (s nbrSlice) mergeOne(other NameBackReferences) nbrSlice {
|
||||
if !found {
|
||||
result = append(result, other)
|
||||
}
|
||||
return result
|
||||
return result, nil
|
||||
}
|
||||
|
||||
@@ -89,17 +89,19 @@ func TestMergeAll(t *testing.T) {
|
||||
Gvk: gvk.Gvk{
|
||||
Kind: "ConfigMap",
|
||||
},
|
||||
// Current behavior allows repeats of FieldSpec
|
||||
FieldSpecs: append(fsSlice1, fsSlice1...),
|
||||
FieldSpecs: fsSlice1,
|
||||
},
|
||||
{
|
||||
Gvk: gvk.Gvk{
|
||||
Kind: "Secret",
|
||||
},
|
||||
FieldSpecs: append(fsSlice2, fsSlice2...),
|
||||
FieldSpecs: fsSlice2,
|
||||
},
|
||||
}
|
||||
actual := nbrsSlice1.mergeAll(nbrsSlice2)
|
||||
actual, err := nbrsSlice1.mergeAll(nbrsSlice2)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected err: %v", err)
|
||||
}
|
||||
if !reflect.DeepEqual(actual, expected) {
|
||||
t.Fatalf("expected\n %v\n but got\n %v\n", expected, actual)
|
||||
}
|
||||
|
||||
@@ -19,7 +19,10 @@ limitations under the License.
|
||||
package config
|
||||
|
||||
import (
|
||||
"log"
|
||||
"sort"
|
||||
|
||||
"sigs.k8s.io/kustomize/pkg/transformers/config/defaultconfig"
|
||||
)
|
||||
|
||||
// TransformerConfig holds the data needed to perform transformations.
|
||||
@@ -31,6 +34,22 @@ type TransformerConfig struct {
|
||||
CommonAnnotations fsSlice `json:"commonAnnotations,omitempty" yaml:"commonAnnotations,omitempty"`
|
||||
NameReference nbrSlice `json:"nameReference,omitempty" yaml:"nameReference,omitempty"`
|
||||
VarReference fsSlice `json:"varReference,omitempty" yaml:"varReference,omitempty"`
|
||||
Images fsSlice `json:"images,omitempty" yaml:"images,omitempty"`
|
||||
}
|
||||
|
||||
// MakeEmptyConfig returns an empty TransformerConfig object
|
||||
func MakeEmptyConfig() *TransformerConfig {
|
||||
return &TransformerConfig{}
|
||||
}
|
||||
|
||||
// MakeDefaultConfig returns a default TransformerConfig.
|
||||
func MakeDefaultConfig() *TransformerConfig {
|
||||
c, err := makeTransformerConfigFromBytes(
|
||||
defaultconfig.GetDefaultFieldSpecs())
|
||||
if err != nil {
|
||||
log.Fatalf("Unable to make default transformconfig: %v", err)
|
||||
}
|
||||
return c
|
||||
}
|
||||
|
||||
// sortFields provides determinism in logging, tests, etc.
|
||||
@@ -41,46 +60,81 @@ func (t *TransformerConfig) sortFields() {
|
||||
sort.Sort(t.CommonAnnotations)
|
||||
sort.Sort(t.NameReference)
|
||||
sort.Sort(t.VarReference)
|
||||
sort.Sort(t.Images)
|
||||
}
|
||||
|
||||
// AddPrefixFieldSpec adds a FieldSpec to NamePrefix
|
||||
func (t *TransformerConfig) AddPrefixFieldSpec(fs FieldSpec) {
|
||||
t.NamePrefix = append(t.NamePrefix, fs)
|
||||
func (t *TransformerConfig) AddPrefixFieldSpec(fs FieldSpec) (err error) {
|
||||
t.NamePrefix, err = t.NamePrefix.mergeOne(fs)
|
||||
return err
|
||||
}
|
||||
|
||||
// AddSuffixFieldSpec adds a FieldSpec to NameSuffix
|
||||
func (t *TransformerConfig) AddSuffixFieldSpec(fs FieldSpec) {
|
||||
t.NameSuffix = append([]FieldSpec{fs}, t.NameSuffix...)
|
||||
func (t *TransformerConfig) AddSuffixFieldSpec(fs FieldSpec) (err error) {
|
||||
t.NameSuffix, err = t.NameSuffix.mergeOne(fs)
|
||||
return err
|
||||
}
|
||||
|
||||
// AddLabelFieldSpec adds a FieldSpec to CommonLabels
|
||||
func (t *TransformerConfig) AddLabelFieldSpec(fs FieldSpec) {
|
||||
t.CommonLabels = append(t.CommonLabels, fs)
|
||||
func (t *TransformerConfig) AddLabelFieldSpec(fs FieldSpec) (err error) {
|
||||
t.CommonLabels, err = t.CommonLabels.mergeOne(fs)
|
||||
return err
|
||||
}
|
||||
|
||||
// AddAnnotationFieldSpec adds a FieldSpec to CommonAnnotations
|
||||
func (t *TransformerConfig) AddAnnotationFieldSpec(fs FieldSpec) {
|
||||
t.CommonAnnotations = append(t.CommonAnnotations, fs)
|
||||
func (t *TransformerConfig) AddAnnotationFieldSpec(fs FieldSpec) (err error) {
|
||||
t.CommonAnnotations, err = t.CommonAnnotations.mergeOne(fs)
|
||||
return err
|
||||
}
|
||||
|
||||
// AddNamereferenceFieldSpec adds a NameBackReferences to NameReference
|
||||
func (t *TransformerConfig) AddNamereferenceFieldSpec(nbrs NameBackReferences) {
|
||||
t.NameReference = t.NameReference.mergeOne(nbrs)
|
||||
func (t *TransformerConfig) AddNamereferenceFieldSpec(
|
||||
nbrs NameBackReferences) (err error) {
|
||||
t.NameReference, err = t.NameReference.mergeOne(nbrs)
|
||||
return err
|
||||
}
|
||||
|
||||
// Merge merges two TransformerConfigs objects into a new TransformerConfig object
|
||||
func (t *TransformerConfig) Merge(input *TransformerConfig) *TransformerConfig {
|
||||
// Merge merges two TransformerConfigs objects into
|
||||
// a new TransformerConfig object
|
||||
func (t *TransformerConfig) Merge(input *TransformerConfig) (
|
||||
merged *TransformerConfig, err error) {
|
||||
if input == nil {
|
||||
return t
|
||||
return t, nil
|
||||
}
|
||||
merged = &TransformerConfig{}
|
||||
merged.NamePrefix, err = t.NamePrefix.mergeAll(input.NamePrefix)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
merged.NameSuffix, err = t.NameSuffix.mergeAll(input.NameSuffix)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
merged.NameSpace, err = t.NameSpace.mergeAll(input.NameSpace)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
merged.CommonAnnotations, err = t.CommonAnnotations.mergeAll(
|
||||
input.CommonAnnotations)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
merged.CommonLabels, err = t.CommonLabels.mergeAll(input.CommonLabels)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
merged.VarReference, err = t.VarReference.mergeAll(input.VarReference)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
merged.NameReference, err = t.NameReference.mergeAll(input.NameReference)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
merged.Images, err = t.Images.mergeAll(input.Images)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
merged := &TransformerConfig{}
|
||||
merged.NamePrefix = append(t.NamePrefix, input.NamePrefix...)
|
||||
merged.NameSuffix = append(input.NameSuffix, t.NameSuffix...)
|
||||
merged.NameSpace = append(t.NameSpace, input.NameSpace...)
|
||||
merged.CommonAnnotations = append(t.CommonAnnotations, input.CommonAnnotations...)
|
||||
merged.CommonLabels = append(t.CommonLabels, input.CommonLabels...)
|
||||
merged.VarReference = append(t.VarReference, input.VarReference...)
|
||||
merged.NameReference = t.NameReference.mergeAll(input.NameReference)
|
||||
merged.sortFields()
|
||||
return merged
|
||||
return merged, nil
|
||||
}
|
||||
|
||||
@@ -42,7 +42,10 @@ func TestAddNamereferenceFieldSpec(t *testing.T) {
|
||||
},
|
||||
}
|
||||
|
||||
cfg.AddNamereferenceFieldSpec(nbrs)
|
||||
err := cfg.AddNamereferenceFieldSpec(nbrs)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected err: %v", err)
|
||||
}
|
||||
if len(cfg.NameReference) != 1 {
|
||||
t.Fatal("failed to add namereference FieldSpec")
|
||||
}
|
||||
@@ -57,19 +60,31 @@ func TestAddFieldSpecs(t *testing.T) {
|
||||
CreateIfNotPresent: true,
|
||||
}
|
||||
|
||||
cfg.AddPrefixFieldSpec(fieldSpec)
|
||||
err := cfg.AddPrefixFieldSpec(fieldSpec)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected err: %v", err)
|
||||
}
|
||||
if len(cfg.NamePrefix) != 1 {
|
||||
t.Fatalf("failed to add nameprefix FieldSpec")
|
||||
}
|
||||
cfg.AddSuffixFieldSpec(fieldSpec)
|
||||
err = cfg.AddSuffixFieldSpec(fieldSpec)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected err: %v", err)
|
||||
}
|
||||
if len(cfg.NameSuffix) != 1 {
|
||||
t.Fatalf("failed to add namesuffix FieldSpec")
|
||||
}
|
||||
cfg.AddLabelFieldSpec(fieldSpec)
|
||||
err = cfg.AddLabelFieldSpec(fieldSpec)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected err: %v", err)
|
||||
}
|
||||
if len(cfg.CommonLabels) != 1 {
|
||||
t.Fatalf("failed to add nameprefix FieldSpec")
|
||||
}
|
||||
cfg.AddAnnotationFieldSpec(fieldSpec)
|
||||
err = cfg.AddAnnotationFieldSpec(fieldSpec)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected err: %v", err)
|
||||
}
|
||||
if len(cfg.CommonAnnotations) != 1 {
|
||||
t.Fatalf("failed to add nameprefix FieldSpec")
|
||||
}
|
||||
@@ -128,7 +143,10 @@ func TestMerge(t *testing.T) {
|
||||
cfgb.AddPrefixFieldSpec(fieldSpecs[1])
|
||||
cfga.AddSuffixFieldSpec(fieldSpecs[1])
|
||||
|
||||
actual := cfga.Merge(cfgb)
|
||||
actual, err := cfga.Merge(cfgb)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected err: %v", err)
|
||||
}
|
||||
|
||||
if len(actual.NamePrefix) != 2 {
|
||||
t.Fatal("merge failed for namePrefix FieldSpec")
|
||||
@@ -154,7 +172,10 @@ func TestMerge(t *testing.T) {
|
||||
t.Fatalf("expected: %v\n but got: %v\n", expected, actual)
|
||||
}
|
||||
|
||||
actual = cfga.Merge(nil)
|
||||
actual, err = cfga.Merge(nil)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected err: %v", err)
|
||||
}
|
||||
if !reflect.DeepEqual(actual, cfga) {
|
||||
t.Fatalf("expected: %v\n but got: %v\n", cfga, actual)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user