Further isolate unstructured with factories.

This commit is contained in:
jregan
2018-10-06 10:44:34 -07:00
committed by Jeffrey Regan
parent 3cdfbd843b
commit 4eb2757847
31 changed files with 525 additions and 348 deletions

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 k8sdeps
import (
"io"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"sigs.k8s.io/kustomize/pkg/ifc"
)
// KustKunstructuredFactory hides construction using apimachinery types.
type KustKunstructuredFactory struct {
decoder ifc.Decoder
}
var _ ifc.KunstructuredFactory = &KustKunstructuredFactory{}
// NewKustKunstructuredFactory returns a factory.
func NewKustKunstructuredFactory(d ifc.Decoder) ifc.KunstructuredFactory {
return &KustKunstructuredFactory{decoder: d}
}
// SliceFromBytes returns a slice of Kunstructured.
func (kf *KustKunstructuredFactory) SliceFromBytes(
in []byte) ([]ifc.Kunstructured, error) {
kf.decoder.SetInput(in)
var result []ifc.Kunstructured
var err error
for err == nil || isEmptyYamlError(err) {
var out unstructured.Unstructured
err = kf.decoder.Decode(&out)
if err == nil {
result = append(result, &UnstructAdapter{Unstructured: out})
}
}
if err != io.EOF {
return nil, err
}
return result, nil
}
// FromMap returns an instance of Kunstructured.
func (kf *KustKunstructuredFactory) FromMap(
m map[string]interface{}) ifc.Kunstructured {
return &UnstructAdapter{Unstructured: unstructured.Unstructured{Object: m}}
}

View File

@@ -0,0 +1,124 @@
/*
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 k8sdeps
import (
"reflect"
"testing"
"sigs.k8s.io/kustomize/pkg/ifc"
)
func TestSliceFromBytes(t *testing.T) {
factory := NewKustKunstructuredFactory(NewKustDecoder())
testConfigMap := factory.FromMap(
map[string]interface{}{
"apiVersion": "v1",
"kind": "ConfigMap",
"metadata": map[string]interface{}{
"name": "winnie",
},
})
tests := []struct {
name string
input []byte
expectedOut []ifc.Kunstructured
expectedErr bool
}{
{
name: "garbage",
input: []byte("garbageIn: garbageOut"),
expectedOut: []ifc.Kunstructured{},
expectedErr: true,
},
{
name: "noBytes",
input: []byte{},
expectedOut: []ifc.Kunstructured{},
expectedErr: false,
},
{
name: "goodJson",
input: []byte(`
{"apiVersion":"v1","kind":"ConfigMap","metadata":{"name":"winnie"}}
`),
expectedOut: []ifc.Kunstructured{testConfigMap},
expectedErr: false,
},
{
name: "goodYaml1",
input: []byte(`
apiVersion: v1
kind: ConfigMap
metadata:
name: winnie
`),
expectedOut: []ifc.Kunstructured{testConfigMap},
expectedErr: false,
},
{
name: "goodYaml2",
input: []byte(`
apiVersion: v1
kind: ConfigMap
metadata:
name: winnie
---
apiVersion: v1
kind: ConfigMap
metadata:
name: winnie
`),
expectedOut: []ifc.Kunstructured{testConfigMap, testConfigMap},
expectedErr: false,
},
{
name: "garbageInOneOfTwoObjects",
input: []byte(`
apiVersion: v1
kind: ConfigMap
metadata:
name: winnie
---
WOOOOOOOOOOOOOOOOOOOOOOOOT: woot
`),
expectedOut: []ifc.Kunstructured{},
expectedErr: true,
},
}
for _, test := range tests {
rs, err := factory.SliceFromBytes(test.input)
if test.expectedErr && err == nil {
t.Fatalf("%v: should return error", test.name)
}
if !test.expectedErr && err != nil {
t.Fatalf("%v: unexpected error: %s", test.name, err)
}
if len(rs) != len(test.expectedOut) {
t.Fatalf("%s: length mismatch %d != %d",
test.name, len(rs), len(test.expectedOut))
}
for i := range rs {
if !reflect.DeepEqual(test.expectedOut[i], rs[i]) {
t.Fatalf("%s: Got: %v\nexpected:%v",
test.name, test.expectedOut[i], rs[i])
}
}
}
}

View File

@@ -1,9 +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 k8sdeps package k8sdeps
import ( import (
"encoding/json" "encoding/json"
"fmt" "fmt"
"io"
"strings" "strings"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@@ -37,35 +52,6 @@ func NewKunstructuredFromObject(obj runtime.Object) (ifc.Kunstructured, error) {
return &UnstructAdapter{Unstructured: u}, err return &UnstructAdapter{Unstructured: u}, err
} }
// NewKunstructuredFromMap returns a new instance of Kunstructured.
func NewKunstructuredFromMap(m map[string]interface{}) ifc.Kunstructured {
return NewKunstructuredFromUnstruct(unstructured.Unstructured{Object: m})
}
// NewKunstructuredFromUnstruct returns a new instance of Kunstructured.
func NewKunstructuredFromUnstruct(u unstructured.Unstructured) ifc.Kunstructured {
return &UnstructAdapter{Unstructured: u}
}
// NewKunstructuredSliceFromBytes unmarshalls bytes into a Kunstructured slice.
func NewKunstructuredSliceFromBytes(
in []byte, decoder ifc.Decoder) ([]ifc.Kunstructured, error) {
decoder.SetInput(in)
var result []ifc.Kunstructured
var err error
for err == nil || isEmptyYamlError(err) {
var out unstructured.Unstructured
err = decoder.Decode(&out)
if err == nil {
result = append(result, &UnstructAdapter{Unstructured: out})
}
}
if err != io.EOF {
return nil, err
}
return result, nil
}
// GetGvk returns the Gvk name of the object. // GetGvk returns the Gvk name of the object.
func (fs *UnstructAdapter) GetGvk() gvk.Gvk { func (fs *UnstructAdapter) GetGvk() gvk.Gvk {
return gvk.FromSchemaGvk(fs.GroupVersionKind()) return gvk.FromSchemaGvk(fs.GroupVersionKind())

View File

@@ -1,113 +1,28 @@
/*
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 k8sdeps package k8sdeps
import ( import (
"reflect"
"sigs.k8s.io/kustomize/pkg/ifc"
"testing" "testing"
) )
var testConfigMap = NewKunstructuredFromMap(
map[string]interface{}{
"apiVersion": "v1",
"kind": "ConfigMap",
"metadata": map[string]interface{}{
"name": "winnie",
},
})
func TestNewKunstructuredSliceFromBytes(t *testing.T) {
tests := []struct {
name string
input []byte
expectedOut []ifc.Kunstructured
expectedErr bool
}{
{
name: "garbage",
input: []byte("garbageIn: garbageOut"),
expectedOut: []ifc.Kunstructured{},
expectedErr: true,
},
{
name: "noBytes",
input: []byte{},
expectedOut: []ifc.Kunstructured{},
expectedErr: false,
},
{
name: "goodJson",
input: []byte(`
{"apiVersion":"v1","kind":"ConfigMap","metadata":{"name":"winnie"}}
`),
expectedOut: []ifc.Kunstructured{testConfigMap},
expectedErr: false,
},
{
name: "goodYaml1",
input: []byte(`
apiVersion: v1
kind: ConfigMap
metadata:
name: winnie
`),
expectedOut: []ifc.Kunstructured{testConfigMap},
expectedErr: false,
},
{
name: "goodYaml2",
input: []byte(`
apiVersion: v1
kind: ConfigMap
metadata:
name: winnie
---
apiVersion: v1
kind: ConfigMap
metadata:
name: winnie
`),
expectedOut: []ifc.Kunstructured{testConfigMap, testConfigMap},
expectedErr: false,
},
{
name: "garbageInOneOfTwoObjects",
input: []byte(`
apiVersion: v1
kind: ConfigMap
metadata:
name: winnie
---
WOOOOOOOOOOOOOOOOOOOOOOOOT: woot
`),
expectedOut: []ifc.Kunstructured{},
expectedErr: true,
},
}
for _, test := range tests {
rs, err := NewKunstructuredSliceFromBytes(
test.input, NewKustDecoder())
if test.expectedErr && err == nil {
t.Fatalf("%v: should return error", test.name)
}
if !test.expectedErr && err != nil {
t.Fatalf("%v: unexpected error: %s", test.name, err)
}
if len(rs) != len(test.expectedOut) {
t.Fatalf("%s: length mismatch %d != %d",
test.name, len(rs), len(test.expectedOut))
}
for i := range rs {
if !reflect.DeepEqual(test.expectedOut[i], rs[i]) {
t.Fatalf("%s: Got: %v\nexpected:%v",
test.name, test.expectedOut[i], rs[i])
}
}
}
}
func TestGetFieldValue(t *testing.T) { func TestGetFieldValue(t *testing.T) {
funStruct := NewKunstructuredFromMap(map[string]interface{}{ factory := NewKustKunstructuredFactory(NewKustDecoder())
kunstructured := factory.FromMap(map[string]interface{}{
"Kind": "Service", "Kind": "Service",
"metadata": map[string]interface{}{ "metadata": map[string]interface{}{
"labels": map[string]string{ "labels": map[string]string{
@@ -150,7 +65,7 @@ func TestGetFieldValue(t *testing.T) {
} }
for _, test := range tests { for _, test := range tests {
s, err := funStruct.GetFieldValue(test.pathToField) s, err := kunstructured.GetFieldValue(test.pathToField)
if test.errorExpected && err == nil { if test.errorExpected && err == nil {
t.Fatalf("should return error, but no error returned") t.Fatalf("should return error, but no error returned")
} else { } else {

View File

@@ -28,6 +28,7 @@ func main() {
defer glog.Flush() defer glog.Flush()
if err := commands.NewDefaultCommand( if err := commands.NewDefaultCommand(
k8sdeps.NewKustKunstructuredFactory(k8sdeps.NewKustDecoder()),
k8sdeps.NewKustDecoder(), k8sdeps.NewKustDecoder(),
k8sdeps.NewKustValidator(), k8sdeps.NewKustValidator(),
k8sdeps.NewKustHash()).Execute(); err != nil { k8sdeps.NewKustHash()).Execute(); err != nil {

View File

@@ -20,13 +20,15 @@ import (
"errors" "errors"
"io" "io"
"log" "log"
"sigs.k8s.io/kustomize/pkg/ifc" "sigs.k8s.io/kustomize/pkg/resmap"
"strings" "strings"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"sigs.k8s.io/kustomize/pkg/constants" "sigs.k8s.io/kustomize/pkg/constants"
"sigs.k8s.io/kustomize/pkg/fs" "sigs.k8s.io/kustomize/pkg/fs"
"sigs.k8s.io/kustomize/pkg/ifc"
"sigs.k8s.io/kustomize/pkg/loader" "sigs.k8s.io/kustomize/pkg/loader"
"sigs.k8s.io/kustomize/pkg/resource"
"sigs.k8s.io/kustomize/pkg/target" "sigs.k8s.io/kustomize/pkg/target"
"sigs.k8s.io/kustomize/pkg/transformerconfig" "sigs.k8s.io/kustomize/pkg/transformerconfig"
) )
@@ -60,6 +62,7 @@ Use different transformer configurations by passing files to kustomize
// NewCmdBuild creates a new build command. // NewCmdBuild creates a new build command.
func NewCmdBuild( func NewCmdBuild(
out io.Writer, fs fs.FileSystem, out io.Writer, fs fs.FileSystem,
kf ifc.KunstructuredFactory,
decoder ifc.Decoder, hash ifc.Hash) *cobra.Command { decoder ifc.Decoder, hash ifc.Hash) *cobra.Command {
var o buildOptions var o buildOptions
var p string var p string
@@ -74,7 +77,7 @@ func NewCmdBuild(
if err != nil { if err != nil {
return err return err
} }
return o.RunBuild(out, fs, decoder, hash) return o.RunBuild(out, fs, kf, decoder, hash)
}, },
} }
cmd.Flags().StringVarP( cmd.Flags().StringVarP(
@@ -119,6 +122,7 @@ func (o *buildOptions) Validate(args []string, p string, fs fs.FileSystem) error
// RunBuild runs build command. // RunBuild runs build command.
func (o *buildOptions) RunBuild( func (o *buildOptions) RunBuild(
out io.Writer, fSys fs.FileSystem, out io.Writer, fSys fs.FileSystem,
kf ifc.KunstructuredFactory,
decoder ifc.Decoder, hash ifc.Hash) error { decoder ifc.Decoder, hash ifc.Hash) error {
rootLoader, err := loader.NewLoader(o.kustomizationPath, "", fSys) rootLoader, err := loader.NewLoader(o.kustomizationPath, "", fSys)
if err != nil { if err != nil {
@@ -127,6 +131,7 @@ func (o *buildOptions) RunBuild(
defer rootLoader.Cleanup() defer rootLoader.Cleanup()
kt, err := target.NewKustTarget( kt, err := target.NewKustTarget(
rootLoader, fSys, rootLoader, fSys,
resmap.NewFactory(resource.NewFactory(kf)),
makeTransformerconfig(fSys, o.transformerconfigPaths), makeTransformerconfig(fSys, o.transformerconfigPaths),
decoder, hash) decoder, hash)
if err != nil { if err != nil {

View File

@@ -128,7 +128,10 @@ func runBuildTestCase(t *testing.T, testcaseName string, updateKustomizeExpected
kustomizationPath: testcase.Filename, kustomizationPath: testcase.Filename,
} }
buf := bytes.NewBuffer([]byte{}) buf := bytes.NewBuffer([]byte{})
err = ops.RunBuild(buf, fSys, k8sdeps.NewKustDecoder(), k8sdeps.NewKustHash()) err = ops.RunBuild(
buf, fSys,
k8sdeps.NewKustKunstructuredFactory(k8sdeps.NewKustDecoder()),
k8sdeps.NewKustDecoder(), k8sdeps.NewKustHash())
switch { switch {
case err != nil && len(testcase.ExpectedError) == 0: case err != nil && len(testcase.ExpectedError) == 0:
t.Errorf("unexpected error: %v", err) t.Errorf("unexpected error: %v", err)

View File

@@ -31,7 +31,8 @@ import (
// NewDefaultCommand returns the default (aka root) command for kustomize command. // NewDefaultCommand returns the default (aka root) command for kustomize command.
func NewDefaultCommand( func NewDefaultCommand(
decoder ifc.Decoder, validator ifc.Validator, hash ifc.Hash) *cobra.Command { kf ifc.KunstructuredFactory, decoder ifc.Decoder,
validator ifc.Validator, hash ifc.Hash) *cobra.Command {
fsys := fs.MakeRealFS() fsys := fs.MakeRealFS()
stdOut := os.Stdout stdOut := os.Stdout
@@ -47,7 +48,7 @@ See https://sigs.k8s.io/kustomize
c.AddCommand( c.AddCommand(
// TODO: Make consistent API for newCmd* functions. // TODO: Make consistent API for newCmd* functions.
build.NewCmdBuild(stdOut, fsys, decoder, hash), build.NewCmdBuild(stdOut, fsys, kf, decoder, hash),
edit.NewCmdEdit(fsys, validator), edit.NewCmdEdit(fsys, validator),
misc.NewCmdConfig(fsys), misc.NewCmdConfig(fsys),
misc.NewCmdVersion(stdOut), misc.NewCmdVersion(stdOut),

View File

@@ -69,3 +69,9 @@ type Kunstructured interface {
GetAnnotations() map[string]string GetAnnotations() map[string]string
SetAnnotations(map[string]string) SetAnnotations(map[string]string)
} }
// KunstructuredFactory makes instances of Kunstructured.
type KunstructuredFactory interface {
SliceFromBytes([]byte) ([]Kunstructured, error)
FromMap(m map[string]interface{}) Kunstructured
}

View File

@@ -22,6 +22,7 @@ import (
"testing" "testing"
"gopkg.in/yaml.v2" "gopkg.in/yaml.v2"
"sigs.k8s.io/kustomize/internal/k8sdeps"
"sigs.k8s.io/kustomize/pkg/gvk" "sigs.k8s.io/kustomize/pkg/gvk"
"sigs.k8s.io/kustomize/pkg/internal/loadertest" "sigs.k8s.io/kustomize/pkg/internal/loadertest"
"sigs.k8s.io/kustomize/pkg/patch" "sigs.k8s.io/kustomize/pkg/patch"
@@ -30,6 +31,9 @@ import (
"sigs.k8s.io/kustomize/pkg/resource" "sigs.k8s.io/kustomize/pkg/resource"
) )
var rf = resource.NewFactory(
k8sdeps.NewKustKunstructuredFactory(k8sdeps.NewKustDecoder()))
func TestNewPatchJson6902FactoryNoTarget(t *testing.T) { func TestNewPatchJson6902FactoryNoTarget(t *testing.T) {
p := patch.Json6902{} p := patch.Json6902{}
_, err := NewPatchJson6902Factory(nil).makeOnePatchJson6902Transformer(p) _, err := NewPatchJson6902Factory(nil).makeOnePatchJson6902Transformer(p)
@@ -182,7 +186,7 @@ func TestNewPatchJson6902FactoryMulti(t *testing.T) {
id := resid.NewResId(gvk.FromKind("foo"), "some-name") id := resid.NewResId(gvk.FromKind("foo"), "some-name")
base := resmap.ResMap{ base := resmap.ResMap{
id: resource.NewFromMap( id: rf.FromMap(
map[string]interface{}{ map[string]interface{}{
"kind": "foo", "kind": "foo",
"metadata": map[string]interface{}{ "metadata": map[string]interface{}{
@@ -208,7 +212,7 @@ func TestNewPatchJson6902FactoryMulti(t *testing.T) {
}), }),
} }
expected := resmap.ResMap{ expected := resmap.ResMap{
id: resource.NewFromMap( id: rf.FromMap(
map[string]interface{}{ map[string]interface{}{
"kind": "foo", "kind": "foo",
"metadata": map[string]interface{}{ "metadata": map[string]interface{}{
@@ -296,7 +300,7 @@ func TestNewPatchJson6902FactoryMultiConflict(t *testing.T) {
id := resid.NewResId(gvk.FromKind("foo"), "some-name") id := resid.NewResId(gvk.FromKind("foo"), "some-name")
base := resmap.ResMap{ base := resmap.ResMap{
id: resource.NewFromMap( id: rf.FromMap(
map[string]interface{}{ map[string]interface{}{
"kind": "foo", "kind": "foo",
"metadata": map[string]interface{}{ "metadata": map[string]interface{}{

View File

@@ -21,6 +21,7 @@ import (
"testing" "testing"
"github.com/evanphx/json-patch" "github.com/evanphx/json-patch"
"sigs.k8s.io/kustomize/internal/k8sdeps"
"sigs.k8s.io/kustomize/pkg/gvk" "sigs.k8s.io/kustomize/pkg/gvk"
"sigs.k8s.io/kustomize/pkg/resid" "sigs.k8s.io/kustomize/pkg/resid"
"sigs.k8s.io/kustomize/pkg/resmap" "sigs.k8s.io/kustomize/pkg/resmap"
@@ -30,9 +31,11 @@ import (
var deploy = gvk.Gvk{Group: "apps", Version: "v1", Kind: "Deployment"} var deploy = gvk.Gvk{Group: "apps", Version: "v1", Kind: "Deployment"}
func TestJsonPatchJSONTransformer_Transform(t *testing.T) { func TestJsonPatchJSONTransformer_Transform(t *testing.T) {
rf := resource.NewFactory(
k8sdeps.NewKustKunstructuredFactory(k8sdeps.NewKustDecoder()))
id := resid.NewResId(deploy, "deploy1") id := resid.NewResId(deploy, "deploy1")
base := resmap.ResMap{ base := resmap.ResMap{
id: resource.NewFromMap( id: rf.FromMap(
map[string]interface{}{ map[string]interface{}{
"apiVersion": "apps/v1", "apiVersion": "apps/v1",
"kind": "Deployment", "kind": "Deployment",
@@ -69,7 +72,7 @@ func TestJsonPatchJSONTransformer_Transform(t *testing.T) {
t.Fatalf("unexpected error : %v", err) t.Fatalf("unexpected error : %v", err)
} }
expected := resmap.ResMap{ expected := resmap.ResMap{
id: resource.NewFromMap( id: rf.FromMap(
map[string]interface{}{ map[string]interface{}{
"apiVersion": "apps/v1", "apiVersion": "apps/v1",
"kind": "Deployment", "kind": "Deployment",

View File

@@ -25,19 +25,19 @@ import (
// NewResMapFromConfigMapArgs returns a Resource slice given // NewResMapFromConfigMapArgs returns a Resource slice given
// a configmap metadata slice from kustomization file. // a configmap metadata slice from kustomization file.
func NewResMapFromConfigMapArgs( func (rmF *Factory) NewResMapFromConfigMapArgs(
f *configmapandsecret.ConfigMapFactory, cf *configmapandsecret.ConfigMapFactory,
cmArgsList []types.ConfigMapArgs) (ResMap, error) { cmArgsList []types.ConfigMapArgs) (ResMap, error) {
var allResources []*resource.Resource var allResources []*resource.Resource
for _, cmArgs := range cmArgsList { for _, cmArgs := range cmArgsList {
if cmArgs.Behavior == "" { if cmArgs.Behavior == "" {
cmArgs.Behavior = "create" cmArgs.Behavior = "create"
} }
cm, err := f.MakeConfigMap(&cmArgs) cm, err := cf.MakeConfigMap(&cmArgs)
if err != nil { if err != nil {
return nil, err return nil, err
} }
res, err := resource.NewWithBehavior( res, err := rmF.resF.WithBehavior(
cm, ifc.NewGenerationBehavior(cmArgs.Behavior)) cm, ifc.NewGenerationBehavior(cmArgs.Behavior))
if err != nil { if err != nil {
return nil, err return nil, err

View File

@@ -26,7 +26,6 @@ import (
"sigs.k8s.io/kustomize/pkg/ifc" "sigs.k8s.io/kustomize/pkg/ifc"
"sigs.k8s.io/kustomize/pkg/internal/loadertest" "sigs.k8s.io/kustomize/pkg/internal/loadertest"
"sigs.k8s.io/kustomize/pkg/resid" "sigs.k8s.io/kustomize/pkg/resid"
"sigs.k8s.io/kustomize/pkg/resource"
"sigs.k8s.io/kustomize/pkg/types" "sigs.k8s.io/kustomize/pkg/types"
) )
@@ -42,7 +41,7 @@ func TestNewFromConfigMaps(t *testing.T) {
} }
l := loadertest.NewFakeLoader("/home/seans/project/") l := loadertest.NewFakeLoader("/home/seans/project/")
f := configmapandsecret.NewConfigMapFactory(fs.MakeFakeFS(), l) cf := configmapandsecret.NewConfigMapFactory(fs.MakeFakeFS(), l)
testCases := []testCase{ testCases := []testCase{
{ {
description: "construct config map from env", description: "construct config map from env",
@@ -57,7 +56,7 @@ func TestNewFromConfigMaps(t *testing.T) {
filepath: "/home/seans/project/app.env", filepath: "/home/seans/project/app.env",
content: "DB_USERNAME=admin\nDB_PASSWORD=somepw", content: "DB_USERNAME=admin\nDB_PASSWORD=somepw",
expected: ResMap{ expected: ResMap{
resid.NewResId(cmap, "envConfigMap"): resource.NewFromMap( resid.NewResId(cmap, "envConfigMap"): rf.FromMap(
map[string]interface{}{ map[string]interface{}{
"apiVersion": "v1", "apiVersion": "v1",
"kind": "ConfigMap", "kind": "ConfigMap",
@@ -83,7 +82,7 @@ func TestNewFromConfigMaps(t *testing.T) {
filepath: "/home/seans/project/app-init.ini", filepath: "/home/seans/project/app-init.ini",
content: "FOO=bar\nBAR=baz\n", content: "FOO=bar\nBAR=baz\n",
expected: ResMap{ expected: ResMap{
resid.NewResId(cmap, "fileConfigMap"): resource.NewFromMap( resid.NewResId(cmap, "fileConfigMap"): rf.FromMap(
map[string]interface{}{ map[string]interface{}{
"apiVersion": "v1", "apiVersion": "v1",
"kind": "ConfigMap", "kind": "ConfigMap",
@@ -109,7 +108,7 @@ BAR=baz
}, },
}, },
expected: ResMap{ expected: ResMap{
resid.NewResId(cmap, "literalConfigMap"): resource.NewFromMap( resid.NewResId(cmap, "literalConfigMap"): rf.FromMap(
map[string]interface{}{ map[string]interface{}{
"apiVersion": "v1", "apiVersion": "v1",
"kind": "ConfigMap", "kind": "ConfigMap",
@@ -133,7 +132,7 @@ BAR=baz
if ferr := l.AddFile(tc.filepath, []byte(tc.content)); ferr != nil { if ferr := l.AddFile(tc.filepath, []byte(tc.content)); ferr != nil {
t.Fatalf("Error adding fake file: %v\n", ferr) t.Fatalf("Error adding fake file: %v\n", ferr)
} }
r, err := NewResMapFromConfigMapArgs(f, tc.input) r, err := rmF.NewResMapFromConfigMapArgs(cf, tc.input)
if err != nil { if err != nil {
t.Fatalf("unexpected error: %v", err) t.Fatalf("unexpected error: %v", err)
} }

View File

@@ -114,10 +114,10 @@ func (m ResMap) ErrorIfNotEqual(m2 ResMap) error {
} }
// DeepCopy clone the resmap into a new one // DeepCopy clone the resmap into a new one
func (m ResMap) DeepCopy() ResMap { func (m ResMap) DeepCopy(rf *resource.Factory) ResMap {
mcopy := make(ResMap) mcopy := make(ResMap)
for id, obj := range m { for id, obj := range m {
mcopy[id] = resource.NewFromKunstructured(obj.Copy()) mcopy[id] = rf.FromKunstructured(obj.Copy())
mcopy[id].SetBehavior(obj.Behavior()) mcopy[id].SetBehavior(obj.Behavior())
} }
return mcopy return mcopy
@@ -135,17 +135,31 @@ func (m ResMap) FilterBy(inputId resid.ResId) ResMap {
return result return result
} }
// NewResMapFromFiles returns a ResMap given a resource path slice. // Factory makes instances of ResMap.
func NewResMapFromFiles( type Factory struct {
loader ifc.Loader, paths []string, resF *resource.Factory
d ifc.Decoder) (ResMap, error) { }
// NewFactory returns a new resmap.Factory.
func NewFactory(rf *resource.Factory) *Factory {
return &Factory{resF: rf}
}
// RF returns a resource.Factory.
func (rmF *Factory) RF() *resource.Factory {
return rmF.resF
}
// FromFiles returns a ResMap given a resource path slice.
func (rmF *Factory) FromFiles(
loader ifc.Loader, paths []string) (ResMap, error) {
var result []ResMap var result []ResMap
for _, path := range paths { for _, path := range paths {
content, err := loader.Load(path) content, err := loader.Load(path)
if err != nil { if err != nil {
return nil, errors.Wrap(err, "Load from path "+path+" failed") return nil, errors.Wrap(err, "Load from path "+path+" failed")
} }
res, err := newResMapFromBytes(content, d) res, err := rmF.newResMapFromBytes(content)
if err != nil { if err != nil {
return nil, internal.Handler(err, path) return nil, internal.Handler(err, path)
} }
@@ -155,8 +169,8 @@ func NewResMapFromFiles(
} }
// newResMapFromBytes decodes a list of objects in byte array format. // newResMapFromBytes decodes a list of objects in byte array format.
func newResMapFromBytes(b []byte, d ifc.Decoder) (ResMap, error) { func (rmF *Factory) newResMapFromBytes(b []byte) (ResMap, error) {
resources, err := resource.NewSliceFromBytes(b, d) resources, err := rmF.resF.SliceFromBytes(b)
if err != nil { if err != nil {
return nil, err return nil, err
} }

View File

@@ -31,6 +31,9 @@ import (
var deploy = gvk.Gvk{Group: "apps", Version: "v1", Kind: "Deployment"} var deploy = gvk.Gvk{Group: "apps", Version: "v1", Kind: "Deployment"}
var statefulset = gvk.Gvk{Group: "apps", Version: "v1", Kind: "StatefulSet"} var statefulset = gvk.Gvk{Group: "apps", Version: "v1", Kind: "StatefulSet"}
var rf = resource.NewFactory(
k8sdeps.NewKustKunstructuredFactory(k8sdeps.NewKustDecoder()))
var rmF = NewFactory(rf)
func TestEncodeAsYaml(t *testing.T) { func TestEncodeAsYaml(t *testing.T) {
encoded := []byte(`apiVersion: v1 encoded := []byte(`apiVersion: v1
@@ -44,7 +47,7 @@ metadata:
name: cm2 name: cm2
`) `)
input := ResMap{ input := ResMap{
resid.NewResId(cmap, "cm1"): resource.NewFromMap( resid.NewResId(cmap, "cm1"): rf.FromMap(
map[string]interface{}{ map[string]interface{}{
"apiVersion": "v1", "apiVersion": "v1",
"kind": "ConfigMap", "kind": "ConfigMap",
@@ -52,7 +55,7 @@ metadata:
"name": "cm1", "name": "cm1",
}, },
}), }),
resid.NewResId(cmap, "cm2"): resource.NewFromMap( resid.NewResId(cmap, "cm2"): rf.FromMap(
map[string]interface{}{ map[string]interface{}{
"apiVersion": "v1", "apiVersion": "v1",
"kind": "ConfigMap", "kind": "ConfigMap",
@@ -72,7 +75,7 @@ metadata:
func TestDemandOneMatchForId(t *testing.T) { func TestDemandOneMatchForId(t *testing.T) {
rm1 := ResMap{ rm1 := ResMap{
resid.NewResIdWithPrefixNamespace(cmap, "cm1", "prefix1", "ns1"): resource.NewFromMap( resid.NewResIdWithPrefixNamespace(cmap, "cm1", "prefix1", "ns1"): rf.FromMap(
map[string]interface{}{ map[string]interface{}{
"apiVersion": "v1", "apiVersion": "v1",
"kind": "ConfigMap", "kind": "ConfigMap",
@@ -80,7 +83,7 @@ func TestDemandOneMatchForId(t *testing.T) {
"name": "cm1", "name": "cm1",
}, },
}), }),
resid.NewResIdWithPrefixNamespace(cmap, "cm2", "prefix1", "ns1"): resource.NewFromMap( resid.NewResIdWithPrefixNamespace(cmap, "cm2", "prefix1", "ns1"): rf.FromMap(
map[string]interface{}{ map[string]interface{}{
"apiVersion": "v1", "apiVersion": "v1",
"kind": "ConfigMap", "kind": "ConfigMap",
@@ -118,7 +121,7 @@ func TestDemandOneMatchForId(t *testing.T) {
} }
func TestFilterBy(t *testing.T) { func TestFilterBy(t *testing.T) {
rm := ResMap{resid.NewResIdWithPrefixNamespace(cmap, "cm1", "prefix1", "ns1"): resource.NewFromMap( rm := ResMap{resid.NewResIdWithPrefixNamespace(cmap, "cm1", "prefix1", "ns1"): rf.FromMap(
map[string]interface{}{ map[string]interface{}{
"apiVersion": "v1", "apiVersion": "v1",
"kind": "ConfigMap", "kind": "ConfigMap",
@@ -126,7 +129,7 @@ func TestFilterBy(t *testing.T) {
"name": "cm1", "name": "cm1",
}, },
}), }),
resid.NewResIdWithPrefixNamespace(cmap, "cm2", "prefix1", "ns1"): resource.NewFromMap( resid.NewResIdWithPrefixNamespace(cmap, "cm2", "prefix1", "ns1"): rf.FromMap(
map[string]interface{}{ map[string]interface{}{
"apiVersion": "v1", "apiVersion": "v1",
"kind": "ConfigMap", "kind": "ConfigMap",
@@ -136,7 +139,7 @@ func TestFilterBy(t *testing.T) {
}), }),
} }
rm1 := ResMap{ rm1 := ResMap{
resid.NewResIdWithPrefixNamespace(cmap, "cm3", "prefix1", "ns2"): resource.NewFromMap( resid.NewResIdWithPrefixNamespace(cmap, "cm3", "prefix1", "ns2"): rf.FromMap(
map[string]interface{}{ map[string]interface{}{
"apiVersion": "v1", "apiVersion": "v1",
"kind": "ConfigMap", "kind": "ConfigMap",
@@ -162,7 +165,7 @@ func TestFilterBy(t *testing.T) {
} }
func TestDeepCopy(t *testing.T) { func TestDeepCopy(t *testing.T) {
rm1 := ResMap{ rm1 := ResMap{
resid.NewResId(cmap, "cm1"): resource.NewFromMap( resid.NewResId(cmap, "cm1"): rf.FromMap(
map[string]interface{}{ map[string]interface{}{
"apiVersion": "v1", "apiVersion": "v1",
"kind": "ConfigMap", "kind": "ConfigMap",
@@ -170,7 +173,7 @@ func TestDeepCopy(t *testing.T) {
"name": "cm1", "name": "cm1",
}, },
}), }),
resid.NewResId(cmap, "cm2"): resource.NewFromMap( resid.NewResId(cmap, "cm2"): rf.FromMap(
map[string]interface{}{ map[string]interface{}{
"apiVersion": "v1", "apiVersion": "v1",
"kind": "ConfigMap", "kind": "ConfigMap",
@@ -180,7 +183,7 @@ func TestDeepCopy(t *testing.T) {
}), }),
} }
rm2 := rm1.DeepCopy() rm2 := rm1.DeepCopy(rf)
if &rm1 == &rm2 { if &rm1 == &rm2 {
t.Fatal("DeepCopy returned a reference to itself instead of a copy") t.Fatal("DeepCopy returned a reference to itself instead of a copy")
@@ -194,7 +197,7 @@ func TestDeepCopy(t *testing.T) {
func TestErrorIfNotEqual(t *testing.T) { func TestErrorIfNotEqual(t *testing.T) {
rm1 := ResMap{ rm1 := ResMap{
resid.NewResId(cmap, "cm1"): resource.NewFromMap( resid.NewResId(cmap, "cm1"): rf.FromMap(
map[string]interface{}{ map[string]interface{}{
"apiVersion": "v1", "apiVersion": "v1",
"kind": "ConfigMap", "kind": "ConfigMap",
@@ -202,7 +205,7 @@ func TestErrorIfNotEqual(t *testing.T) {
"name": "cm1", "name": "cm1",
}, },
}), }),
resid.NewResId(cmap, "cm2"): resource.NewFromMap( resid.NewResId(cmap, "cm2"): rf.FromMap(
map[string]interface{}{ map[string]interface{}{
"apiVersion": "v1", "apiVersion": "v1",
"kind": "ConfigMap", "kind": "ConfigMap",
@@ -218,7 +221,7 @@ func TestErrorIfNotEqual(t *testing.T) {
} }
rm2 := ResMap{ rm2 := ResMap{
resid.NewResId(cmap, "cm1"): resource.NewFromMap( resid.NewResId(cmap, "cm1"): rf.FromMap(
map[string]interface{}{ map[string]interface{}{
"apiVersion": "v1", "apiVersion": "v1",
"kind": "ConfigMap", "kind": "ConfigMap",
@@ -235,7 +238,7 @@ func TestErrorIfNotEqual(t *testing.T) {
} }
rm3 := ResMap{ rm3 := ResMap{
resid.NewResId(cmap, "cm2"): resource.NewFromMap( resid.NewResId(cmap, "cm2"): rf.FromMap(
map[string]interface{}{ map[string]interface{}{
"apiVersion": "v1", "apiVersion": "v1",
"kind": "ConfigMap", "kind": "ConfigMap",
@@ -252,7 +255,7 @@ func TestErrorIfNotEqual(t *testing.T) {
} }
rm4 := ResMap{ rm4 := ResMap{
resid.NewResId(cmap, "cm1"): resource.NewFromMap( resid.NewResId(cmap, "cm1"): rf.FromMap(
map[string]interface{}{ map[string]interface{}{
"apiVersion": "v1", "apiVersion": "v1",
"kind": "ConfigMap", "kind": "ConfigMap",
@@ -291,7 +294,7 @@ metadata:
if ferr := l.AddFile("/home/seans/project/deployment.yaml", []byte(resourceStr)); ferr != nil { if ferr := l.AddFile("/home/seans/project/deployment.yaml", []byte(resourceStr)); ferr != nil {
t.Fatalf("Error adding fake file: %v\n", ferr) t.Fatalf("Error adding fake file: %v\n", ferr)
} }
expected := ResMap{resid.NewResId(deploy, "dply1"): resource.NewFromMap( expected := ResMap{resid.NewResId(deploy, "dply1"): rf.FromMap(
map[string]interface{}{ map[string]interface{}{
"apiVersion": "apps/v1", "apiVersion": "apps/v1",
"kind": "Deployment", "kind": "Deployment",
@@ -299,7 +302,7 @@ metadata:
"name": "dply1", "name": "dply1",
}, },
}), }),
resid.NewResId(deploy, "dply2"): resource.NewFromMap( resid.NewResId(deploy, "dply2"): rf.FromMap(
map[string]interface{}{ map[string]interface{}{
"apiVersion": "apps/v1", "apiVersion": "apps/v1",
"kind": "Deployment", "kind": "Deployment",
@@ -309,9 +312,8 @@ metadata:
}), }),
} }
m, _ := NewResMapFromFiles( m, _ := rmF.FromFiles(
l, []string{"/home/seans/project/deployment.yaml"}, l, []string{"/home/seans/project/deployment.yaml"})
k8sdeps.NewKustDecoder())
if len(m) != 2 { if len(m) != 2 {
t.Fatalf("%#v should contain 2 appResource, but got %d", m, len(m)) t.Fatalf("%#v should contain 2 appResource, but got %d", m, len(m))
} }
@@ -333,7 +335,7 @@ metadata:
name: cm2 name: cm2
`) `)
expected := ResMap{ expected := ResMap{
resid.NewResId(cmap, "cm1"): resource.NewFromMap( resid.NewResId(cmap, "cm1"): rf.FromMap(
map[string]interface{}{ map[string]interface{}{
"apiVersion": "v1", "apiVersion": "v1",
"kind": "ConfigMap", "kind": "ConfigMap",
@@ -341,7 +343,7 @@ metadata:
"name": "cm1", "name": "cm1",
}, },
}), }),
resid.NewResId(cmap, "cm2"): resource.NewFromMap( resid.NewResId(cmap, "cm2"): rf.FromMap(
map[string]interface{}{ map[string]interface{}{
"apiVersion": "v1", "apiVersion": "v1",
"kind": "ConfigMap", "kind": "ConfigMap",
@@ -350,7 +352,7 @@ metadata:
}, },
}), }),
} }
m, err := newResMapFromBytes(encoded, k8sdeps.NewKustDecoder()) m, err := rmF.newResMapFromBytes(encoded)
fmt.Printf("%v\n", m) fmt.Printf("%v\n", m)
if err != nil { if err != nil {
t.Fatalf("unexpected error: %v", err) t.Fatalf("unexpected error: %v", err)
@@ -362,7 +364,7 @@ metadata:
func TestMergeWithoutOverride(t *testing.T) { func TestMergeWithoutOverride(t *testing.T) {
input1 := ResMap{ input1 := ResMap{
resid.NewResId(deploy, "deploy1"): resource.NewFromMap( resid.NewResId(deploy, "deploy1"): rf.FromMap(
map[string]interface{}{ map[string]interface{}{
"apiVersion": "apps/v1", "apiVersion": "apps/v1",
"kind": "Deployment", "kind": "Deployment",
@@ -372,7 +374,7 @@ func TestMergeWithoutOverride(t *testing.T) {
}), }),
} }
input2 := ResMap{ input2 := ResMap{
resid.NewResId(statefulset, "stateful1"): resource.NewFromMap( resid.NewResId(statefulset, "stateful1"): rf.FromMap(
map[string]interface{}{ map[string]interface{}{
"apiVersion": "apps/v1", "apiVersion": "apps/v1",
"kind": "StatefulSet", "kind": "StatefulSet",
@@ -383,7 +385,7 @@ func TestMergeWithoutOverride(t *testing.T) {
} }
input := []ResMap{input1, input2} input := []ResMap{input1, input2}
expected := ResMap{ expected := ResMap{
resid.NewResId(deploy, "deploy1"): resource.NewFromMap( resid.NewResId(deploy, "deploy1"): rf.FromMap(
map[string]interface{}{ map[string]interface{}{
"apiVersion": "apps/v1", "apiVersion": "apps/v1",
"kind": "Deployment", "kind": "Deployment",
@@ -391,7 +393,7 @@ func TestMergeWithoutOverride(t *testing.T) {
"name": "foo-deploy1", "name": "foo-deploy1",
}, },
}), }),
resid.NewResId(statefulset, "stateful1"): resource.NewFromMap( resid.NewResId(statefulset, "stateful1"): rf.FromMap(
map[string]interface{}{ map[string]interface{}{
"apiVersion": "apps/v1", "apiVersion": "apps/v1",
"kind": "StatefulSet", "kind": "StatefulSet",
@@ -428,7 +430,7 @@ func TestMergeWithoutOverride(t *testing.T) {
func generateMergeFixtures(b ifc.GenerationBehavior) []ResMap { func generateMergeFixtures(b ifc.GenerationBehavior) []ResMap {
input1 := ResMap{ input1 := ResMap{
resid.NewResId(cmap, "cmap"): resource.NewFromMap( resid.NewResId(cmap, "cmap"): rf.FromMap(
map[string]interface{}{ map[string]interface{}{
"apiVersion": "apps/v1", "apiVersion": "apps/v1",
"kind": "ConfigMap", "kind": "ConfigMap",
@@ -442,7 +444,7 @@ func generateMergeFixtures(b ifc.GenerationBehavior) []ResMap {
}), }),
} }
input2 := ResMap{ input2 := ResMap{
resid.NewResId(cmap, "cmap"): resource.NewFromMap( resid.NewResId(cmap, "cmap"): rf.FromMap(
map[string]interface{}{ map[string]interface{}{
"apiVersion": "apps/v1", "apiVersion": "apps/v1",
"kind": "ConfigMap", "kind": "ConfigMap",
@@ -463,7 +465,7 @@ func generateMergeFixtures(b ifc.GenerationBehavior) []ResMap {
func TestMergeWithOverride(t *testing.T) { func TestMergeWithOverride(t *testing.T) {
expected := ResMap{ expected := ResMap{
resid.NewResId(cmap, "cmap"): resource.NewFromMap( resid.NewResId(cmap, "cmap"): rf.FromMap(
map[string]interface{}{ map[string]interface{}{
"apiVersion": "apps/v1", "apiVersion": "apps/v1",
"kind": "ConfigMap", "kind": "ConfigMap",

View File

@@ -26,7 +26,7 @@ import (
// NewResMapFromSecretArgs takes a SecretArgs slice, generates // NewResMapFromSecretArgs takes a SecretArgs slice, generates
// secrets from each entry, and accumulates them in a ResMap. // secrets from each entry, and accumulates them in a ResMap.
func NewResMapFromSecretArgs( func (rmF *Factory) NewResMapFromSecretArgs(
f *configmapandsecret.SecretFactory, f *configmapandsecret.SecretFactory,
secretList []types.SecretArgs) (ResMap, error) { secretList []types.SecretArgs) (ResMap, error) {
var allResources []*resource.Resource var allResources []*resource.Resource
@@ -38,10 +38,10 @@ func NewResMapFromSecretArgs(
if args.Behavior == "" { if args.Behavior == "" {
args.Behavior = "create" args.Behavior = "create"
} }
res, err := resource.NewWithBehavior( res, err := rmF.resF.WithBehavior(
s, ifc.NewGenerationBehavior(args.Behavior)) s, ifc.NewGenerationBehavior(args.Behavior))
if err != nil { if err != nil {
return nil, errors.Wrap(err, "NewWithBehavior") return nil, errors.Wrap(err, "WithBehavior")
} }
allResources = append(allResources, res) allResources = append(allResources, res)
} }

View File

@@ -27,7 +27,6 @@ import (
"sigs.k8s.io/kustomize/pkg/gvk" "sigs.k8s.io/kustomize/pkg/gvk"
"sigs.k8s.io/kustomize/pkg/ifc" "sigs.k8s.io/kustomize/pkg/ifc"
"sigs.k8s.io/kustomize/pkg/resid" "sigs.k8s.io/kustomize/pkg/resid"
"sigs.k8s.io/kustomize/pkg/resource"
"sigs.k8s.io/kustomize/pkg/types" "sigs.k8s.io/kustomize/pkg/types"
) )
@@ -55,7 +54,7 @@ func TestNewResMapFromSecretArgs(t *testing.T) {
} }
fakeFs := fs.MakeFakeFS() fakeFs := fs.MakeFakeFS()
fakeFs.Mkdir(".") fakeFs.Mkdir(".")
actual, err := NewResMapFromSecretArgs( actual, err := rmF.NewResMapFromSecretArgs(
configmapandsecret.NewSecretFactory(fakeFs, "."), secrets) configmapandsecret.NewSecretFactory(fakeFs, "."), secrets)
if err != nil { if err != nil {
@@ -63,7 +62,7 @@ func TestNewResMapFromSecretArgs(t *testing.T) {
} }
expected := ResMap{ expected := ResMap{
resid.NewResId(secret, "apple"): resource.NewFromMap( resid.NewResId(secret, "apple"): rf.FromMap(
map[string]interface{}{ map[string]interface{}{
"apiVersion": "v1", "apiVersion": "v1",
"kind": "Secret", "kind": "Secret",
@@ -76,7 +75,7 @@ func TestNewResMapFromSecretArgs(t *testing.T) {
"DB_PASSWORD": base64.StdEncoding.EncodeToString([]byte("somepw")), "DB_PASSWORD": base64.StdEncoding.EncodeToString([]byte("somepw")),
}, },
}).SetBehavior(ifc.BehaviorCreate), }).SetBehavior(ifc.BehaviorCreate),
resid.NewResId(secret, "peanuts"): resource.NewFromMap( resid.NewResId(secret, "peanuts"): rf.FromMap(
map[string]interface{}{ map[string]interface{}{
"apiVersion": "v1", "apiVersion": "v1",
"kind": "Secret", "kind": "Secret",
@@ -111,7 +110,7 @@ func TestSecretTimeout(t *testing.T) {
} }
fakeFs := fs.MakeFakeFS() fakeFs := fs.MakeFakeFS()
fakeFs.Mkdir(".") fakeFs.Mkdir(".")
_, err := NewResMapFromSecretArgs( _, err := rmF.NewResMapFromSecretArgs(
configmapandsecret.NewSecretFactory(fakeFs, "."), secrets) configmapandsecret.NewSecretFactory(fakeFs, "."), secrets)
if err == nil { if err == nil {

View File

@@ -29,46 +29,53 @@ import (
"sigs.k8s.io/kustomize/pkg/resid" "sigs.k8s.io/kustomize/pkg/resid"
) )
// Resource is map representation of a Kubernetes API resource object // Factory makes instances of Resource.
// paired with a GenerationBehavior. type Factory struct {
type Resource struct { kf ifc.KunstructuredFactory
ifc.Kunstructured
b ifc.GenerationBehavior
} }
// NewWithBehavior returns a new instance of Resource. // NewFactory makes an instance of Factory.
func NewWithBehavior(obj runtime.Object, b ifc.GenerationBehavior) (*Resource, error) { func NewFactory(kf ifc.KunstructuredFactory) *Factory {
return &Factory{kf: kf}
}
// WithBehavior returns a new instance of Resource.
// TODO(monopole): This runtime dependence must be refactored away.
// The logic calling this has to move to k8sdeps.
func (rf *Factory) WithBehavior(
obj runtime.Object, b ifc.GenerationBehavior) (*Resource, error) {
// TODO(monopole): This k8sdeps dependence must be refactored away.
u, err := k8sdeps.NewKunstructuredFromObject(obj) u, err := k8sdeps.NewKunstructuredFromObject(obj)
return &Resource{Kunstructured: u, b: b}, err return &Resource{Kunstructured: u, b: b}, err
} }
// NewFromMap returns a new instance of Resource. // FromMap returns a new instance of Resource.
func NewFromMap(m map[string]interface{}) *Resource { func (rf *Factory) FromMap(m map[string]interface{}) *Resource {
return &Resource{ return &Resource{
Kunstructured: k8sdeps.NewKunstructuredFromMap(m), Kunstructured: rf.kf.FromMap(m),
b: ifc.BehaviorUnspecified} b: ifc.BehaviorUnspecified}
} }
// NewFromKunstructured returns a new instance of Resource. // FromKunstructured returns a new instance of Resource.
func NewFromKunstructured(u ifc.Kunstructured) *Resource { func (rf *Factory) FromKunstructured(
u ifc.Kunstructured) *Resource {
if u == nil { if u == nil {
log.Fatal("unstruct ifc must not be null") log.Fatal("unstruct ifc must not be null")
} }
return &Resource{Kunstructured: u, b: ifc.BehaviorUnspecified} return &Resource{Kunstructured: u, b: ifc.BehaviorUnspecified}
} }
// NewSliceFromPatches returns a slice of resources given a patch path // SliceFromPatches returns a slice of resources given a patch path
// slice from a kustomization file. // slice from a kustomization file.
func NewSliceFromPatches( func (rf *Factory) SliceFromPatches(
ldr ifc.Loader, paths []patch.StrategicMerge, ldr ifc.Loader, paths []patch.StrategicMerge) ([]*Resource, error) {
decoder ifc.Decoder) ([]*Resource, error) {
var result []*Resource var result []*Resource
for _, path := range paths { for _, path := range paths {
content, err := ldr.Load(string(path)) content, err := ldr.Load(string(path))
if err != nil { if err != nil {
return nil, err return nil, err
} }
res, err := NewSliceFromBytes(content, decoder) res, err := rf.SliceFromBytes(content)
if err != nil { if err != nil {
return nil, internal.Handler(err, string(path)) return nil, internal.Handler(err, string(path))
} }
@@ -77,20 +84,26 @@ func NewSliceFromPatches(
return result, nil return result, nil
} }
// NewSliceFromBytes unmarshalls bytes into a Resource slice. // SliceFromBytes unmarshalls bytes into a Resource slice.
func NewSliceFromBytes( func (rf *Factory) SliceFromBytes(in []byte) ([]*Resource, error) {
in []byte, decoder ifc.Decoder) ([]*Resource, error) { kunStructs, err := rf.kf.SliceFromBytes(in)
funStructs, err := k8sdeps.NewKunstructuredSliceFromBytes(in, decoder)
if err != nil { if err != nil {
return nil, err return nil, err
} }
var result []*Resource var result []*Resource
for _, u := range funStructs { for _, u := range kunStructs {
result = append(result, NewFromKunstructured(u)) result = append(result, rf.FromKunstructured(u))
} }
return result, nil return result, nil
} }
// Resource is map representation of a Kubernetes API resource object
// paired with a GenerationBehavior.
type Resource struct {
ifc.Kunstructured
b ifc.GenerationBehavior
}
// String returns resource as JSON. // String returns resource as JSON.
func (r *Resource) String() string { func (r *Resource) String() string {
bs, err := r.MarshalJSON() bs, err := r.MarshalJSON()

View File

@@ -18,14 +18,17 @@ package resource
import ( import (
"reflect" "reflect"
"sigs.k8s.io/kustomize/internal/k8sdeps"
"testing" "testing"
"sigs.k8s.io/kustomize/internal/k8sdeps"
"sigs.k8s.io/kustomize/pkg/internal/loadertest" "sigs.k8s.io/kustomize/pkg/internal/loadertest"
"sigs.k8s.io/kustomize/pkg/patch" "sigs.k8s.io/kustomize/pkg/patch"
) )
var testConfigMap = NewFromMap( var factory = NewFactory(
k8sdeps.NewKustKunstructuredFactory(k8sdeps.NewKustDecoder()))
var testConfigMap = factory.FromMap(
map[string]interface{}{ map[string]interface{}{
"apiVersion": "v1", "apiVersion": "v1",
"kind": "ConfigMap", "kind": "ConfigMap",
@@ -36,7 +39,7 @@ var testConfigMap = NewFromMap(
const testConfigMapString = `unspecified:{"apiVersion":"v1","kind":"ConfigMap","metadata":{"name":"winnie"}}` const testConfigMapString = `unspecified:{"apiVersion":"v1","kind":"ConfigMap","metadata":{"name":"winnie"}}`
var testDeployment = NewFromMap( var testDeployment = factory.FromMap(
map[string]interface{}{ map[string]interface{}{
"apiVersion": "apps/v1", "apiVersion": "apps/v1",
"kind": "Deployment", "kind": "Deployment",
@@ -68,7 +71,8 @@ func TestResourceString(t *testing.T) {
} }
} }
func TestNewResourceSliceFromPatches(t *testing.T) { func TestSliceFromPatches(t *testing.T) {
patchGood1 := patch.StrategicMerge("/foo/patch1.yaml") patchGood1 := patch.StrategicMerge("/foo/patch1.yaml")
patch1 := ` patch1 := `
apiVersion: apps/v1 apiVersion: apps/v1
@@ -122,8 +126,7 @@ WOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOT: woot
}, },
} }
for _, test := range tests { for _, test := range tests {
rs, err := NewSliceFromPatches( rs, err := factory.SliceFromPatches(l, test.input)
l, test.input, k8sdeps.NewKustDecoder())
if test.expectedErr && err == nil { if test.expectedErr && err == nil {
t.Fatalf("%v: should return error", test.name) t.Fatalf("%v: should return error", test.name)
} }

View File

@@ -47,12 +47,14 @@ type KustTarget struct {
hash ifc.Hash hash ifc.Hash
ldr ifc.Loader ldr ifc.Loader
fSys fs.FileSystem fSys fs.FileSystem
rf *resmap.Factory
tcfg *transformerconfig.TransformerConfig tcfg *transformerconfig.TransformerConfig
} }
// NewKustTarget returns a new instance of KustTarget primed with a Loader. // NewKustTarget returns a new instance of KustTarget primed with a Loader.
func NewKustTarget( func NewKustTarget(
ldr ifc.Loader, fSys fs.FileSystem, ldr ifc.Loader, fSys fs.FileSystem,
rf *resmap.Factory,
tcfg *transformerconfig.TransformerConfig, tcfg *transformerconfig.TransformerConfig,
d ifc.Decoder, h ifc.Hash) (*KustTarget, error) { d ifc.Decoder, h ifc.Hash) (*KustTarget, error) {
content, err := ldr.Load(constants.KustomizationFileName) content, err := ldr.Load(constants.KustomizationFileName)
@@ -70,6 +72,7 @@ func NewKustTarget(
kustomization: &k, kustomization: &k,
ldr: ldr, ldr: ldr,
fSys: fSys, fSys: fSys,
rf: rf,
tcfg: tcfg, tcfg: tcfg,
decoder: d, decoder: d,
hash: h, hash: h,
@@ -146,10 +149,10 @@ func (kt *KustTarget) loadCustomizedResMap() (resmap.ResMap, error) {
return nil, err return nil, err
} }
patches, err := resource.NewSliceFromPatches( patches, err := kt.rf.RF().SliceFromPatches(
kt.ldr, kt.kustomization.PatchesStrategicMerge, kt.decoder) kt.ldr, kt.kustomization.PatchesStrategicMerge)
if err != nil { if err != nil {
errs.Append(errors.Wrap(err, "NewSliceFromPatches")) errs.Append(errors.Wrap(err, "SliceFromPatches"))
} }
if len(errs.Get()) > 0 { if len(errs.Get()) > 0 {
@@ -183,13 +186,13 @@ func (kt *KustTarget) loadCustomizedResMap() (resmap.ResMap, error) {
func (kt *KustTarget) generateConfigMapsAndSecrets( func (kt *KustTarget) generateConfigMapsAndSecrets(
errs *interror.KustomizationErrors) (resmap.ResMap, error) { errs *interror.KustomizationErrors) (resmap.ResMap, error) {
cms, err := resmap.NewResMapFromConfigMapArgs( cms, err := kt.rf.NewResMapFromConfigMapArgs(
configmapandsecret.NewConfigMapFactory(kt.fSys, kt.ldr), configmapandsecret.NewConfigMapFactory(kt.fSys, kt.ldr),
kt.kustomization.ConfigMapGenerator) kt.kustomization.ConfigMapGenerator)
if err != nil { if err != nil {
errs.Append(errors.Wrap(err, "NewResMapFromConfigMapArgs")) errs.Append(errors.Wrap(err, "NewResMapFromConfigMapArgs"))
} }
secrets, err := resmap.NewResMapFromSecretArgs( secrets, err := kt.rf.NewResMapFromSecretArgs(
configmapandsecret.NewSecretFactory(kt.fSys, kt.ldr.Root()), configmapandsecret.NewSecretFactory(kt.fSys, kt.ldr.Root()),
kt.kustomization.SecretGenerator) kt.kustomization.SecretGenerator)
if err != nil { if err != nil {
@@ -201,8 +204,8 @@ func (kt *KustTarget) generateConfigMapsAndSecrets(
// Gets Bases and Resources as advertised. // Gets Bases and Resources as advertised.
func (kt *KustTarget) loadResMapFromBasesAndResources() (resmap.ResMap, error) { func (kt *KustTarget) loadResMapFromBasesAndResources() (resmap.ResMap, error) {
bases, errs := kt.loadCustomizedBases() bases, errs := kt.loadCustomizedBases()
resources, err := resmap.NewResMapFromFiles( resources, err := kt.rf.FromFiles(
kt.ldr, kt.kustomization.Resources, kt.decoder) kt.ldr, kt.kustomization.Resources)
if err != nil { if err != nil {
errs.Append(errors.Wrap(err, "rawResources failed to read Resources")) errs.Append(errors.Wrap(err, "rawResources failed to read Resources"))
} }
@@ -223,7 +226,8 @@ func (kt *KustTarget) loadCustomizedBases() (resmap.ResMap, *interror.Kustomizat
errs.Append(errors.Wrap(err, "couldn't make ldr for "+path)) errs.Append(errors.Wrap(err, "couldn't make ldr for "+path))
continue continue
} }
target, err := NewKustTarget(ldr, kt.fSys, kt.tcfg, kt.decoder, kt.hash) target, err := NewKustTarget(
ldr, kt.fSys, kt.rf, kt.tcfg, kt.decoder, kt.hash)
if err != nil { if err != nil {
errs.Append(errors.Wrap(err, "couldn't make target for "+path)) errs.Append(errors.Wrap(err, "couldn't make target for "+path))
continue continue
@@ -252,7 +256,8 @@ func (kt *KustTarget) loadBasesAsFlatList() ([]*KustTarget, error) {
errs.Append(err) errs.Append(err)
continue continue
} }
target, err := NewKustTarget(ldr, kt.fSys, kt.tcfg, kt.decoder, kt.hash) target, err := NewKustTarget(
ldr, kt.fSys, kt.rf, kt.tcfg, kt.decoder, kt.hash)
if err != nil { if err != nil {
errs.Append(err) errs.Append(err)
continue continue
@@ -268,7 +273,7 @@ func (kt *KustTarget) loadBasesAsFlatList() ([]*KustTarget, error) {
// newTransformer makes a Transformer that does everything except resolve generated names. // newTransformer makes a Transformer that does everything except resolve generated names.
func (kt *KustTarget) newTransformer(patches []*resource.Resource) (transformers.Transformer, error) { func (kt *KustTarget) newTransformer(patches []*resource.Resource) (transformers.Transformer, error) {
var r []transformers.Transformer var r []transformers.Transformer
t, err := transformers.NewPatchTransformer(patches) t, err := transformers.NewPatchTransformer(patches, kt.rf.RF())
if err != nil { if err != nil {
return nil, err return nil, err
} }

View File

@@ -88,6 +88,9 @@ metadata:
]` ]`
) )
var rf = resmap.NewFactory(resource.NewFactory(
k8sdeps.NewKustKunstructuredFactory(k8sdeps.NewKustDecoder())))
func makeLoader1(t *testing.T) ifc.Loader { func makeLoader1(t *testing.T) ifc.Loader {
ldr := loadertest.NewFakeLoader("/testpath") ldr := loadertest.NewFakeLoader("/testpath")
err := ldr.AddFile("/testpath/"+constants.KustomizationFileName, []byte(kustomizationContent1)) err := ldr.AddFile("/testpath/"+constants.KustomizationFileName, []byte(kustomizationContent1))
@@ -116,7 +119,7 @@ var ns = gvk.Gvk{Version: "v1", Kind: "Namespace"}
func TestResources1(t *testing.T) { func TestResources1(t *testing.T) {
expected := resmap.ResMap{ expected := resmap.ResMap{
resid.NewResIdWithPrefixNamespace(deploy, "dply1", "foo-", "ns1"): resource.NewFromMap( resid.NewResIdWithPrefixNamespace(deploy, "dply1", "foo-", "ns1"): rf.RF().FromMap(
map[string]interface{}{ map[string]interface{}{
"apiVersion": "apps/v1", "apiVersion": "apps/v1",
"kind": "Deployment", "kind": "Deployment",
@@ -149,7 +152,7 @@ func TestResources1(t *testing.T) {
}, },
}, },
}), }),
resid.NewResIdWithPrefixNamespace(cmap, "literalConfigMap", "foo-", "ns1"): resource.NewFromMap( resid.NewResIdWithPrefixNamespace(cmap, "literalConfigMap", "foo-", "ns1"): rf.RF().FromMap(
map[string]interface{}{ map[string]interface{}{
"apiVersion": "v1", "apiVersion": "v1",
"kind": "ConfigMap", "kind": "ConfigMap",
@@ -168,7 +171,7 @@ func TestResources1(t *testing.T) {
"DB_PASSWORD": "somepw", "DB_PASSWORD": "somepw",
}, },
}).SetBehavior(ifc.BehaviorCreate), }).SetBehavior(ifc.BehaviorCreate),
resid.NewResIdWithPrefixNamespace(secret, "secret", "foo-", "ns1"): resource.NewFromMap( resid.NewResIdWithPrefixNamespace(secret, "secret", "foo-", "ns1"): rf.RF().FromMap(
map[string]interface{}{ map[string]interface{}{
"apiVersion": "v1", "apiVersion": "v1",
"kind": "Secret", "kind": "Secret",
@@ -188,7 +191,7 @@ func TestResources1(t *testing.T) {
"DB_PASSWORD": base64.StdEncoding.EncodeToString([]byte("somepw")), "DB_PASSWORD": base64.StdEncoding.EncodeToString([]byte("somepw")),
}, },
}).SetBehavior(ifc.BehaviorCreate), }).SetBehavior(ifc.BehaviorCreate),
resid.NewResIdWithPrefixNamespace(ns, "ns1", "foo-", ""): resource.NewFromMap( resid.NewResIdWithPrefixNamespace(ns, "ns1", "foo-", ""): rf.RF().FromMap(
map[string]interface{}{ map[string]interface{}{
"apiVersion": "v1", "apiVersion": "v1",
"kind": "Namespace", "kind": "Namespace",
@@ -207,7 +210,7 @@ func TestResources1(t *testing.T) {
fakeFs := fs.MakeFakeFS() fakeFs := fs.MakeFakeFS()
fakeFs.Mkdir("/") fakeFs.Mkdir("/")
kt, err := NewKustTarget( kt, err := NewKustTarget(
l, fakeFs, transformerconfig.MakeDefaultTransformerConfig(), l, fakeFs, rf, transformerconfig.MakeDefaultTransformerConfig(),
k8sdeps.NewKustDecoder(), k8sdeps.NewKustHash()) k8sdeps.NewKustDecoder(), k8sdeps.NewKustHash())
if err != nil { if err != nil {
t.Fatalf("unexpected construction error %v", err) t.Fatalf("unexpected construction error %v", err)
@@ -232,7 +235,7 @@ func TestResourceNotFound(t *testing.T) {
fakeFs := fs.MakeFakeFS() fakeFs := fs.MakeFakeFS()
fakeFs.Mkdir("/") fakeFs.Mkdir("/")
kt, err := NewKustTarget( kt, err := NewKustTarget(
l, fakeFs, transformerconfig.MakeDefaultTransformerConfig(), l, fakeFs, rf, transformerconfig.MakeDefaultTransformerConfig(),
k8sdeps.NewKustDecoder(), k8sdeps.NewKustHash()) k8sdeps.NewKustDecoder(), k8sdeps.NewKustHash())
if err != nil { if err != nil {
t.Fatalf("Unexpected construction error %v", err) t.Fatalf("Unexpected construction error %v", err)
@@ -255,7 +258,7 @@ func TestSecretTimeout(t *testing.T) {
fakeFs := fs.MakeFakeFS() fakeFs := fs.MakeFakeFS()
fakeFs.Mkdir("/") fakeFs.Mkdir("/")
kt, err := NewKustTarget( kt, err := NewKustTarget(
l, fakeFs, transformerconfig.MakeDefaultTransformerConfig(), l, fakeFs, rf, transformerconfig.MakeDefaultTransformerConfig(),
k8sdeps.NewKustDecoder(), k8sdeps.NewKustHash()) k8sdeps.NewKustDecoder(), k8sdeps.NewKustHash())
if err != nil { if err != nil {
t.Fatalf("Unexpected construction error %v", err) t.Fatalf("Unexpected construction error %v", err)

View File

@@ -18,18 +18,22 @@ package transformers
import ( import (
"reflect" "reflect"
"sigs.k8s.io/kustomize/pkg/resid"
"testing" "testing"
"sigs.k8s.io/kustomize/internal/k8sdeps"
"sigs.k8s.io/kustomize/pkg/gvk" "sigs.k8s.io/kustomize/pkg/gvk"
"sigs.k8s.io/kustomize/pkg/resid"
"sigs.k8s.io/kustomize/pkg/resmap" "sigs.k8s.io/kustomize/pkg/resmap"
"sigs.k8s.io/kustomize/pkg/resource" "sigs.k8s.io/kustomize/pkg/resource"
"sigs.k8s.io/kustomize/pkg/types" "sigs.k8s.io/kustomize/pkg/types"
) )
func TestImageTagTransformer(t *testing.T) { func TestImageTagTransformer(t *testing.T) {
var rf = resource.NewFactory(
k8sdeps.NewKustKunstructuredFactory(k8sdeps.NewKustDecoder()))
m := resmap.ResMap{ m := resmap.ResMap{
resid.NewResId(deploy, "deploy1"): resource.NewFromMap( resid.NewResId(deploy, "deploy1"): rf.FromMap(
map[string]interface{}{ map[string]interface{}{
"group": "apps", "group": "apps",
"apiVersion": "v1", "apiVersion": "v1",
@@ -60,7 +64,7 @@ func TestImageTagTransformer(t *testing.T) {
}, },
}, },
}), }),
resid.NewResId(gvk.Gvk{Kind: "randomKind"}, "random"): resource.NewFromMap( resid.NewResId(gvk.Gvk{Kind: "randomKind"}, "random"): rf.FromMap(
map[string]interface{}{ map[string]interface{}{
"spec": map[string]interface{}{ "spec": map[string]interface{}{
"template": map[string]interface{}{ "template": map[string]interface{}{
@@ -97,7 +101,7 @@ func TestImageTagTransformer(t *testing.T) {
}), }),
} }
expected := resmap.ResMap{ expected := resmap.ResMap{
resid.NewResId(deploy, "deploy1"): resource.NewFromMap( resid.NewResId(deploy, "deploy1"): rf.FromMap(
map[string]interface{}{ map[string]interface{}{
"group": "apps", "group": "apps",
"apiVersion": "v1", "apiVersion": "v1",
@@ -128,7 +132,7 @@ func TestImageTagTransformer(t *testing.T) {
}, },
}, },
}), }),
resid.NewResId(gvk.Gvk{Kind: "randomKind"}, "random"): resource.NewFromMap( resid.NewResId(gvk.Gvk{Kind: "randomKind"}, "random"): rf.FromMap(
map[string]interface{}{ map[string]interface{}{
"spec": map[string]interface{}{ "spec": map[string]interface{}{
"template": map[string]interface{}{ "template": map[string]interface{}{

View File

@@ -20,6 +20,7 @@ import (
"reflect" "reflect"
"testing" "testing"
"sigs.k8s.io/kustomize/internal/k8sdeps"
"sigs.k8s.io/kustomize/pkg/gvk" "sigs.k8s.io/kustomize/pkg/gvk"
"sigs.k8s.io/kustomize/pkg/resid" "sigs.k8s.io/kustomize/pkg/resid"
"sigs.k8s.io/kustomize/pkg/resmap" "sigs.k8s.io/kustomize/pkg/resmap"
@@ -41,10 +42,12 @@ var pvc = gvk.Gvk{Version: "v1", Kind: "PersistentVolumeClaim"}
var crb = gvk.Gvk{Group: "rbac.authorization.k8s.io", Version: "v1", Kind: "ClusterRoleBinding"} var crb = gvk.Gvk{Group: "rbac.authorization.k8s.io", Version: "v1", Kind: "ClusterRoleBinding"}
var sa = gvk.Gvk{Version: "v1", Kind: "ServiceAccount"} var sa = gvk.Gvk{Version: "v1", Kind: "ServiceAccount"}
var ingress = gvk.Gvk{Kind: "Ingress"} var ingress = gvk.Gvk{Kind: "Ingress"}
var rf = resource.NewFactory(
k8sdeps.NewKustKunstructuredFactory(k8sdeps.NewKustDecoder()))
func TestLabelsRun(t *testing.T) { func TestLabelsRun(t *testing.T) {
m := resmap.ResMap{ m := resmap.ResMap{
resid.NewResId(cmap, "cm1"): resource.NewFromMap( resid.NewResId(cmap, "cm1"): rf.FromMap(
map[string]interface{}{ map[string]interface{}{
"apiVersion": "v1", "apiVersion": "v1",
"kind": "ConfigMap", "kind": "ConfigMap",
@@ -52,7 +55,7 @@ func TestLabelsRun(t *testing.T) {
"name": "cm1", "name": "cm1",
}, },
}), }),
resid.NewResId(deploy, "deploy1"): resource.NewFromMap( resid.NewResId(deploy, "deploy1"): rf.FromMap(
map[string]interface{}{ map[string]interface{}{
"group": "apps", "group": "apps",
"apiVersion": "v1", "apiVersion": "v1",
@@ -78,7 +81,7 @@ func TestLabelsRun(t *testing.T) {
}, },
}, },
}), }),
resid.NewResId(service, "svc1"): resource.NewFromMap( resid.NewResId(service, "svc1"): rf.FromMap(
map[string]interface{}{ map[string]interface{}{
"apiVersion": "v1", "apiVersion": "v1",
"kind": "Service", "kind": "Service",
@@ -94,7 +97,7 @@ func TestLabelsRun(t *testing.T) {
}, },
}, },
}), }),
resid.NewResId(job, "job1"): resource.NewFromMap( resid.NewResId(job, "job1"): rf.FromMap(
map[string]interface{}{ map[string]interface{}{
"apiVersion": "batch/v1", "apiVersion": "batch/v1",
"kind": "Job", "kind": "Job",
@@ -114,7 +117,7 @@ func TestLabelsRun(t *testing.T) {
}, },
}, },
}), }),
resid.NewResId(job, "job2"): resource.NewFromMap( resid.NewResId(job, "job2"): rf.FromMap(
map[string]interface{}{ map[string]interface{}{
"apiVersion": "batch/v1", "apiVersion": "batch/v1",
"kind": "Job", "kind": "Job",
@@ -139,7 +142,7 @@ func TestLabelsRun(t *testing.T) {
}, },
}, },
}), }),
resid.NewResId(cronjob, "cronjob1"): resource.NewFromMap( resid.NewResId(cronjob, "cronjob1"): rf.FromMap(
map[string]interface{}{ map[string]interface{}{
"apiVersion": "batch/v1beta1", "apiVersion": "batch/v1beta1",
"kind": "CronJob", "kind": "CronJob",
@@ -164,7 +167,7 @@ func TestLabelsRun(t *testing.T) {
}, },
}, },
}), }),
resid.NewResId(cronjob, "cronjob2"): resource.NewFromMap( resid.NewResId(cronjob, "cronjob2"): rf.FromMap(
map[string]interface{}{ map[string]interface{}{
"apiVersion": "batch/v1beta1", "apiVersion": "batch/v1beta1",
"kind": "CronJob", "kind": "CronJob",
@@ -196,7 +199,7 @@ func TestLabelsRun(t *testing.T) {
}), }),
} }
expected := resmap.ResMap{ expected := resmap.ResMap{
resid.NewResId(cmap, "cm1"): resource.NewFromMap( resid.NewResId(cmap, "cm1"): rf.FromMap(
map[string]interface{}{ map[string]interface{}{
"apiVersion": "v1", "apiVersion": "v1",
"kind": "ConfigMap", "kind": "ConfigMap",
@@ -208,7 +211,7 @@ func TestLabelsRun(t *testing.T) {
}, },
}, },
}), }),
resid.NewResId(deploy, "deploy1"): resource.NewFromMap( resid.NewResId(deploy, "deploy1"): rf.FromMap(
map[string]interface{}{ map[string]interface{}{
"group": "apps", "group": "apps",
"apiVersion": "v1", "apiVersion": "v1",
@@ -246,7 +249,7 @@ func TestLabelsRun(t *testing.T) {
}, },
}, },
}), }),
resid.NewResId(service, "svc1"): resource.NewFromMap( resid.NewResId(service, "svc1"): rf.FromMap(
map[string]interface{}{ map[string]interface{}{
"apiVersion": "v1", "apiVersion": "v1",
"kind": "Service", "kind": "Service",
@@ -270,7 +273,7 @@ func TestLabelsRun(t *testing.T) {
}, },
}, },
}), }),
resid.NewResId(job, "job1"): resource.NewFromMap( resid.NewResId(job, "job1"): rf.FromMap(
map[string]interface{}{ map[string]interface{}{
"apiVersion": "batch/v1", "apiVersion": "batch/v1",
"kind": "Job", "kind": "Job",
@@ -300,7 +303,7 @@ func TestLabelsRun(t *testing.T) {
}, },
}, },
}), }),
resid.NewResId(job, "job2"): resource.NewFromMap( resid.NewResId(job, "job2"): rf.FromMap(
map[string]interface{}{ map[string]interface{}{
"apiVersion": "batch/v1", "apiVersion": "batch/v1",
"kind": "Job", "kind": "Job",
@@ -337,7 +340,7 @@ func TestLabelsRun(t *testing.T) {
}, },
}, },
}), }),
resid.NewResId(cronjob, "cronjob1"): resource.NewFromMap( resid.NewResId(cronjob, "cronjob1"): rf.FromMap(
map[string]interface{}{ map[string]interface{}{
"apiVersion": "batch/v1beta1", "apiVersion": "batch/v1beta1",
"kind": "CronJob", "kind": "CronJob",
@@ -372,7 +375,7 @@ func TestLabelsRun(t *testing.T) {
}, },
}, },
}), }),
resid.NewResId(cronjob, "cronjob2"): resource.NewFromMap( resid.NewResId(cronjob, "cronjob2"): rf.FromMap(
map[string]interface{}{ map[string]interface{}{
"apiVersion": "batch/v1beta1", "apiVersion": "batch/v1beta1",
"kind": "CronJob", "kind": "CronJob",
@@ -433,7 +436,7 @@ func TestLabelsRun(t *testing.T) {
func TestAnnotationsRun(t *testing.T) { func TestAnnotationsRun(t *testing.T) {
m := resmap.ResMap{ m := resmap.ResMap{
resid.NewResId(cmap, "cm1"): resource.NewFromMap( resid.NewResId(cmap, "cm1"): rf.FromMap(
map[string]interface{}{ map[string]interface{}{
"apiVersion": "v1", "apiVersion": "v1",
"kind": "ConfigMap", "kind": "ConfigMap",
@@ -441,7 +444,7 @@ func TestAnnotationsRun(t *testing.T) {
"name": "cm1", "name": "cm1",
}, },
}), }),
resid.NewResId(deploy, "deploy1"): resource.NewFromMap( resid.NewResId(deploy, "deploy1"): rf.FromMap(
map[string]interface{}{ map[string]interface{}{
"group": "apps", "group": "apps",
"apiVersion": "v1", "apiVersion": "v1",
@@ -467,7 +470,7 @@ func TestAnnotationsRun(t *testing.T) {
}, },
}, },
}), }),
resid.NewResId(service, "svc1"): resource.NewFromMap( resid.NewResId(service, "svc1"): rf.FromMap(
map[string]interface{}{ map[string]interface{}{
"apiVersion": "v1", "apiVersion": "v1",
"kind": "Service", "kind": "Service",
@@ -485,7 +488,7 @@ func TestAnnotationsRun(t *testing.T) {
}), }),
} }
expected := resmap.ResMap{ expected := resmap.ResMap{
resid.NewResId(cmap, "cm1"): resource.NewFromMap( resid.NewResId(cmap, "cm1"): rf.FromMap(
map[string]interface{}{ map[string]interface{}{
"apiVersion": "v1", "apiVersion": "v1",
"kind": "ConfigMap", "kind": "ConfigMap",
@@ -497,7 +500,7 @@ func TestAnnotationsRun(t *testing.T) {
}, },
}, },
}), }),
resid.NewResId(deploy, "deploy1"): resource.NewFromMap( resid.NewResId(deploy, "deploy1"): rf.FromMap(
map[string]interface{}{ map[string]interface{}{
"group": "apps", "group": "apps",
"apiVersion": "v1", "apiVersion": "v1",
@@ -531,7 +534,7 @@ func TestAnnotationsRun(t *testing.T) {
}, },
}, },
}), }),
resid.NewResId(service, "svc1"): resource.NewFromMap( resid.NewResId(service, "svc1"): rf.FromMap(
map[string]interface{}{ map[string]interface{}{
"apiVersion": "v1", "apiVersion": "v1",
"kind": "Service", "kind": "Service",

View File

@@ -18,6 +18,7 @@ package transformers
import ( import (
"fmt" "fmt"
"sigs.k8s.io/kustomize/pkg/resource"
"sigs.k8s.io/kustomize/pkg/resmap" "sigs.k8s.io/kustomize/pkg/resmap"
) )
@@ -26,6 +27,7 @@ import (
type multiTransformer struct { type multiTransformer struct {
transformers []Transformer transformers []Transformer
checkConflictEnabled bool checkConflictEnabled bool
rf *resource.Factory
} }
var _ Transformer = &multiTransformer{} var _ Transformer = &multiTransformer{}
@@ -69,7 +71,7 @@ func (o *multiTransformer) transform(m resmap.ResMap) error {
// A spot check to perform when the transformations are supposed to be commutative. // A spot check to perform when the transformations are supposed to be commutative.
// Fail if there's a difference in the result. // Fail if there's a difference in the result.
func (o *multiTransformer) transformWithCheckConflict(m resmap.ResMap) error { func (o *multiTransformer) transformWithCheckConflict(m resmap.ResMap) error {
mcopy := m.DeepCopy() mcopy := m.DeepCopy(o.rf)
err := o.transform(m) err := o.transform(m)
if err != nil { if err != nil {
return err return err

View File

@@ -28,8 +28,10 @@ import (
) )
func TestNameHashTransformer(t *testing.T) { func TestNameHashTransformer(t *testing.T) {
rf := resource.NewFactory(
k8sdeps.NewKustKunstructuredFactory(k8sdeps.NewKustDecoder()))
objs := resmap.ResMap{ objs := resmap.ResMap{
resid.NewResId(cmap, "cm1"): resource.NewFromMap( resid.NewResId(cmap, "cm1"): rf.FromMap(
map[string]interface{}{ map[string]interface{}{
"apiVersion": "v1", "apiVersion": "v1",
"kind": "ConfigMap", "kind": "ConfigMap",
@@ -37,7 +39,7 @@ func TestNameHashTransformer(t *testing.T) {
"name": "cm1", "name": "cm1",
}, },
}), }),
resid.NewResId(deploy, "deploy1"): resource.NewFromMap( resid.NewResId(deploy, "deploy1"): rf.FromMap(
map[string]interface{}{ map[string]interface{}{
"group": "apps", "group": "apps",
"apiVersion": "v1", "apiVersion": "v1",
@@ -63,7 +65,7 @@ func TestNameHashTransformer(t *testing.T) {
}, },
}, },
}), }),
resid.NewResId(service, "svc1"): resource.NewFromMap( resid.NewResId(service, "svc1"): rf.FromMap(
map[string]interface{}{ map[string]interface{}{
"apiVersion": "v1", "apiVersion": "v1",
"kind": "Service", "kind": "Service",
@@ -79,7 +81,7 @@ func TestNameHashTransformer(t *testing.T) {
}, },
}, },
}), }),
resid.NewResId(secret, "secret1"): resource.NewFromMap( resid.NewResId(secret, "secret1"): rf.FromMap(
map[string]interface{}{ map[string]interface{}{
"apiVersion": "v1", "apiVersion": "v1",
"kind": "Secret", "kind": "Secret",
@@ -90,7 +92,7 @@ func TestNameHashTransformer(t *testing.T) {
} }
expected := resmap.ResMap{ expected := resmap.ResMap{
resid.NewResId(cmap, "cm1"): resource.NewFromMap( resid.NewResId(cmap, "cm1"): rf.FromMap(
map[string]interface{}{ map[string]interface{}{
"apiVersion": "v1", "apiVersion": "v1",
"kind": "ConfigMap", "kind": "ConfigMap",
@@ -98,7 +100,7 @@ func TestNameHashTransformer(t *testing.T) {
"name": "cm1", "name": "cm1",
}, },
}), }),
resid.NewResId(deploy, "deploy1"): resource.NewFromMap( resid.NewResId(deploy, "deploy1"): rf.FromMap(
map[string]interface{}{ map[string]interface{}{
"group": "apps", "group": "apps",
"apiVersion": "v1", "apiVersion": "v1",
@@ -124,7 +126,7 @@ func TestNameHashTransformer(t *testing.T) {
}, },
}, },
}), }),
resid.NewResId(service, "svc1"): resource.NewFromMap( resid.NewResId(service, "svc1"): rf.FromMap(
map[string]interface{}{ map[string]interface{}{
"apiVersion": "v1", "apiVersion": "v1",
"kind": "Service", "kind": "Service",
@@ -140,7 +142,7 @@ func TestNameHashTransformer(t *testing.T) {
}, },
}, },
}), }),
resid.NewResId(secret, "secret1"): resource.NewFromMap( resid.NewResId(secret, "secret1"): rf.FromMap(
map[string]interface{}{ map[string]interface{}{
"apiVersion": "v1", "apiVersion": "v1",
"kind": "Secret", "kind": "Secret",

View File

@@ -20,6 +20,7 @@ import (
"reflect" "reflect"
"testing" "testing"
"sigs.k8s.io/kustomize/internal/k8sdeps"
"sigs.k8s.io/kustomize/pkg/resid" "sigs.k8s.io/kustomize/pkg/resid"
"sigs.k8s.io/kustomize/pkg/resmap" "sigs.k8s.io/kustomize/pkg/resmap"
"sigs.k8s.io/kustomize/pkg/resource" "sigs.k8s.io/kustomize/pkg/resource"
@@ -27,8 +28,10 @@ import (
) )
func TestNameReferenceRun(t *testing.T) { func TestNameReferenceRun(t *testing.T) {
rf := resource.NewFactory(
k8sdeps.NewKustKunstructuredFactory(k8sdeps.NewKustDecoder()))
m := resmap.ResMap{ m := resmap.ResMap{
resid.NewResId(cmap, "cm1"): resource.NewFromMap( resid.NewResId(cmap, "cm1"): rf.FromMap(
map[string]interface{}{ map[string]interface{}{
"apiVersion": "v1", "apiVersion": "v1",
"kind": "ConfigMap", "kind": "ConfigMap",
@@ -36,7 +39,7 @@ func TestNameReferenceRun(t *testing.T) {
"name": "someprefix-cm1-somehash", "name": "someprefix-cm1-somehash",
}, },
}), }),
resid.NewResId(cmap, "cm2"): resource.NewFromMap( resid.NewResId(cmap, "cm2"): rf.FromMap(
map[string]interface{}{ map[string]interface{}{
"apiVersion": "v1", "apiVersion": "v1",
"kind": "ConfigMap", "kind": "ConfigMap",
@@ -44,7 +47,7 @@ func TestNameReferenceRun(t *testing.T) {
"name": "someprefix-cm2-somehash", "name": "someprefix-cm2-somehash",
}, },
}), }),
resid.NewResId(secret, "secret1"): resource.NewFromMap( resid.NewResId(secret, "secret1"): rf.FromMap(
map[string]interface{}{ map[string]interface{}{
"apiVersion": "v1", "apiVersion": "v1",
"kind": "Secret", "kind": "Secret",
@@ -52,7 +55,7 @@ func TestNameReferenceRun(t *testing.T) {
"name": "someprefix-secret1-somehash", "name": "someprefix-secret1-somehash",
}, },
}), }),
resid.NewResId(pvc, "claim1"): resource.NewFromMap( resid.NewResId(pvc, "claim1"): rf.FromMap(
map[string]interface{}{ map[string]interface{}{
"apiVersion": "v1", "apiVersion": "v1",
"kind": "PersistentVolumeClaim", "kind": "PersistentVolumeClaim",
@@ -60,7 +63,7 @@ func TestNameReferenceRun(t *testing.T) {
"name": "someprefix-claim1", "name": "someprefix-claim1",
}, },
}), }),
resid.NewResId(ingress, "ingress1"): resource.NewFromMap( resid.NewResId(ingress, "ingress1"): rf.FromMap(
map[string]interface{}{ map[string]interface{}{
"group": "extensions", "group": "extensions",
"apiVersion": "v1beta1", "apiVersion": "v1beta1",
@@ -80,7 +83,7 @@ func TestNameReferenceRun(t *testing.T) {
}, },
}, },
), ),
resid.NewResId(deploy, "deploy1"): resource.NewFromMap( resid.NewResId(deploy, "deploy1"): rf.FromMap(
map[string]interface{}{ map[string]interface{}{
"group": "apps", "group": "apps",
"apiVersion": "v1", "apiVersion": "v1",
@@ -158,7 +161,7 @@ func TestNameReferenceRun(t *testing.T) {
}, },
}, },
}), }),
resid.NewResId(statefulset, "statefulset1"): resource.NewFromMap( resid.NewResId(statefulset, "statefulset1"): rf.FromMap(
map[string]interface{}{ map[string]interface{}{
"group": "apps", "group": "apps",
"apiVersion": "v1", "apiVersion": "v1",
@@ -195,7 +198,7 @@ func TestNameReferenceRun(t *testing.T) {
expected[k] = v expected[k] = v
} }
expected[resid.NewResId(deploy, "deploy1")] = resource.NewFromMap( expected[resid.NewResId(deploy, "deploy1")] = rf.FromMap(
map[string]interface{}{ map[string]interface{}{
"group": "apps", "group": "apps",
"apiVersion": "v1", "apiVersion": "v1",
@@ -273,7 +276,7 @@ func TestNameReferenceRun(t *testing.T) {
}, },
}, },
}) })
expected[resid.NewResId(statefulset, "statefulset1")] = resource.NewFromMap( expected[resid.NewResId(statefulset, "statefulset1")] = rf.FromMap(
map[string]interface{}{ map[string]interface{}{
"group": "apps", "group": "apps",
"apiVersion": "v1", "apiVersion": "v1",
@@ -303,7 +306,7 @@ func TestNameReferenceRun(t *testing.T) {
}, },
}, },
}) })
expected[resid.NewResId(ingress, "ingress1")] = resource.NewFromMap( expected[resid.NewResId(ingress, "ingress1")] = rf.FromMap(
map[string]interface{}{ map[string]interface{}{
"group": "extensions", "group": "extensions",
"apiVersion": "v1beta1", "apiVersion": "v1beta1",

View File

@@ -20,6 +20,7 @@ import (
"reflect" "reflect"
"testing" "testing"
"sigs.k8s.io/kustomize/internal/k8sdeps"
"sigs.k8s.io/kustomize/pkg/resid" "sigs.k8s.io/kustomize/pkg/resid"
"sigs.k8s.io/kustomize/pkg/resmap" "sigs.k8s.io/kustomize/pkg/resmap"
"sigs.k8s.io/kustomize/pkg/resource" "sigs.k8s.io/kustomize/pkg/resource"
@@ -27,8 +28,10 @@ import (
) )
func TestNamespaceRun(t *testing.T) { func TestNamespaceRun(t *testing.T) {
rf := resource.NewFactory(
k8sdeps.NewKustKunstructuredFactory(k8sdeps.NewKustDecoder()))
m := resmap.ResMap{ m := resmap.ResMap{
resid.NewResId(cmap, "cm1"): resource.NewFromMap( resid.NewResId(cmap, "cm1"): rf.FromMap(
map[string]interface{}{ map[string]interface{}{
"apiVersion": "v1", "apiVersion": "v1",
"kind": "ConfigMap", "kind": "ConfigMap",
@@ -36,7 +39,7 @@ func TestNamespaceRun(t *testing.T) {
"name": "cm1", "name": "cm1",
}, },
}), }),
resid.NewResId(cmap, "cm2"): resource.NewFromMap( resid.NewResId(cmap, "cm2"): rf.FromMap(
map[string]interface{}{ map[string]interface{}{
"apiVersion": "v1", "apiVersion": "v1",
"kind": "ConfigMap", "kind": "ConfigMap",
@@ -45,7 +48,7 @@ func TestNamespaceRun(t *testing.T) {
"namespace": "foo", "namespace": "foo",
}, },
}), }),
resid.NewResId(ns, "ns1"): resource.NewFromMap( resid.NewResId(ns, "ns1"): rf.FromMap(
map[string]interface{}{ map[string]interface{}{
"apiVersion": "v1", "apiVersion": "v1",
"kind": "Namespace", "kind": "Namespace",
@@ -53,7 +56,7 @@ func TestNamespaceRun(t *testing.T) {
"name": "ns1", "name": "ns1",
}, },
}), }),
resid.NewResId(sa, "default"): resource.NewFromMap( resid.NewResId(sa, "default"): rf.FromMap(
map[string]interface{}{ map[string]interface{}{
"apiVersion": "v1", "apiVersion": "v1",
"kind": "ServiceAccount", "kind": "ServiceAccount",
@@ -62,7 +65,7 @@ func TestNamespaceRun(t *testing.T) {
"namespace": "system", "namespace": "system",
}, },
}), }),
resid.NewResId(sa, "service-account"): resource.NewFromMap( resid.NewResId(sa, "service-account"): rf.FromMap(
map[string]interface{}{ map[string]interface{}{
"apiVersion": "v1", "apiVersion": "v1",
"kind": "ServiceAccount", "kind": "ServiceAccount",
@@ -71,7 +74,7 @@ func TestNamespaceRun(t *testing.T) {
"namespace": "system", "namespace": "system",
}, },
}), }),
resid.NewResId(crb, "crb"): resource.NewFromMap( resid.NewResId(crb, "crb"): rf.FromMap(
map[string]interface{}{ map[string]interface{}{
"apiVersion": "rbac.authorization.k8s.io/v1", "apiVersion": "rbac.authorization.k8s.io/v1",
"kind": "ClusterRoleBinding", "kind": "ClusterRoleBinding",
@@ -96,7 +99,7 @@ func TestNamespaceRun(t *testing.T) {
}, },
}, },
}), }),
resid.NewResId(crd, "crd"): resource.NewFromMap( resid.NewResId(crd, "crd"): rf.FromMap(
map[string]interface{}{ map[string]interface{}{
"apiVersion": "apiextensions.k8s.io/v1beta1", "apiVersion": "apiextensions.k8s.io/v1beta1",
"kind": "CustomResourceDefinition", "kind": "CustomResourceDefinition",
@@ -106,7 +109,7 @@ func TestNamespaceRun(t *testing.T) {
}), }),
} }
expected := resmap.ResMap{ expected := resmap.ResMap{
resid.NewResIdWithPrefixNamespace(ns, "ns1", "", ""): resource.NewFromMap( resid.NewResIdWithPrefixNamespace(ns, "ns1", "", ""): rf.FromMap(
map[string]interface{}{ map[string]interface{}{
"apiVersion": "v1", "apiVersion": "v1",
"kind": "Namespace", "kind": "Namespace",
@@ -114,7 +117,7 @@ func TestNamespaceRun(t *testing.T) {
"name": "ns1", "name": "ns1",
}, },
}), }),
resid.NewResIdWithPrefixNamespace(cmap, "cm1", "", "test"): resource.NewFromMap( resid.NewResIdWithPrefixNamespace(cmap, "cm1", "", "test"): rf.FromMap(
map[string]interface{}{ map[string]interface{}{
"apiVersion": "v1", "apiVersion": "v1",
"kind": "ConfigMap", "kind": "ConfigMap",
@@ -123,7 +126,7 @@ func TestNamespaceRun(t *testing.T) {
"namespace": "test", "namespace": "test",
}, },
}), }),
resid.NewResIdWithPrefixNamespace(cmap, "cm2", "", "test"): resource.NewFromMap( resid.NewResIdWithPrefixNamespace(cmap, "cm2", "", "test"): rf.FromMap(
map[string]interface{}{ map[string]interface{}{
"apiVersion": "v1", "apiVersion": "v1",
"kind": "ConfigMap", "kind": "ConfigMap",
@@ -132,7 +135,7 @@ func TestNamespaceRun(t *testing.T) {
"namespace": "test", "namespace": "test",
}, },
}), }),
resid.NewResIdWithPrefixNamespace(sa, "default", "", "test"): resource.NewFromMap( resid.NewResIdWithPrefixNamespace(sa, "default", "", "test"): rf.FromMap(
map[string]interface{}{ map[string]interface{}{
"apiVersion": "v1", "apiVersion": "v1",
"kind": "ServiceAccount", "kind": "ServiceAccount",
@@ -141,7 +144,7 @@ func TestNamespaceRun(t *testing.T) {
"namespace": "test", "namespace": "test",
}, },
}), }),
resid.NewResIdWithPrefixNamespace(sa, "service-account", "", "test"): resource.NewFromMap( resid.NewResIdWithPrefixNamespace(sa, "service-account", "", "test"): rf.FromMap(
map[string]interface{}{ map[string]interface{}{
"apiVersion": "v1", "apiVersion": "v1",
"kind": "ServiceAccount", "kind": "ServiceAccount",
@@ -150,7 +153,7 @@ func TestNamespaceRun(t *testing.T) {
"namespace": "test", "namespace": "test",
}, },
}), }),
resid.NewResId(crb, "crb"): resource.NewFromMap( resid.NewResId(crb, "crb"): rf.FromMap(
map[string]interface{}{ map[string]interface{}{
"apiVersion": "rbac.authorization.k8s.io/v1", "apiVersion": "rbac.authorization.k8s.io/v1",
"kind": "ClusterRoleBinding", "kind": "ClusterRoleBinding",
@@ -175,7 +178,7 @@ func TestNamespaceRun(t *testing.T) {
}, },
}, },
}), }),
resid.NewResId(crd, "crd"): resource.NewFromMap( resid.NewResId(crd, "crd"): rf.FromMap(
map[string]interface{}{ map[string]interface{}{
"apiVersion": "apiextensions.k8s.io/v1beta1", "apiVersion": "apiextensions.k8s.io/v1beta1",
"kind": "CustomResourceDefinition", "kind": "CustomResourceDefinition",

View File

@@ -31,16 +31,18 @@ import (
// patchTransformer applies patches. // patchTransformer applies patches.
type patchTransformer struct { type patchTransformer struct {
patches []*resource.Resource patches []*resource.Resource
rf *resource.Factory
} }
var _ Transformer = &patchTransformer{} var _ Transformer = &patchTransformer{}
// NewPatchTransformer constructs a patchTransformer. // NewPatchTransformer constructs a patchTransformer.
func NewPatchTransformer(slice []*resource.Resource) (Transformer, error) { func NewPatchTransformer(
slice []*resource.Resource, rf *resource.Factory) (Transformer, error) {
if len(slice) == 0 { if len(slice) == 0 {
return NewNoOpTransformer(), nil return NewNoOpTransformer(), nil
} }
return &patchTransformer{slice}, nil return &patchTransformer{patches: slice, rf: rf}, nil
} }
// Transform apply the patches on top of the base resources. // Transform apply the patches on top of the base resources.
@@ -129,9 +131,9 @@ func (pt *patchTransformer) mergePatches() (resmap.ResMap, error) {
} }
var cd conflictDetector var cd conflictDetector
if err != nil { if err != nil {
cd = newJMPConflictDetector() cd = newJMPConflictDetector(pt.rf)
} else { } else {
cd, err = newSMPConflictDetector(versionedObj) cd, err = newSMPConflictDetector(versionedObj, pt.rf)
if err != nil { if err != nil {
return nil, err return nil, err
} }

View File

@@ -21,14 +21,17 @@ import (
"strings" "strings"
"testing" "testing"
"sigs.k8s.io/kustomize/internal/k8sdeps"
"sigs.k8s.io/kustomize/pkg/resid" "sigs.k8s.io/kustomize/pkg/resid"
"sigs.k8s.io/kustomize/pkg/resmap" "sigs.k8s.io/kustomize/pkg/resmap"
"sigs.k8s.io/kustomize/pkg/resource" "sigs.k8s.io/kustomize/pkg/resource"
) )
func TestOverlayRun(t *testing.T) { func TestOverlayRun(t *testing.T) {
rf := resource.NewFactory(
k8sdeps.NewKustKunstructuredFactory(k8sdeps.NewKustDecoder()))
base := resmap.ResMap{ base := resmap.ResMap{
resid.NewResId(deploy, "deploy1"): resource.NewFromMap( resid.NewResId(deploy, "deploy1"): rf.FromMap(
map[string]interface{}{ map[string]interface{}{
"apiVersion": "apps/v1", "apiVersion": "apps/v1",
"kind": "Deployment", "kind": "Deployment",
@@ -55,7 +58,7 @@ func TestOverlayRun(t *testing.T) {
}), }),
} }
patch := []*resource.Resource{ patch := []*resource.Resource{
resource.NewFromMap(map[string]interface{}{ rf.FromMap(map[string]interface{}{
"apiVersion": "apps/v1", "apiVersion": "apps/v1",
"kind": "Deployment", "kind": "Deployment",
"metadata": map[string]interface{}{ "metadata": map[string]interface{}{
@@ -88,7 +91,7 @@ func TestOverlayRun(t *testing.T) {
), ),
} }
expected := resmap.ResMap{ expected := resmap.ResMap{
resid.NewResId(deploy, "deploy1"): resource.NewFromMap( resid.NewResId(deploy, "deploy1"): rf.FromMap(
map[string]interface{}{ map[string]interface{}{
"apiVersion": "apps/v1", "apiVersion": "apps/v1",
"kind": "Deployment", "kind": "Deployment",
@@ -121,7 +124,7 @@ func TestOverlayRun(t *testing.T) {
}, },
}), }),
} }
lt, err := NewPatchTransformer(patch) lt, err := NewPatchTransformer(patch, rf)
if err != nil { if err != nil {
t.Fatalf("unexpected error: %v", err) t.Fatalf("unexpected error: %v", err)
} }
@@ -137,7 +140,7 @@ func TestOverlayRun(t *testing.T) {
func TestMultiplePatches(t *testing.T) { func TestMultiplePatches(t *testing.T) {
base := resmap.ResMap{ base := resmap.ResMap{
resid.NewResId(deploy, "deploy1"): resource.NewFromMap( resid.NewResId(deploy, "deploy1"): rf.FromMap(
map[string]interface{}{ map[string]interface{}{
"apiVersion": "apps/v1", "apiVersion": "apps/v1",
"kind": "Deployment", "kind": "Deployment",
@@ -159,7 +162,7 @@ func TestMultiplePatches(t *testing.T) {
}), }),
} }
patch := []*resource.Resource{ patch := []*resource.Resource{
resource.NewFromMap(map[string]interface{}{ rf.FromMap(map[string]interface{}{
"apiVersion": "apps/v1", "apiVersion": "apps/v1",
"kind": "Deployment", "kind": "Deployment",
"metadata": map[string]interface{}{ "metadata": map[string]interface{}{
@@ -185,7 +188,7 @@ func TestMultiplePatches(t *testing.T) {
}, },
}, },
), ),
resource.NewFromMap(map[string]interface{}{ rf.FromMap(map[string]interface{}{
"apiVersion": "apps/v1", "apiVersion": "apps/v1",
"kind": "Deployment", "kind": "Deployment",
"metadata": map[string]interface{}{ "metadata": map[string]interface{}{
@@ -216,7 +219,7 @@ func TestMultiplePatches(t *testing.T) {
), ),
} }
expected := resmap.ResMap{ expected := resmap.ResMap{
resid.NewResId(deploy, "deploy1"): resource.NewFromMap( resid.NewResId(deploy, "deploy1"): rf.FromMap(
map[string]interface{}{ map[string]interface{}{
"apiVersion": "apps/v1", "apiVersion": "apps/v1",
"kind": "Deployment", "kind": "Deployment",
@@ -251,7 +254,7 @@ func TestMultiplePatches(t *testing.T) {
}, },
}), }),
} }
lt, err := NewPatchTransformer(patch) lt, err := NewPatchTransformer(patch, rf)
if err != nil { if err != nil {
t.Fatalf("unexpected error: %v", err) t.Fatalf("unexpected error: %v", err)
} }
@@ -267,7 +270,7 @@ func TestMultiplePatches(t *testing.T) {
func TestMultiplePatchesWithConflict(t *testing.T) { func TestMultiplePatchesWithConflict(t *testing.T) {
base := resmap.ResMap{ base := resmap.ResMap{
resid.NewResId(deploy, "deploy1"): resource.NewFromMap( resid.NewResId(deploy, "deploy1"): rf.FromMap(
map[string]interface{}{ map[string]interface{}{
"apiVersion": "apps/v1", "apiVersion": "apps/v1",
"kind": "Deployment", "kind": "Deployment",
@@ -289,7 +292,7 @@ func TestMultiplePatchesWithConflict(t *testing.T) {
}), }),
} }
patch := []*resource.Resource{ patch := []*resource.Resource{
resource.NewFromMap(map[string]interface{}{ rf.FromMap(map[string]interface{}{
"apiVersion": "apps/v1", "apiVersion": "apps/v1",
"kind": "Deployment", "kind": "Deployment",
"metadata": map[string]interface{}{ "metadata": map[string]interface{}{
@@ -315,7 +318,7 @@ func TestMultiplePatchesWithConflict(t *testing.T) {
}, },
}, },
), ),
resource.NewFromMap(map[string]interface{}{ rf.FromMap(map[string]interface{}{
"apiVersion": "apps/v1", "apiVersion": "apps/v1",
"kind": "Deployment", "kind": "Deployment",
"metadata": map[string]interface{}{ "metadata": map[string]interface{}{
@@ -337,7 +340,7 @@ func TestMultiplePatchesWithConflict(t *testing.T) {
), ),
} }
lt, err := NewPatchTransformer(patch) lt, err := NewPatchTransformer(patch, rf)
if err != nil { if err != nil {
t.Fatalf("unexpected error: %v", err) t.Fatalf("unexpected error: %v", err)
} }
@@ -352,7 +355,7 @@ func TestMultiplePatchesWithConflict(t *testing.T) {
func TestNoSchemaOverlayRun(t *testing.T) { func TestNoSchemaOverlayRun(t *testing.T) {
base := resmap.ResMap{ base := resmap.ResMap{
resid.NewResId(foo, "my-foo"): resource.NewFromMap( resid.NewResId(foo, "my-foo"): rf.FromMap(
map[string]interface{}{ map[string]interface{}{
"apiVersion": "example.com/v1", "apiVersion": "example.com/v1",
"kind": "Foo", "kind": "Foo",
@@ -368,7 +371,7 @@ func TestNoSchemaOverlayRun(t *testing.T) {
}), }),
} }
patch := []*resource.Resource{ patch := []*resource.Resource{
resource.NewFromMap(map[string]interface{}{ rf.FromMap(map[string]interface{}{
"apiVersion": "example.com/v1", "apiVersion": "example.com/v1",
"kind": "Foo", "kind": "Foo",
"metadata": map[string]interface{}{ "metadata": map[string]interface{}{
@@ -384,7 +387,7 @@ func TestNoSchemaOverlayRun(t *testing.T) {
), ),
} }
expected := resmap.ResMap{ expected := resmap.ResMap{
resid.NewResId(foo, "my-foo"): resource.NewFromMap( resid.NewResId(foo, "my-foo"): rf.FromMap(
map[string]interface{}{ map[string]interface{}{
"apiVersion": "example.com/v1", "apiVersion": "example.com/v1",
"kind": "Foo", "kind": "Foo",
@@ -400,7 +403,7 @@ func TestNoSchemaOverlayRun(t *testing.T) {
}), }),
} }
lt, err := NewPatchTransformer(patch) lt, err := NewPatchTransformer(patch, rf)
if err != nil { if err != nil {
t.Fatalf("unexpected error: %v", err) t.Fatalf("unexpected error: %v", err)
} }
@@ -415,7 +418,7 @@ func TestNoSchemaOverlayRun(t *testing.T) {
func TestNoSchemaMultiplePatches(t *testing.T) { func TestNoSchemaMultiplePatches(t *testing.T) {
base := resmap.ResMap{ base := resmap.ResMap{
resid.NewResId(foo, "my-foo"): resource.NewFromMap( resid.NewResId(foo, "my-foo"): rf.FromMap(
map[string]interface{}{ map[string]interface{}{
"apiVersion": "example.com/v1", "apiVersion": "example.com/v1",
"kind": "Foo", "kind": "Foo",
@@ -431,7 +434,7 @@ func TestNoSchemaMultiplePatches(t *testing.T) {
}), }),
} }
patch := []*resource.Resource{ patch := []*resource.Resource{
resource.NewFromMap(map[string]interface{}{ rf.FromMap(map[string]interface{}{
"apiVersion": "example.com/v1", "apiVersion": "example.com/v1",
"kind": "Foo", "kind": "Foo",
"metadata": map[string]interface{}{ "metadata": map[string]interface{}{
@@ -445,7 +448,7 @@ func TestNoSchemaMultiplePatches(t *testing.T) {
}, },
}, },
), ),
resource.NewFromMap(map[string]interface{}{ rf.FromMap(map[string]interface{}{
"apiVersion": "example.com/v1", "apiVersion": "example.com/v1",
"kind": "Foo", "kind": "Foo",
"metadata": map[string]interface{}{ "metadata": map[string]interface{}{
@@ -464,7 +467,7 @@ func TestNoSchemaMultiplePatches(t *testing.T) {
), ),
} }
expected := resmap.ResMap{ expected := resmap.ResMap{
resid.NewResId(foo, "my-foo"): resource.NewFromMap( resid.NewResId(foo, "my-foo"): rf.FromMap(
map[string]interface{}{ map[string]interface{}{
"apiVersion": "example.com/v1", "apiVersion": "example.com/v1",
"kind": "Foo", "kind": "Foo",
@@ -484,7 +487,7 @@ func TestNoSchemaMultiplePatches(t *testing.T) {
}), }),
} }
lt, err := NewPatchTransformer(patch) lt, err := NewPatchTransformer(patch, rf)
if err != nil { if err != nil {
t.Fatalf("unexpected error: %v", err) t.Fatalf("unexpected error: %v", err)
} }
@@ -499,7 +502,7 @@ func TestNoSchemaMultiplePatches(t *testing.T) {
func TestNoSchemaMultiplePatchesWithConflict(t *testing.T) { func TestNoSchemaMultiplePatchesWithConflict(t *testing.T) {
base := resmap.ResMap{ base := resmap.ResMap{
resid.NewResId(foo, "my-foo"): resource.NewFromMap( resid.NewResId(foo, "my-foo"): rf.FromMap(
map[string]interface{}{ map[string]interface{}{
"apiVersion": "example.com/v1", "apiVersion": "example.com/v1",
"kind": "Foo", "kind": "Foo",
@@ -515,7 +518,7 @@ func TestNoSchemaMultiplePatchesWithConflict(t *testing.T) {
}), }),
} }
patch := []*resource.Resource{ patch := []*resource.Resource{
resource.NewFromMap(map[string]interface{}{ rf.FromMap(map[string]interface{}{
"apiVersion": "example.com/v1", "apiVersion": "example.com/v1",
"kind": "Foo", "kind": "Foo",
"metadata": map[string]interface{}{ "metadata": map[string]interface{}{
@@ -528,7 +531,7 @@ func TestNoSchemaMultiplePatchesWithConflict(t *testing.T) {
}, },
}, },
}), }),
resource.NewFromMap(map[string]interface{}{ rf.FromMap(map[string]interface{}{
"apiVersion": "example.com/v1", "apiVersion": "example.com/v1",
"kind": "Foo", "kind": "Foo",
"metadata": map[string]interface{}{ "metadata": map[string]interface{}{
@@ -542,7 +545,7 @@ func TestNoSchemaMultiplePatchesWithConflict(t *testing.T) {
}), }),
} }
lt, err := NewPatchTransformer(patch) lt, err := NewPatchTransformer(patch, rf)
if err != nil { if err != nil {
t.Fatalf("unexpected error: %v", err) t.Fatalf("unexpected error: %v", err)
} }

View File

@@ -18,6 +18,7 @@ package transformers
import ( import (
"encoding/json" "encoding/json"
"github.com/evanphx/json-patch" "github.com/evanphx/json-patch"
"k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/util/mergepatch" "k8s.io/apimachinery/pkg/util/mergepatch"
@@ -31,12 +32,14 @@ type conflictDetector interface {
mergePatches(patch1, patch2 *resource.Resource) (*resource.Resource, error) mergePatches(patch1, patch2 *resource.Resource) (*resource.Resource, error)
} }
type jsonMergePatch struct{} type jsonMergePatch struct {
rf *resource.Factory
}
var _ conflictDetector = &jsonMergePatch{} var _ conflictDetector = &jsonMergePatch{}
func newJMPConflictDetector() conflictDetector { func newJMPConflictDetector(rf *resource.Factory) conflictDetector {
return &jsonMergePatch{} return &jsonMergePatch{rf: rf}
} }
func (jmp *jsonMergePatch) hasConflict( func (jmp *jsonMergePatch) hasConflict(
@@ -82,18 +85,21 @@ func (jmp *jsonMergePatch) mergePatches(
} }
mergedMap := make(map[string]interface{}) mergedMap := make(map[string]interface{})
err = json.Unmarshal(mergedBytes, &mergedMap) err = json.Unmarshal(mergedBytes, &mergedMap)
return resource.NewFromMap(mergedMap), err return jmp.rf.FromMap(mergedMap), err
} }
type strategicMergePatch struct { type strategicMergePatch struct {
lookupPatchMeta strategicpatch.LookupPatchMeta lookupPatchMeta strategicpatch.LookupPatchMeta
rf *resource.Factory
} }
var _ conflictDetector = &strategicMergePatch{} var _ conflictDetector = &strategicMergePatch{}
func newSMPConflictDetector(versionedObj runtime.Object) (conflictDetector, error) { func newSMPConflictDetector(
versionedObj runtime.Object,
rf *resource.Factory) (conflictDetector, error) {
lookupPatchMeta, err := strategicpatch.NewPatchMetaFromStruct(versionedObj) lookupPatchMeta, err := strategicpatch.NewPatchMetaFromStruct(versionedObj)
return &strategicMergePatch{lookupPatchMeta: lookupPatchMeta}, err return &strategicMergePatch{lookupPatchMeta: lookupPatchMeta, rf: rf}, err
} }
func (smp *strategicMergePatch) hasConflict(p1, p2 *resource.Resource) (bool, error) { func (smp *strategicMergePatch) hasConflict(p1, p2 *resource.Resource) (bool, error) {
@@ -127,5 +133,5 @@ func (smp *strategicMergePatch) findConflict(
func (smp *strategicMergePatch) mergePatches(patch1, patch2 *resource.Resource) (*resource.Resource, error) { func (smp *strategicMergePatch) mergePatches(patch1, patch2 *resource.Resource) (*resource.Resource, error) {
mergeJsonMap, err := strategicpatch.MergeStrategicMergeMapPatchUsingLookupPatchMeta( mergeJsonMap, err := strategicpatch.MergeStrategicMergeMapPatchUsingLookupPatchMeta(
smp.lookupPatchMeta, patch1.Map(), patch2.Map()) smp.lookupPatchMeta, patch1.Map(), patch2.Map())
return resource.NewFromMap(mergeJsonMap), err return smp.rf.FromMap(mergeJsonMap), err
} }

View File

@@ -20,6 +20,7 @@ import (
"reflect" "reflect"
"testing" "testing"
"sigs.k8s.io/kustomize/internal/k8sdeps"
"sigs.k8s.io/kustomize/pkg/resid" "sigs.k8s.io/kustomize/pkg/resid"
"sigs.k8s.io/kustomize/pkg/resmap" "sigs.k8s.io/kustomize/pkg/resmap"
"sigs.k8s.io/kustomize/pkg/resource" "sigs.k8s.io/kustomize/pkg/resource"
@@ -27,8 +28,10 @@ import (
) )
func TestPrefixNameRun(t *testing.T) { func TestPrefixNameRun(t *testing.T) {
rf := resource.NewFactory(
k8sdeps.NewKustKunstructuredFactory(k8sdeps.NewKustDecoder()))
m := resmap.ResMap{ m := resmap.ResMap{
resid.NewResId(cmap, "cm1"): resource.NewFromMap( resid.NewResId(cmap, "cm1"): rf.FromMap(
map[string]interface{}{ map[string]interface{}{
"apiVersion": "v1", "apiVersion": "v1",
"kind": "ConfigMap", "kind": "ConfigMap",
@@ -36,7 +39,7 @@ func TestPrefixNameRun(t *testing.T) {
"name": "cm1", "name": "cm1",
}, },
}), }),
resid.NewResId(cmap, "cm2"): resource.NewFromMap( resid.NewResId(cmap, "cm2"): rf.FromMap(
map[string]interface{}{ map[string]interface{}{
"apiVersion": "v1", "apiVersion": "v1",
"kind": "ConfigMap", "kind": "ConfigMap",
@@ -44,7 +47,7 @@ func TestPrefixNameRun(t *testing.T) {
"name": "cm2", "name": "cm2",
}, },
}), }),
resid.NewResId(crd, "crd"): resource.NewFromMap( resid.NewResId(crd, "crd"): rf.FromMap(
map[string]interface{}{ map[string]interface{}{
"apiVersion": "apiextensions.k8s.io/v1beta1", "apiVersion": "apiextensions.k8s.io/v1beta1",
"kind": "CustomResourceDefinition", "kind": "CustomResourceDefinition",
@@ -54,7 +57,7 @@ func TestPrefixNameRun(t *testing.T) {
}), }),
} }
expected := resmap.ResMap{ expected := resmap.ResMap{
resid.NewResIdWithPrefix(cmap, "cm1", "someprefix-"): resource.NewFromMap( resid.NewResIdWithPrefix(cmap, "cm1", "someprefix-"): rf.FromMap(
map[string]interface{}{ map[string]interface{}{
"apiVersion": "v1", "apiVersion": "v1",
"kind": "ConfigMap", "kind": "ConfigMap",
@@ -62,7 +65,7 @@ func TestPrefixNameRun(t *testing.T) {
"name": "someprefix-cm1", "name": "someprefix-cm1",
}, },
}), }),
resid.NewResIdWithPrefix(cmap, "cm2", "someprefix-"): resource.NewFromMap( resid.NewResIdWithPrefix(cmap, "cm2", "someprefix-"): rf.FromMap(
map[string]interface{}{ map[string]interface{}{
"apiVersion": "v1", "apiVersion": "v1",
"kind": "ConfigMap", "kind": "ConfigMap",
@@ -70,7 +73,7 @@ func TestPrefixNameRun(t *testing.T) {
"name": "someprefix-cm2", "name": "someprefix-cm2",
}, },
}), }),
resid.NewResId(crd, "crd"): resource.NewFromMap( resid.NewResId(crd, "crd"): rf.FromMap(
map[string]interface{}{ map[string]interface{}{
"apiVersion": "apiextensions.k8s.io/v1beta1", "apiVersion": "apiextensions.k8s.io/v1beta1",
"kind": "CustomResourceDefinition", "kind": "CustomResourceDefinition",