move transformerconfig package to transformers/config

This commit is contained in:
Jingfang Liu
2018-10-10 14:30:31 -07:00
parent ca4a5d33f0
commit c33a97fcf2
27 changed files with 47 additions and 48 deletions

View File

@@ -0,0 +1,42 @@
/*
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"

View File

@@ -0,0 +1,60 @@
/*
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 defaultconfig
const commonAnnotationPathConfigs = `
commonAnnotations:
- path: metadata/annotations
create: true
- path: spec/template/metadata/annotations
create: true
version: v1
kind: ReplicationController
- path: spec/template/metadata/annotations
create: true
kind: Deployment
- path: spec/template/metadata/annotations
create: true
kind: ReplicaSet
- path: spec/template/metadata/annotations
create: true
kind: DaemonSet
- path: spec/template/metadata/annotations
create: true
kind: StatefulSet
- path: spec/template/metadata/annotations
create: true
group: batch
kind: Job
- path: spec/jobTemplate/metadata/annotations
create: true
group: batch
kind: CronJob
- path: spec/jobTemplate/spec/template/metadata/annotations
create: true
group: batch
kind: CronJob
`

View File

@@ -0,0 +1,152 @@
/*
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 defaultconfig
const commonLabelPathConfigs = `
commonLabels:
- path: metadata/labels
create: true
- path: spec/selector
create: true
version: v1
kind: Service
- path: spec/selector
create: true
version: v1
kind: ReplicationController
- path: spec/template/metadata/labels
create: true
version: v1
kind: ReplicationController
- path: spec/selector/matchLabels
create: true
kind: Deployment
- path: spec/template/metadata/labels
create: true
kind: Deployment
- path: spec/template/spec/affinity/podAffinity/preferredDuringSchedulingIgnoredDuringExecution/podAffinityTerm/labelSelector/matchLabels
create: false
group: apps
kind: Deployment
- path: spec/template/spec/affinity/podAffinity/requiredDuringSchedulingIgnoredDuringExecution/labelSelector/matchLabels
create: false
group: apps
kind: Deployment
- path: spec/template/spec/affinity/podAntiAffinity/preferredDuringSchedulingIgnoredDuringExecution/podAffinityTerm/labelSelector/matchLabels
create: false
group: apps
kind: Deployment
- path: spec/template/spec/affinity/podAntiAffinity/requiredDuringSchedulingIgnoredDuringExecution/labelSelector/matchLabels
create: false
group: apps
kind: Deployment
- path: spec/selector/matchLabels
create: true
kind: ReplicaSet
- path: spec/template/metadata/labels
create: true
kind: ReplicaSet
- path: spec/selector/matchLabels
create: true
kind: DaemonSet
- path: spec/template/metadata/labels
create: true
kind: DaemonSet
- path: spec/selector/matchLabels
create: true
group: apps
kind: StatefulSet
- path: spec/template/metadata/labels
create: true
group: apps
kind: StatefulSet
- path: spec/template/spec/affinity/podAffinity/preferredDuringSchedulingIgnoredDuringExecution/podAffinityTerm/labelSelector/matchLabels
create: false
group: apps
kind: StatefulSet
- path: spec/template/spec/affinity/podAffinity/requiredDuringSchedulingIgnoredDuringExecution/labelSelector/matchLabels
create: false
group: apps
kind: StatefulSet
- path: spec/template/spec/affinity/podAntiAffinity/preferredDuringSchedulingIgnoredDuringExecution/podAffinityTerm/labelSelector/matchLabels
create: false
group: apps
kind: StatefulSet
- path: spec/template/spec/affinity/podAntiAffinity/requiredDuringSchedulingIgnoredDuringExecution/labelSelector/matchLabels
create: false
group: apps
kind: StatefulSet
- path: spec/selector/matchLabels
create: false
group: batch
kind: Job
- path: spec/template/metadata/labels
create: true
group: batch
kind: Job
- path: spec/jobTemplate/spec/selector/matchLabels
create: false
group: batch
kind: CronJob
- path: spec/jobTemplate/spec/template/metadata/labels
create: true
group: batch
kind: CronJob
- path: spec/selector/matchLabels
create: false
group: policy
kind: PodDisruptionBudget
- path: spec/podSelector/matchLabels
create: false
group: networking.k8s.io
kind: NetworkPolicy
- path: spec/ingress/from/podSelector/matchLabels
create: false
group: networking.k8s.io
kind: NetworkPolicy
- path: spec/egress/to/podSelector/matchLabels
create: false
group: networking.k8s.io
kind: NetworkPolicy
`

View File

@@ -0,0 +1,48 @@
/*
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 defaultconfig provides the default
// transformer configurations
package defaultconfig
import (
"bytes"
)
// GetDefaultPathConfigs returns the default pathConfigs data
func GetDefaultPathConfigs() []byte {
configData := [][]byte{
[]byte(namePrefixPathConfigs),
[]byte(commonLabelPathConfigs),
[]byte(commonAnnotationPathConfigs),
[]byte(namespacePathConfigs),
[]byte(varReferencePathConfigs),
[]byte(nameReferencePathConfigs),
}
return bytes.Join(configData, []byte("\n"))
}
// GetDefaultPathConfigStrings returns the default pathConfigs in string format
func GetDefaultPathConfigStrings() map[string]string {
result := make(map[string]string)
result["nameprefix"] = namePrefixPathConfigs
result["commonlabels"] = commonLabelPathConfigs
result["commonannotations"] = commonAnnotationPathConfigs
result["namespace"] = namespacePathConfigs
result["varreference"] = varReferencePathConfigs
result["namereference"] = namespacePathConfigs
return result
}

View File

@@ -0,0 +1,24 @@
/*
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 defaultconfig
const (
namePrefixPathConfigs = `
namePrefix:
- path: metadata/name
`
)

View File

@@ -0,0 +1,306 @@
/*
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 defaultconfig
const (
nameReferencePathConfigs = `
nameReference:
- kind: Deployment
pathConfigs:
- path: spec/scaleTargetRef/name
kind: HorizontalPodAutoscaler
- kind: ReplicationController
pathConfigs:
- path: spec/scaleTargetRef/name
kind: HorizontalPodAutoscaler
- kind: ReplicaSet
pathConfigs:
- path: spec/scaleTargetRef/name
kind: HorizontalPodAutoscaler
- kind: ConfigMap
version: v1
pathConfigs:
- path: spec/volumes/configMap/name
version: v1
kind: Pod
- path: spec/containers/env/valueFrom/configMapKeyRef/name
version: v1
kind: Pod
- path: spec/initContainers/env/valueFrom/configMapKeyRef/name
version: v1
kind: Pod
- path: spec/containers/envFrom/configMapRef/name
version: v1
kind: Pod
- path: spec/initContainers/envFrom/configMapRef/name
version: v1
kind: Pod
- path: spec/template/spec/volumes/configMap/name
kind: Deployment
- path: spec/template/spec/containers/env/valueFrom/configMapKeyRef/name
kind: Deployment
- path: spec/template/spec/initContainers/env/valueFrom/configMapKeyRef/name
kind: Deployment
- path: spec/template/spec/containers/envFrom/configMapRef/name
kind: Deployment
- path: spec/template/spec/initContainers/envFrom/configMapRef/name
kind: Deployment
- path: spec/template/spec/volumes/projected/sources/configMap/name
kind: Deployment
- path: spec/template/spec/volumes/configMap/name
kind: ReplicaSet
- path: spec/template/spec/containers/env/valueFrom/configMapKeyRef/name
kind: ReplicaSet
- path: spec/template/spec/initContainers/env/valueFrom/configMapKeyRef/name
kind: ReplicaSet
- path: spec/template/spec/containers/envFrom/configMapRef/name
kind: ReplicaSet
- path: spec/template/spec/initContainers/envFrom/configMapRef/name
kind: ReplicaSet
- path: spec/template/spec/volumes/configMap/name
kind: DaemonSet
- path: spec/template/spec/containers/env/valueFrom/configMapKeyRef/name
kind: DaemonSet
- path: spec/template/spec/initContainers/env/valueFrom/configMapKeyRef/name
kind: DaemonSet
- path: spec/template/spec/containers/envFrom/configMapRef/name
kind: DaemonSet
- path: spec/template/spec/initContainers/envFrom/configMapRef/name
kind: DaemonSet
- path: spec/template/spec/volumes/configMap/name
kind: StatefulSet
- path: spec/template/spec/containers/env/valueFrom/configMapKeyRef/name
kind: StatefulSet
- path: spec/template/spec/initContainers/env/valueFrom/configMapKeyRef/name
kind: StatefulSet
- path: spec/template/spec/containers/envFrom/configMapRef/name
kind: StatefulSet
- path: spec/template/spec/initContainers/envFrom/configMapRef/name
kind: StatefulSet
- path: spec/template/spec/volumes/projected/sources/configMap/name
kind: StatefulSet
- path: spec/template/spec/volumes/configMap/name
kind: Job
- path: spec/template/spec/containers/env/valueFrom/configMapKeyRef/name
kind: Job
- path: spec/template/spec/initContainers/env/valueFrom/configMapKeyRef/name
kind: Job
- path: spec/template/spec/containers/envFrom/configMapRef/name
kind: Job
- path: spec/template/spec/initContainers/envFrom/configMapRef/name
kind: Job
- path: spec/jobTemplate/spec/template/spec/volumes/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
kind: CronJob
- kind: Secret
version: v1
pathConfigs:
- path: spec/volumes/secret/secretName
version: v1
kind: Pod
- path: spec/containers/env/valueFrom/secretKeyRef/name
version: v1
kind: Pod
- path: spec/initContainers/env/valueFrom/secretKeyRef/name
version: v1
kind: Pod
- path: spec/containers/envFrom/secretRef/name
version: v1
kind: Pod
- path: spec/initContainers/envFrom/secretRef/name
version: v1
kind: Pod
- path: spec/imagePullSecrets/name
version: v1
kind: Pod
- path: spec/template/spec/volumes/secret/secretName
kind: Deployment
- path: spec/template/spec/containers/env/valueFrom/secretKeyRef/name
kind: Deployment
- path: spec/template/spec/initContainers/env/valueFrom/secretKeyRef/name
kind: Deployment
- path: spec/template/spec/containers/envFrom/secretRef/name
kind: Deployment
- path: spec/template/spec/initContainers/envFrom/secretRef/name
kind: Deployment
- path: spec/template/spec/imagePullSecrets/name
kind: Deployment
- path: spec/template/spec/volumes/secret/secretName
kind: ReplicaSet
- path: spec/template/spec/containers/env/valueFrom/secretKeyRef/name
kind: ReplicaSet
- path: spec/template/spec/initContainers/env/valueFrom/secretKeyRef/name
kind: ReplicaSet
- path: spec/template/spec/containers/envFrom/secretRef/name
kind: ReplicaSet
- path: spec/template/spec/initContainers/envFrom/secretRef/name
kind: ReplicaSet
- path: spec/template/spec/imagePullSecrets/name
kind: ReplicaSet
- path: spec/template/spec/volumes/secret/secretName
kind: DaemonSet
- path: spec/template/spec/containers/env/valueFrom/secretKeyRef/name
kind: DaemonSet
- path: spec/template/spec/initContainers/env/valueFrom/secretKeyRef/name
kind: DaemonSet
- path: spec/template/spec/containers/envFrom/secretRef/name
kind: DaemonSet
- path: spec/template/spec/initContainers/envFrom/secretRef/name
kind: DaemonSet
- path: spec/template/spec/imagePullSecrets/name
kind: DaemonSet
- path: spec/template/spec/volumes/secret/secretName
kind: StatefulSet
- path: spec/template/spec/containers/env/valueFrom/secretKeyRef/name
kind: StatefulSet
- path: spec/template/spec/initContainers/env/valueFrom/secretKeyRef/name
kind: StatefulSet
- path: spec/template/spec/containers/envFrom/secretRef/name
kind: StatefulSet
- path: spec/template/spec/initContainers/envFrom/secretRef/name
kind: StatefulSet
- path: spec/template/spec/imagePullSecrets/name
kind: StatefulSet
- path: spec/template/spec/volumes/secret/secretName
kind: Job
- path: spec/template/spec/containers/env/valueFrom/secretKeyRef/name
kind: Job
- path: spec/template/spec/initContainers/env/valueFrom/secretKeyRef/name
kind: Job
- path: spec/template/spec/containers/envFrom/secretRef/name
kind: Job
- path: spec/template/spec/initContainers/envFrom/secretRef/name
kind: Job
- path: spec/template/spec/imagePullSecrets/name
kind: Job
- path: spec/jobTemplate/spec/template/sepc/volumes/secret/secretName
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
kind: CronJob
- path: spec/jobTemplate/spec/template/spec/containers/envFrom/secretRef/name
kind: CronJob
- path: spec/jobTemplate/spec/template/spec/initContainers/envFrom/secretRef/name
kind: CronJob
- path: spec/jobTemplate/spec/template/spec/imagePullSecrets/name
kind: CronJob
- path: spec/tls/secretName
kind: Ingress
- path: metadata/annotations/ingress.kubernetes.io\/auth-secret
kind: Ingress
- path: metadata/annotations/nginx.ingress.kubernetes.io\/auth-secret
kind: Ingress
- path: imagePullSecrets/name
kind: ServiceAccount
- path: parameters/secretName
kind: StorageClass
- path: parameters/adminSecretName
kind: StorageClass
- path: parameters/userSecretName
kind: StorageClass
- path: parameters/secretRef
kind: StorageClass
- kind: Service
version: v1
pathConfigs:
- path: spec/serviceName
kind: StatefulSet
group: apps
- path: spec/rules/http/paths/backend/serviceName
kind: Ingress
- path: spec/backend/serviceName
kind: Ingress
- kind: Role
group: rbac.authorization.k8s.io
pathConfigs:
- path: roleRef/name
kind: RoleBinding
group: rbac.authorization.k8s.io
- kind: ClusterRole
group: rbac.authorization.k8s.io
pathConfigs:
- path: roleRef/name
kind: RoleBinding
group: rbac.authorization.k8s.io
- path: roleRef/name
kind: ClusterRoleBinding
group: rbac.authorization.k8s.io
- kind: ServiceAccount
version: v1
pathConfigs:
- path: subjects/name
kind: RoleBinding
group: rbac.authorization.k8s.io
- path: subjects/name
kind: ClusterRoleBinding
group: rbac.authorization.k8s.io
- path: spec/serviceAccountName
kind: Pod
- path: spec/template/spec/serviceAccountName
kind: StatefulSet
- path: spec/template/spec/serviceAccountName
kind: Deployment
- path: spec/template/spec/serviceAccountName
kind: ReplicationController
- path: spec/jobTemplate/spec/template/spec/serviceAccountName
kind: CronJob
- path: spec/template/spec/serviceAccountName
kind: job
- path: spec/template/spec/serviceAccountName
kind: DaemonSet
- kind: PersistentVolumeClaim
version: v1
pathConfigs:
- path: spec/volumes/persistentVolumeClaim/claimName
kind: Pod
- path: spec/template/spec/volumes/persistentVolumeClaim/claimName
kind: StatefulSet
- path: spec/template/spec/volumes/persistentVolumeClaim/claimName
kind: Deployment
- path: spec/template/spec/volumes/persistentVolumeClaim/claimName
kind: ReplicationController
- path: spec/jobTemplate/spec/template/spec/volumes/persistentVolumeClaim/claimName
kind: CronJob
- path: spec/template/spec/volumes/persistentVolumeClaim/claimName
kind: Job
- path: spec/template/spec/volumes/persistentVolumeClaim/claimName
kind: DaemonSet
- kind: PersistentVolume
version: v1
pathConfigs:
- path: spec/volumeName
kind: PersistentVolumeClaim
`
)

View File

@@ -0,0 +1,25 @@
/*
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 defaultconfig
const (
namespacePathConfigs = `
namespace:
- path: metadata/namespace
create: true
`
)

View File

@@ -0,0 +1,85 @@
/*
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 defaultconfig
const (
varReferencePathConfigs = `
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/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/containers/args
kind: Pod
- path: spec/containers/env/value
kind: Pod
`
)

View File

@@ -0,0 +1,86 @@
/*
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
import (
"log"
"github.com/ghodss/yaml"
"sigs.k8s.io/kustomize/pkg/ifc"
"sigs.k8s.io/kustomize/pkg/transformers/config/defaultconfig"
)
// Factory makes instances of TransformerConfig.
type Factory struct {
ldr ifc.Loader
}
func NewFactory(l ifc.Loader) *Factory {
return &Factory{ldr: l}
}
func (tf *Factory) loader() ifc.Loader {
if tf.ldr.(ifc.Loader) == nil {
log.Fatal("no loader")
}
return tf.ldr
}
// FromFiles returns a TranformerConfig object from a list of files
func (tf *Factory) FromFiles(
paths []string) (*TransformerConfig, error) {
result := &TransformerConfig{}
for _, path := range paths {
data, err := tf.loader().Load(path)
if err != nil {
return nil, err
}
t, err := makeTransformerConfigFromBytes(data)
if err != nil {
return nil, err
}
result = result.Merge(t)
}
return result, nil
}
// makeTransformerConfigFromBytes returns a TransformerConfig object from bytes
func makeTransformerConfigFromBytes(data []byte) (*TransformerConfig, error) {
var t TransformerConfig
err := yaml.Unmarshal(data, &t)
if err != nil {
return nil, err
}
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.GetDefaultPathConfigs())
if err != nil {
log.Fatalf("Unable to make default transformconfig: %v", err)
}
return c
}

View File

@@ -0,0 +1,64 @@
/*
Copyright 2018 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package 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"
)
func TestMakeDefaultTransformerConfig(t *testing.T) {
// Confirm default can be made without fatal error inside call.
l, _, _ := makeFakeLoaderAndOutput()
_ = NewFactory(l).DefaultConfig()
}
func makeFakeLoaderAndOutput() (ifc.Loader, *TransformerConfig, *TransformerConfig) {
transformerConfig := `
namePrefix:
- path: nameprefix/path
kind: SomeKind
`
fakeFS := fs.MakeFakeFS()
fakeFS.WriteFile("transformerconfig/test/config.yaml", []byte(transformerConfig))
ldr := loader.NewFileLoader(fakeFS)
expected := &TransformerConfig{
NamePrefix: []PathConfig{
{
Gvk: gvk.Gvk{Kind: "SomeKind"},
Path: "nameprefix/path",
},
},
}
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)
}
}

View File

@@ -0,0 +1,156 @@
/*
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
import (
"encoding/json"
"strings"
"github.com/ghodss/yaml"
"k8s.io/kube-openapi/pkg/common"
"sigs.k8s.io/kustomize/pkg/gvk"
)
// LoadCRDs parse CRD schemas from paths into a TransformerConfig
func (tf *Factory) LoadCRDs(paths []string) (*TransformerConfig, error) {
pathConfigs := tf.EmptyConfig()
for _, path := range paths {
pathConfig, err := tf.loadCRD(path)
if err != nil {
return nil, err
}
pathConfigs = pathConfigs.Merge(pathConfig)
}
return pathConfigs, 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
if content[0] == '{' {
err = json.Unmarshal(content, &types)
} else {
err = yaml.Unmarshal(content, &types)
}
if err != nil {
return nil, err
}
crds := getCRDs(types)
for crd, k := range crds {
crdPathConfigs := tf.EmptyConfig()
err = getCRDPathConfig(
types, crd, crd, k, []string{}, crdPathConfigs)
if err != nil {
return result, err
}
result = result.Merge(crdPathConfigs)
}
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
}
// getCRDPathConfig gets pathConfigs for one CRD recursively
func getCRDPathConfig(
types map[string]common.OpenAPIDefinition, atype string, crd string, in gvk.Gvk,
path []string, configs *TransformerConfig) error {
if _, ok := types[crd]; !ok {
return nil
}
for propname, property := range types[atype].Schema.SchemaProps.Properties {
_, annotate := property.Extensions.GetString(Annotation)
if annotate {
configs.AddAnnotationPathConfig(
PathConfig{
CreateIfNotPresent: false,
Gvk: in,
Path: strings.Join(append(path, propname), "/"),
},
)
}
_, label := property.Extensions.GetString(LabelSelector)
if label {
configs.AddLabelPathConfig(
PathConfig{
CreateIfNotPresent: false,
Gvk: in,
Path: strings.Join(append(path, propname), "/"),
},
)
}
_, identity := property.Extensions.GetString(Identity)
if identity {
configs.AddPrefixPathConfig(
PathConfig{
CreateIfNotPresent: false,
Gvk: in,
Path: strings.Join(append(path, propname), "/"),
},
)
}
version, ok := property.Extensions.GetString(Version)
if ok {
kind, ok := property.Extensions.GetString(Kind)
if ok {
nameKey, ok := property.Extensions.GetString(NameKey)
if !ok {
nameKey = "name"
}
configs.AddNamereferencePathConfig(ReferencePathConfig{
Gvk: gvk.Gvk{Kind: kind, Version: version},
PathConfigs: []PathConfig{
{
CreateIfNotPresent: false,
Gvk: in,
Path: strings.Join(append(path, propname, nameKey), "/"),
},
},
})
}
}
if property.Ref.GetURL() != nil {
getCRDPathConfig(types, property.Ref.String(), crd, in, append(path, propname), configs)
}
}
return nil
}

View File

@@ -0,0 +1,185 @@
/*
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
import (
"reflect"
"testing"
"sigs.k8s.io/kustomize/pkg/gvk"
"sigs.k8s.io/kustomize/pkg/ifc"
"sigs.k8s.io/kustomize/pkg/internal/loadertest"
)
const (
crdContent = `
{
"github.com/example/pkg/apis/jingfang/v1beta1.Bee": {
"Schema": {
"description": "Bee",
"properties": {
"apiVersion": {
"description": "APIVersion defines the versioned schema of this representation of an object. Servers should convert
recognized schemas to the latest internal value, and may reject unrecognized values.
More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources",
"type": "string"
},
"kind": {
"description": "Kind is a string value representing the REST resource this object represents. Servers may infer
this from the endpoint the client submits requests to. Cannot be updated. In CamelCase.
More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds",
"type": "string"
},
"metadata": {
"$ref": "k8s.io/apimachinery/pkg/apis/meta/v1.ObjectMeta"
},
"spec": {
"$ref": "github.com/example/pkg/apis/jingfang/v1beta1.BeeSpec"
},
"status": {
"$ref": "github.com/example/pkg/apis/jingfang/v1beta1.BeeStatus"
}
}
},
"Dependencies": [
"github.com/example/pkg/apis/jingfang/v1beta1.BeeSpec",
"github.com/example/pkg/apis/jingfang/v1beta1.BeeStatus",
"k8s.io/apimachinery/pkg/apis/meta/v1.ObjectMeta"
]
},
"github.com/example/pkg/apis/jingfang/v1beta1.BeeSpec": {
"Schema": {
"description": "BeeSpec defines the desired state of Bee"
},
"Dependencies": []
},
"github.com/example/pkg/apis/jingfang/v1beta1.BeeStatus": {
"Schema": {
"description": "BeeStatus defines the observed state of Bee"
},
"Dependencies": []
},
"github.com/example/pkg/apis/jingfang/v1beta1.MyKind": {
"Schema": {
"description": "MyKind",
"properties": {
"apiVersion": {
"description": "APIVersion defines the versioned schema of this representation of an object.
Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values.
More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources",
"type": "string"
},
"kind": {
"description": "Kind is a string value representing the REST resource this object represents.
Servers may infer this from the endpoint the client submits requests to. Cannot be updated.
In CamelCase. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds",
"type": "string"
},
"metadata": {
"$ref": "k8s.io/apimachinery/pkg/apis/meta/v1.ObjectMeta"
},
"spec": {
"$ref": "github.com/example/pkg/apis/jingfang/v1beta1.MyKindSpec"
},
"status": {
"$ref": "github.com/example/pkg/apis/jingfang/v1beta1.MyKindStatus"
}
}
},
"Dependencies": [
"github.com/example/pkg/apis/jingfang/v1beta1.MyKindSpec",
"github.com/example/pkg/apis/jingfang/v1beta1.MyKindStatus",
"k8s.io/apimachinery/pkg/apis/meta/v1.ObjectMeta"
]
},
"github.com/example/pkg/apis/jingfang/v1beta1.MyKindSpec": {
"Schema": {
"description": "MyKindSpec defines the desired state of MyKind",
"properties": {
"beeRef": {
"x-kubernetes-object-ref-api-version": "v1beta1",
"x-kubernetes-object-ref-kind": "Bee",
"$ref": "github.com/example/pkg/apis/jingfang/v1beta1.Bee"
},
"secretRef": {
"description": "If defined, we use this secret for configuring the MYSQL_ROOT_PASSWORD
If it is not set we generate a secret dynamically",
"x-kubernetes-object-ref-api-version": "v1",
"x-kubernetes-object-ref-kind": "Secret",
"$ref": "k8s.io/api/core/v1.LocalObjectReference"
}
}
},
"Dependencies": [
"github.com/example/pkg/apis/jingfang/v1beta1.Bee",
"k8s.io/api/core/v1.LocalObjectReference"
]
},
"github.com/example/pkg/apis/jingfang/v1beta1.MyKindStatus": {
"Schema": {
"description": "MyKindStatus defines the observed state of MyKind"
},
"Dependencies": []
}
}
`
)
func makeLoader(t *testing.T) ifc.Loader {
ldr := loadertest.NewFakeLoader("/testpath")
err := ldr.AddFile("/testpath/crd.json", []byte(crdContent))
if err != nil {
t.Fatalf("Failed to setup fake ldr.")
}
return ldr
}
func TestLoadCRDs(t *testing.T) {
refpathconfigs := []ReferencePathConfig{
{
Gvk: gvk.Gvk{Kind: "Secret", Version: "v1"},
PathConfigs: []PathConfig{
{
CreateIfNotPresent: false,
Gvk: gvk.Gvk{Kind: "MyKind"},
Path: "spec/secretRef/name",
},
},
},
{
Gvk: gvk.Gvk{Kind: "Bee", Version: "v1beta1"},
PathConfigs: []PathConfig{
{
CreateIfNotPresent: false,
Gvk: gvk.Gvk{Kind: "MyKind"},
Path: "spec/beeRef/name",
},
},
},
}
expected := &TransformerConfig{
NameReference: refpathconfigs,
}
pathconfig, _ := NewFactory(makeLoader(t)).LoadCRDs(
[]string{"/testpath/crd.json"})
if !reflect.DeepEqual(pathconfig, expected) {
t.Fatalf("expected\n %v\n but got\n %v\n", expected, pathconfig)
}
}

View File

@@ -0,0 +1,60 @@
/*
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
import (
"strings"
"sigs.k8s.io/kustomize/pkg/gvk"
)
// PathConfig contains the configuration of a field, including the gvk it ties to,
// path to the field, etc.
type PathConfig struct {
gvk.Gvk `json:",inline,omitempty" yaml:",inline,omitempty"`
Path string `json:"path,omitempty" yaml:"path,omitempty"`
CreateIfNotPresent bool `json:"create,omitempty" yaml:"create,omitempty"`
}
const (
escapedForwardSlash = "\\/"
tempSlashReplacement = "???"
)
// PathSlice converts the path string to a slice of strings, separated by "/"
// "/" can be contained in a fieldname.
// such as ingress.kubernetes.io/auth-secret in Ingress annotations.
// To deal with this special case, the path to this field should be formatted as
//
// metadata/annotations/ingress.kubernetes.io\/auth-secret
//
// Then PathSlice will return
//
// []string{"metadata", "annotations", "ingress.auth-secretkubernetes.io/auth-secret"}
func (p PathConfig) PathSlice() []string {
if !strings.Contains(p.Path, escapedForwardSlash) {
return strings.Split(p.Path, "/")
}
s := strings.Replace(p.Path, escapedForwardSlash, tempSlashReplacement, -1)
paths := strings.Split(s, "/")
var result []string
for _, path := range paths {
result = append(result, strings.Replace(path, tempSlashReplacement, "/", -1))
}
return result
}

View File

@@ -0,0 +1,46 @@
/*
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
import (
"reflect"
"testing"
)
func TestPathSlice(t *testing.T) {
type path struct {
input string
parsed []string
}
paths := []path{
{
input: "spec/metadata/annotations",
parsed: []string{"spec", "metadata", "annotations"},
},
{
input: `metadata/annotations/nginx.ingress.kubernetes.io\/auth-secret`,
parsed: []string{"metadata", "annotations", "nginx.ingress.kubernetes.io/auth-secret"},
},
}
for _, p := range paths {
pathConfig := PathConfig{Path: p.input}
actual := pathConfig.PathSlice()
if !reflect.DeepEqual(actual, p.parsed) {
t.Fatalf("expected %v, but got %v", p.parsed, actual)
}
}
}

View File

@@ -0,0 +1,64 @@
/*
Copyright 2018 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package config
import (
"sigs.k8s.io/kustomize/pkg/gvk"
)
// ReferencePathConfig contains the configuration of a field that references
// the name of another resource whose GroupVersionKind is specified in referencedGVK.
// e.g. pod.spec.template.volumes.configMap.name references the name of a configmap
// Its corresponding referencePathConfig will look like:
//
// ReferencePathConfig{
// referencedGVK: schema.GroupVersionKind{Version: "v1", Kind: "ConfigMap"},
// pathConfigs: []PathConfig{
// {
// GroupVersionKind: &schema.GroupVersionKind{Version: "v1", Kind: "Pod"},
// Path: []string{"spec", "volumes", "configMap", "name"},
// },
// }
type ReferencePathConfig struct {
gvk.Gvk `json:",inline,omitempty" yaml:",inline,omitempty"`
// PathConfig is the gvk that is referencing the referencedGVK object's name.
PathConfigs []PathConfig `json:"pathConfigs,omitempty" yaml:"pathConfigs,omitempty"`
}
func merge(configs []ReferencePathConfig, config ReferencePathConfig) []ReferencePathConfig {
var result []ReferencePathConfig
found := false
for _, c := range configs {
if c.Equals(config.Gvk) {
c.PathConfigs = append(c.PathConfigs, config.PathConfigs...)
found = true
}
result = append(result, c)
}
if !found {
result = append(result, config)
}
return result
}
func mergeNameReferencePathConfigs(a, b []ReferencePathConfig) []ReferencePathConfig {
for _, r := range b {
a = merge(a, r)
}
return a
}

View File

@@ -0,0 +1,92 @@
/*
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 provides the functions to load default or user provided configurations
// for different transformers
package config
import (
"sort"
)
type rpcSlice []ReferencePathConfig
func (s rpcSlice) Len() int { return len(s) }
func (s rpcSlice) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
func (s rpcSlice) Less(i, j int) bool {
return s[i].Gvk.IsLessThan(s[j].Gvk)
}
type pcSlice []PathConfig
func (s pcSlice) Len() int { return len(s) }
func (s pcSlice) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
func (s pcSlice) Less(i, j int) bool {
return s[i].Gvk.IsLessThan(s[j].Gvk)
}
// TransformerConfig represents the path configurations for different transformations
type TransformerConfig struct {
NamePrefix pcSlice `json:"namePrefix,omitempty" yaml:"namePrefix,omitempty"`
NameSpace pcSlice `json:"namespace,omitempty" yaml:"namespace,omitempty"`
CommonLabels pcSlice `json:"commonLabels,omitempty" yaml:"commonLabels,omitempty"`
CommonAnnotations pcSlice `json:"commonAnnotations,omitempty" yaml:"commonAnnotations,omitempty"`
NameReference rpcSlice `json:"nameReference,omitempty" yaml:"nameReference,omitempty"`
VarReference pcSlice `json:"varReference,omitempty" yaml:"varReference,omitempty"`
}
// sortFields provides determinism in logging, tests, etc.
func (t *TransformerConfig) sortFields() {
sort.Sort(t.NamePrefix)
sort.Sort(t.NameSpace)
sort.Sort(t.CommonLabels)
sort.Sort(t.CommonAnnotations)
sort.Sort(t.NameReference)
sort.Sort(t.VarReference)
}
// AddPrefixPathConfig adds a PathConfig to NamePrefix
func (t *TransformerConfig) AddPrefixPathConfig(config PathConfig) {
t.NamePrefix = append(t.NamePrefix, config)
}
// AddLabelPathConfig adds a PathConfig to CommonLabels
func (t *TransformerConfig) AddLabelPathConfig(config PathConfig) {
t.CommonLabels = append(t.CommonLabels, config)
}
// AddAnnotationPathConfig adds a PathConfig to CommonAnnotations
func (t *TransformerConfig) AddAnnotationPathConfig(config PathConfig) {
t.CommonAnnotations = append(t.CommonAnnotations, config)
}
// AddNamereferencePathConfig adds a ReferencePathConfig to NameReference
func (t *TransformerConfig) AddNamereferencePathConfig(config ReferencePathConfig) {
t.NameReference = mergeNameReferencePathConfigs(t.NameReference, []ReferencePathConfig{config})
}
// Merge merges two TransformerConfigs objects into a new TransformerConfig object
func (t *TransformerConfig) Merge(input *TransformerConfig) *TransformerConfig {
merged := &TransformerConfig{}
merged.NamePrefix = append(t.NamePrefix, input.NamePrefix...)
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 = mergeNameReferencePathConfigs(t.NameReference, input.NameReference)
merged.sortFields()
return merged
}

View File

@@ -0,0 +1,144 @@
/*
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
import (
"testing"
"reflect"
"sigs.k8s.io/kustomize/pkg/gvk"
)
func TestAddNameReferencePathConfigs(t *testing.T) {
cfg := &TransformerConfig{}
pathConfig := ReferencePathConfig{
Gvk: gvk.Gvk{
Kind: "KindA",
},
PathConfigs: []PathConfig{
{
Gvk: gvk.Gvk{
Kind: "KindB",
},
Path: "path/to/a/field",
CreateIfNotPresent: false,
},
},
}
cfg.AddNamereferencePathConfig(pathConfig)
if len(cfg.NameReference) != 1 {
t.Fatal("failed to add namerefence pathconfig")
}
}
func TestAddPathConfigs(t *testing.T) {
cfg := &TransformerConfig{}
pathConfig := PathConfig{
Gvk: gvk.Gvk{Group: "GroupA", Kind: "KindB"},
Path: "path/to/a/field",
CreateIfNotPresent: true,
}
cfg.AddPrefixPathConfig(pathConfig)
if len(cfg.NamePrefix) != 1 {
t.Fatalf("failed to add nameprefix pathconfig")
}
cfg.AddLabelPathConfig(pathConfig)
if len(cfg.CommonLabels) != 1 {
t.Fatalf("failed to add nameprefix pathconfig")
}
cfg.AddAnnotationPathConfig(pathConfig)
if len(cfg.CommonAnnotations) != 1 {
t.Fatalf("failed to add nameprefix pathconfig")
}
}
func TestMerge(t *testing.T) {
nameReference := []ReferencePathConfig{
{
Gvk: gvk.Gvk{
Kind: "KindA",
},
PathConfigs: []PathConfig{
{
Gvk: gvk.Gvk{
Kind: "KindB",
},
Path: "path/to/a/field",
CreateIfNotPresent: false,
},
},
},
{
Gvk: gvk.Gvk{
Kind: "KindA",
},
PathConfigs: []PathConfig{
{
Gvk: gvk.Gvk{
Kind: "KindC",
},
Path: "path/to/a/field",
CreateIfNotPresent: false,
},
},
},
}
pathConfigs := []PathConfig{
{
Gvk: gvk.Gvk{Group: "GroupA", Kind: "KindB"},
Path: "path/to/a/field",
CreateIfNotPresent: true,
},
{
Gvk: gvk.Gvk{Group: "GroupA", Kind: "KindC"},
Path: "path/to/a/field",
CreateIfNotPresent: true,
},
}
cfga := &TransformerConfig{}
cfga.AddNamereferencePathConfig(nameReference[0])
cfga.AddPrefixPathConfig(pathConfigs[0])
cfgb := &TransformerConfig{}
cfgb.AddNamereferencePathConfig(nameReference[1])
cfgb.AddPrefixPathConfig(pathConfigs[1])
actual := cfga.Merge(cfgb)
if len(actual.NamePrefix) != 2 {
t.Fatal("merge failed for namePrefix pathconfig")
}
if len(actual.NameReference) != 1 {
t.Fatal("merge failed for namereference pathconfig")
}
expected := &TransformerConfig{}
expected.AddNamereferencePathConfig(nameReference[0])
expected.AddNamereferencePathConfig(nameReference[1])
expected.AddPrefixPathConfig(pathConfigs[0])
expected.AddPrefixPathConfig(pathConfigs[1])
if !reflect.DeepEqual(actual, expected) {
t.Fatalf("expected: %v\n but got: %v\n", expected, actual)
}
}