Merge pull request #432 from monopole/mergeResmapFactoryCode

Gather resmap factory code into one file.
This commit is contained in:
k8s-ci-robot
2018-10-08 15:17:46 -07:00
committed by GitHub
6 changed files with 258 additions and 359 deletions

View File

@@ -1,48 +0,0 @@
/*
Copyright 2018 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package resmap
import (
"sigs.k8s.io/kustomize/pkg/configmapandsecret"
"sigs.k8s.io/kustomize/pkg/ifc"
"sigs.k8s.io/kustomize/pkg/resource"
"sigs.k8s.io/kustomize/pkg/types"
)
// NewResMapFromConfigMapArgs returns a Resource slice given
// a configmap metadata slice from kustomization file.
func (rmF *Factory) NewResMapFromConfigMapArgs(
cf *configmapandsecret.ConfigMapFactory,
cmArgsList []types.ConfigMapArgs) (ResMap, error) {
var allResources []*resource.Resource
for _, cmArgs := range cmArgsList {
if cmArgs.Behavior == "" {
cmArgs.Behavior = "create"
}
cm, err := cf.MakeConfigMap(&cmArgs)
if err != nil {
return nil, err
}
res, err := rmF.resF.WithBehavior(
cm, ifc.NewGenerationBehavior(cmArgs.Behavior))
if err != nil {
return nil, err
}
allResources = append(allResources, res)
}
return newResMapFromResourceSlice(allResources)
}

View File

@@ -1,143 +0,0 @@
/*
Copyright 2018 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package resmap
import (
"reflect"
"testing"
"sigs.k8s.io/kustomize/pkg/configmapandsecret"
"sigs.k8s.io/kustomize/pkg/fs"
"sigs.k8s.io/kustomize/pkg/gvk"
"sigs.k8s.io/kustomize/pkg/ifc"
"sigs.k8s.io/kustomize/pkg/internal/loadertest"
"sigs.k8s.io/kustomize/pkg/resid"
"sigs.k8s.io/kustomize/pkg/types"
)
var cmap = gvk.Gvk{Version: "v1", Kind: "ConfigMap"}
func TestNewFromConfigMaps(t *testing.T) {
type testCase struct {
description string
input []types.ConfigMapArgs
filepath string
content string
expected ResMap
}
l := loadertest.NewFakeLoader("/home/seans/project/")
cf := configmapandsecret.NewConfigMapFactory(fs.MakeFakeFS(), l)
testCases := []testCase{
{
description: "construct config map from env",
input: []types.ConfigMapArgs{
{
Name: "envConfigMap",
DataSources: types.DataSources{
EnvSource: "app.env",
},
},
},
filepath: "/home/seans/project/app.env",
content: "DB_USERNAME=admin\nDB_PASSWORD=somepw",
expected: ResMap{
resid.NewResId(cmap, "envConfigMap"): rf.FromMap(
map[string]interface{}{
"apiVersion": "v1",
"kind": "ConfigMap",
"metadata": map[string]interface{}{
"name": "envConfigMap",
},
"data": map[string]interface{}{
"DB_USERNAME": "admin",
"DB_PASSWORD": "somepw",
},
}).SetBehavior(ifc.BehaviorCreate),
},
},
{
description: "construct config map from file",
input: []types.ConfigMapArgs{{
Name: "fileConfigMap",
DataSources: types.DataSources{
FileSources: []string{"app-init.ini"},
},
},
},
filepath: "/home/seans/project/app-init.ini",
content: "FOO=bar\nBAR=baz\n",
expected: ResMap{
resid.NewResId(cmap, "fileConfigMap"): rf.FromMap(
map[string]interface{}{
"apiVersion": "v1",
"kind": "ConfigMap",
"metadata": map[string]interface{}{
"name": "fileConfigMap",
},
"data": map[string]interface{}{
"app-init.ini": `FOO=bar
BAR=baz
`,
},
}).SetBehavior(ifc.BehaviorCreate),
},
},
{
description: "construct config map from literal",
input: []types.ConfigMapArgs{
{
Name: "literalConfigMap",
DataSources: types.DataSources{
LiteralSources: []string{"a=x", "b=y", "c=\"Good Morning\"", "d=\"false\""},
},
},
},
expected: ResMap{
resid.NewResId(cmap, "literalConfigMap"): rf.FromMap(
map[string]interface{}{
"apiVersion": "v1",
"kind": "ConfigMap",
"metadata": map[string]interface{}{
"name": "literalConfigMap",
},
"data": map[string]interface{}{
"a": "x",
"b": "y",
"c": "Good Morning",
"d": "false",
},
}).SetBehavior(ifc.BehaviorCreate),
},
},
// TODO: add testcase for data coming from multiple sources like
// files/literal/env etc.
}
for _, tc := range testCases {
if ferr := l.AddFile(tc.filepath, []byte(tc.content)); ferr != nil {
t.Fatalf("Error adding fake file: %v\n", ferr)
}
r, err := rmF.NewResMapFromConfigMapArgs(cf, tc.input)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
if !reflect.DeepEqual(r, tc.expected) {
t.Fatalf("in testcase: %q got:\n%+v\n expected:\n%+v\n", tc.description, r, tc.expected)
}
}
}

View File

@@ -20,9 +20,11 @@ import (
"fmt"
"github.com/pkg/errors"
"sigs.k8s.io/kustomize/pkg/configmapandsecret"
"sigs.k8s.io/kustomize/pkg/ifc"
internal "sigs.k8s.io/kustomize/pkg/internal/error"
"sigs.k8s.io/kustomize/pkg/resource"
"sigs.k8s.io/kustomize/pkg/types"
)
// Factory makes instances of ResMap.
@@ -76,6 +78,54 @@ func (rmF *Factory) newResMapFromBytes(b []byte) (ResMap, error) {
return result, nil
}
// NewResMapFromConfigMapArgs returns a Resource slice given
// a configmap metadata slice from kustomization file.
func (rmF *Factory) NewResMapFromConfigMapArgs(
cf *configmapandsecret.ConfigMapFactory,
argList []types.ConfigMapArgs) (ResMap, error) {
var resources []*resource.Resource
for _, args := range argList {
obj, err := cf.MakeConfigMap(&args)
if err != nil {
return nil, errors.Wrap(err, "NewResMapFromConfigMapArgs")
}
res, err := rmF.resF.WithBehavior(obj, fixBehavior(args.Behavior))
if err != nil {
return nil, err
}
resources = append(resources, res)
}
return newResMapFromResourceSlice(resources)
}
// NewResMapFromSecretArgs takes a SecretArgs slice, generates
// secrets from each entry, and accumulates them in a ResMap.
func (rmF *Factory) NewResMapFromSecretArgs(
sf *configmapandsecret.SecretFactory,
argsList []types.SecretArgs) (ResMap, error) {
var resources []*resource.Resource
for _, args := range argsList {
obj, err := sf.MakeSecret(&args)
if err != nil {
return nil, errors.Wrap(err, "NewResMapFromSecretArgs")
}
res, err := rmF.resF.WithBehavior(obj, fixBehavior(args.Behavior))
if err != nil {
return nil, errors.Wrap(err, "WithBehavior")
}
resources = append(resources, res)
}
return newResMapFromResourceSlice(resources)
}
func fixBehavior(s string) ifc.GenerationBehavior {
b := ifc.NewGenerationBehavior(s)
if b == ifc.BehaviorUnspecified {
return ifc.BehaviorCreate
}
return b
}
func newResMapFromResourceSlice(resources []*resource.Resource) (ResMap, error) {
result := ResMap{}
for _, res := range resources {

View File

@@ -17,12 +17,19 @@ limitations under the License.
package resmap
import (
"encoding/base64"
"fmt"
"reflect"
"testing"
"k8s.io/api/core/v1"
"sigs.k8s.io/kustomize/pkg/configmapandsecret"
"sigs.k8s.io/kustomize/pkg/fs"
"sigs.k8s.io/kustomize/pkg/gvk"
"sigs.k8s.io/kustomize/pkg/ifc"
"sigs.k8s.io/kustomize/pkg/internal/loadertest"
"sigs.k8s.io/kustomize/pkg/resid"
"sigs.k8s.io/kustomize/pkg/types"
)
func TestFromFiles(t *testing.T) {
@@ -113,3 +120,204 @@ metadata:
t.Fatalf("%#v doesn't match expected %#v", m, expected)
}
}
var cmap = gvk.Gvk{Version: "v1", Kind: "ConfigMap"}
func TestNewFromConfigMaps(t *testing.T) {
type testCase struct {
description string
input []types.ConfigMapArgs
filepath string
content string
expected ResMap
}
l := loadertest.NewFakeLoader("/home/seans/project/")
cf := configmapandsecret.NewConfigMapFactory(fs.MakeFakeFS(), l)
testCases := []testCase{
{
description: "construct config map from env",
input: []types.ConfigMapArgs{
{
Name: "envConfigMap",
DataSources: types.DataSources{
EnvSource: "app.env",
},
},
},
filepath: "/home/seans/project/app.env",
content: "DB_USERNAME=admin\nDB_PASSWORD=somepw",
expected: ResMap{
resid.NewResId(cmap, "envConfigMap"): rf.FromMap(
map[string]interface{}{
"apiVersion": "v1",
"kind": "ConfigMap",
"metadata": map[string]interface{}{
"name": "envConfigMap",
},
"data": map[string]interface{}{
"DB_USERNAME": "admin",
"DB_PASSWORD": "somepw",
},
}).SetBehavior(ifc.BehaviorCreate),
},
},
{
description: "construct config map from file",
input: []types.ConfigMapArgs{{
Name: "fileConfigMap",
DataSources: types.DataSources{
FileSources: []string{"app-init.ini"},
},
},
},
filepath: "/home/seans/project/app-init.ini",
content: "FOO=bar\nBAR=baz\n",
expected: ResMap{
resid.NewResId(cmap, "fileConfigMap"): rf.FromMap(
map[string]interface{}{
"apiVersion": "v1",
"kind": "ConfigMap",
"metadata": map[string]interface{}{
"name": "fileConfigMap",
},
"data": map[string]interface{}{
"app-init.ini": `FOO=bar
BAR=baz
`,
},
}).SetBehavior(ifc.BehaviorCreate),
},
},
{
description: "construct config map from literal",
input: []types.ConfigMapArgs{
{
Name: "literalConfigMap",
DataSources: types.DataSources{
LiteralSources: []string{"a=x", "b=y", "c=\"Good Morning\"", "d=\"false\""},
},
},
},
expected: ResMap{
resid.NewResId(cmap, "literalConfigMap"): rf.FromMap(
map[string]interface{}{
"apiVersion": "v1",
"kind": "ConfigMap",
"metadata": map[string]interface{}{
"name": "literalConfigMap",
},
"data": map[string]interface{}{
"a": "x",
"b": "y",
"c": "Good Morning",
"d": "false",
},
}).SetBehavior(ifc.BehaviorCreate),
},
},
// TODO: add testcase for data coming from multiple sources like
// files/literal/env etc.
}
for _, tc := range testCases {
if ferr := l.AddFile(tc.filepath, []byte(tc.content)); ferr != nil {
t.Fatalf("Error adding fake file: %v\n", ferr)
}
r, err := rmF.NewResMapFromConfigMapArgs(cf, tc.input)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
if !reflect.DeepEqual(r, tc.expected) {
t.Fatalf("in testcase: %q got:\n%+v\n expected:\n%+v\n", tc.description, r, tc.expected)
}
}
}
var secret = gvk.Gvk{Version: "v1", Kind: "Secret"}
func TestNewResMapFromSecretArgs(t *testing.T) {
secrets := []types.SecretArgs{
{
Name: "apple",
CommandSources: types.CommandSources{
Commands: map[string]string{
"DB_USERNAME": "printf admin",
"DB_PASSWORD": "printf somepw",
},
},
Type: "Opaque",
},
{
Name: "peanuts",
CommandSources: types.CommandSources{
EnvCommand: "printf \"DB_USERNAME=admin\nDB_PASSWORD=somepw\"",
},
Type: "Opaque",
},
}
fakeFs := fs.MakeFakeFS()
fakeFs.Mkdir(".")
actual, err := rmF.NewResMapFromSecretArgs(
configmapandsecret.NewSecretFactory(fakeFs, "."), secrets)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
expected := ResMap{
resid.NewResId(secret, "apple"): rf.FromMap(
map[string]interface{}{
"apiVersion": "v1",
"kind": "Secret",
"metadata": map[string]interface{}{
"name": "apple",
},
"type": string(v1.SecretTypeOpaque),
"data": map[string]interface{}{
"DB_USERNAME": base64.StdEncoding.EncodeToString([]byte("admin")),
"DB_PASSWORD": base64.StdEncoding.EncodeToString([]byte("somepw")),
},
}).SetBehavior(ifc.BehaviorCreate),
resid.NewResId(secret, "peanuts"): rf.FromMap(
map[string]interface{}{
"apiVersion": "v1",
"kind": "Secret",
"metadata": map[string]interface{}{
"name": "peanuts",
},
"type": string(v1.SecretTypeOpaque),
"data": map[string]interface{}{
"DB_USERNAME": base64.StdEncoding.EncodeToString([]byte("admin")),
"DB_PASSWORD": base64.StdEncoding.EncodeToString([]byte("somepw")),
},
}).SetBehavior(ifc.BehaviorCreate),
}
if !reflect.DeepEqual(actual, expected) {
t.Fatalf("%#v\ndoesn't match expected:\n%#v", actual, expected)
}
}
func TestSecretTimeout(t *testing.T) {
timeout := int64(1)
secrets := []types.SecretArgs{
{
Name: "slow",
TimeoutSeconds: &timeout,
CommandSources: types.CommandSources{
Commands: map[string]string{
"USER": "sleep 2",
},
},
Type: "Opaque",
},
}
fakeFs := fs.MakeFakeFS()
fakeFs.Mkdir(".")
_, err := rmF.NewResMapFromSecretArgs(
configmapandsecret.NewSecretFactory(fakeFs, "."), secrets)
if err == nil {
t.Fatal("didn't get the expected timeout error", err)
}
}

View File

@@ -1,49 +0,0 @@
/*
Copyright 2018 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package resmap
import (
"github.com/pkg/errors"
"sigs.k8s.io/kustomize/pkg/configmapandsecret"
"sigs.k8s.io/kustomize/pkg/ifc"
"sigs.k8s.io/kustomize/pkg/resource"
"sigs.k8s.io/kustomize/pkg/types"
)
// NewResMapFromSecretArgs takes a SecretArgs slice, generates
// secrets from each entry, and accumulates them in a ResMap.
func (rmF *Factory) NewResMapFromSecretArgs(
f *configmapandsecret.SecretFactory,
secretList []types.SecretArgs) (ResMap, error) {
var allResources []*resource.Resource
for _, args := range secretList {
s, err := f.MakeSecret(&args)
if err != nil {
return nil, errors.Wrap(err, "makeSecret")
}
if args.Behavior == "" {
args.Behavior = "create"
}
res, err := rmF.resF.WithBehavior(
s, ifc.NewGenerationBehavior(args.Behavior))
if err != nil {
return nil, errors.Wrap(err, "WithBehavior")
}
allResources = append(allResources, res)
}
return newResMapFromResourceSlice(allResources)
}

View File

@@ -1,119 +0,0 @@
/*
Copyright 2018 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package resmap
import (
"encoding/base64"
"reflect"
"testing"
corev1 "k8s.io/api/core/v1"
"sigs.k8s.io/kustomize/pkg/configmapandsecret"
"sigs.k8s.io/kustomize/pkg/fs"
"sigs.k8s.io/kustomize/pkg/gvk"
"sigs.k8s.io/kustomize/pkg/ifc"
"sigs.k8s.io/kustomize/pkg/resid"
"sigs.k8s.io/kustomize/pkg/types"
)
var secret = gvk.Gvk{Version: "v1", Kind: "Secret"}
func TestNewResMapFromSecretArgs(t *testing.T) {
secrets := []types.SecretArgs{
{
Name: "apple",
CommandSources: types.CommandSources{
Commands: map[string]string{
"DB_USERNAME": "printf admin",
"DB_PASSWORD": "printf somepw",
},
},
Type: "Opaque",
},
{
Name: "peanuts",
CommandSources: types.CommandSources{
EnvCommand: "printf \"DB_USERNAME=admin\nDB_PASSWORD=somepw\"",
},
Type: "Opaque",
},
}
fakeFs := fs.MakeFakeFS()
fakeFs.Mkdir(".")
actual, err := rmF.NewResMapFromSecretArgs(
configmapandsecret.NewSecretFactory(fakeFs, "."), secrets)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
expected := ResMap{
resid.NewResId(secret, "apple"): rf.FromMap(
map[string]interface{}{
"apiVersion": "v1",
"kind": "Secret",
"metadata": map[string]interface{}{
"name": "apple",
},
"type": string(corev1.SecretTypeOpaque),
"data": map[string]interface{}{
"DB_USERNAME": base64.StdEncoding.EncodeToString([]byte("admin")),
"DB_PASSWORD": base64.StdEncoding.EncodeToString([]byte("somepw")),
},
}).SetBehavior(ifc.BehaviorCreate),
resid.NewResId(secret, "peanuts"): rf.FromMap(
map[string]interface{}{
"apiVersion": "v1",
"kind": "Secret",
"metadata": map[string]interface{}{
"name": "peanuts",
},
"type": string(corev1.SecretTypeOpaque),
"data": map[string]interface{}{
"DB_USERNAME": base64.StdEncoding.EncodeToString([]byte("admin")),
"DB_PASSWORD": base64.StdEncoding.EncodeToString([]byte("somepw")),
},
}).SetBehavior(ifc.BehaviorCreate),
}
if !reflect.DeepEqual(actual, expected) {
t.Fatalf("%#v\ndoesn't match expected:\n%#v", actual, expected)
}
}
func TestSecretTimeout(t *testing.T) {
timeout := int64(1)
secrets := []types.SecretArgs{
{
Name: "slow",
TimeoutSeconds: &timeout,
CommandSources: types.CommandSources{
Commands: map[string]string{
"USER": "sleep 2",
},
},
Type: "Opaque",
},
}
fakeFs := fs.MakeFakeFS()
fakeFs.Mkdir(".")
_, err := rmF.NewResMapFromSecretArgs(
configmapandsecret.NewSecretFactory(fakeFs, "."), secrets)
if err == nil {
t.Fatal("didn't get the expected timeout error", err)
}
}