...

Source file src/sigs.k8s.io/kustomize/api/resmap/factory_test.go

Documentation: sigs.k8s.io/kustomize/api/resmap

     1  // Copyright 2019 The Kubernetes Authors.
     2  // SPDX-License-Identifier: Apache-2.0
     3  
     4  package resmap_test
     5  
     6  import (
     7  	"encoding/base64"
     8  	"testing"
     9  
    10  	"github.com/stretchr/testify/assert"
    11  	"github.com/stretchr/testify/require"
    12  	"sigs.k8s.io/kustomize/api/ifc"
    13  	loader "sigs.k8s.io/kustomize/api/internal/loader"
    14  	"sigs.k8s.io/kustomize/api/kv"
    15  	ldrpkg "sigs.k8s.io/kustomize/api/pkg/loader"
    16  	. "sigs.k8s.io/kustomize/api/resmap"
    17  	resmaptest_test "sigs.k8s.io/kustomize/api/testutils/resmaptest"
    18  	valtest_test "sigs.k8s.io/kustomize/api/testutils/valtest"
    19  	"sigs.k8s.io/kustomize/api/types"
    20  	"sigs.k8s.io/kustomize/kyaml/filesys"
    21  	"sigs.k8s.io/kustomize/kyaml/yaml"
    22  )
    23  
    24  func TestFromFile(t *testing.T) {
    25  	resourceStr := `apiVersion: apps/v1
    26  kind: Deployment
    27  metadata:
    28    name: dply1
    29  ---
    30  apiVersion: apps/v1
    31  kind: Deployment
    32  metadata:
    33    name: dply2
    34  ---
    35  # some comment
    36  ---
    37  apiVersion: apps/v1
    38  kind: Deployment
    39  metadata:
    40    name: dply2
    41    namespace: test
    42  ---
    43  `
    44  	expected := resmaptest_test.NewRmBuilder(t, rf).
    45  		Add(map[string]interface{}{
    46  			"apiVersion": "apps/v1",
    47  			"kind":       "Deployment",
    48  			"metadata": map[string]interface{}{
    49  				"name": "dply1",
    50  			}}).
    51  		Add(map[string]interface{}{
    52  			"apiVersion": "apps/v1",
    53  			"kind":       "Deployment",
    54  			"metadata": map[string]interface{}{
    55  				"name": "dply2",
    56  			}}).
    57  		Add(map[string]interface{}{
    58  			"apiVersion": "apps/v1",
    59  			"kind":       "Deployment",
    60  			"metadata": map[string]interface{}{
    61  				"name":      "dply2",
    62  				"namespace": "test",
    63  			}}).ResMap()
    64  	expYaml, err := expected.AsYaml()
    65  	require.NoError(t, err)
    66  
    67  	fSys := filesys.MakeFsInMemory()
    68  	require.NoError(t, fSys.WriteFile("deployment.yaml", []byte(resourceStr)))
    69  
    70  	ldr, err := loader.NewLoader(
    71  		loader.RestrictionRootOnly, filesys.Separator, fSys)
    72  	require.NoError(t, err)
    73  
    74  	m, err := rmF.FromFile(ldr, "deployment.yaml")
    75  	require.NoError(t, err)
    76  	mYaml, err := m.AsYaml()
    77  	require.NoError(t, err)
    78  	assert.Equal(t, expYaml, mYaml)
    79  }
    80  
    81  func TestFromBytes(t *testing.T) {
    82  	encoded := []byte(`apiVersion: v1
    83  kind: ConfigMap
    84  metadata:
    85    name: cm1
    86  ---
    87  apiVersion: v1
    88  kind: ConfigMap
    89  metadata:
    90    name: cm2
    91  `)
    92  	expected := resmaptest_test.NewRmBuilder(t, rf).
    93  		Add(map[string]interface{}{
    94  			"apiVersion": "v1",
    95  			"kind":       "ConfigMap",
    96  			"metadata": map[string]interface{}{
    97  				"name": "cm1",
    98  			}}).
    99  		Add(map[string]interface{}{
   100  			"apiVersion": "v1",
   101  			"kind":       "ConfigMap",
   102  			"metadata": map[string]interface{}{
   103  				"name": "cm2",
   104  			}}).ResMap()
   105  	expYaml, err := expected.AsYaml()
   106  	require.NoError(t, err)
   107  	m, err := rmF.NewResMapFromBytes(encoded)
   108  	require.NoError(t, err)
   109  	mYaml, err := m.AsYaml()
   110  	require.NoError(t, err)
   111  	assert.Equal(t, expYaml, mYaml)
   112  }
   113  
   114  func TestNewFromConfigMaps(t *testing.T) {
   115  	type testCase struct {
   116  		description string
   117  		input       []types.ConfigMapArgs
   118  		filepath    string
   119  		content     string
   120  		expected    ResMap
   121  	}
   122  
   123  	fSys := filesys.MakeFsInMemory()
   124  	ldr, err := loader.NewLoader(
   125  		loader.RestrictionRootOnly, filesys.Separator, fSys)
   126  	if err != nil {
   127  		t.Fatal(err)
   128  	}
   129  	kvLdr := kv.NewLoader(ldr, valtest_test.MakeFakeValidator())
   130  	testCases := []testCase{
   131  		{
   132  			description: "construct config map from env",
   133  			input: []types.ConfigMapArgs{
   134  				{
   135  					GeneratorArgs: types.GeneratorArgs{
   136  						Name: "envConfigMap",
   137  						KvPairSources: types.KvPairSources{
   138  							EnvSources: []string{"app.env"},
   139  						},
   140  					},
   141  				},
   142  			},
   143  			filepath: "app.env",
   144  			content:  "DB_USERNAME=admin\nDB_PASSWORD=somepw",
   145  			expected: resmaptest_test.NewRmBuilder(t, rf).Add(
   146  				map[string]interface{}{
   147  					"apiVersion": "v1",
   148  					"kind":       "ConfigMap",
   149  					"metadata": map[string]interface{}{
   150  						"name": "envConfigMap",
   151  					},
   152  					"data": map[string]interface{}{
   153  						"DB_USERNAME": "admin",
   154  						"DB_PASSWORD": "somepw",
   155  					}}).ResMap(),
   156  		},
   157  
   158  		{
   159  			description: "construct config map from file",
   160  			input: []types.ConfigMapArgs{{
   161  				GeneratorArgs: types.GeneratorArgs{
   162  					Name: "fileConfigMap",
   163  					KvPairSources: types.KvPairSources{
   164  						FileSources: []string{"app-init.ini"},
   165  					},
   166  				},
   167  			},
   168  			},
   169  			filepath: "app-init.ini",
   170  			content:  "FOO=bar\nBAR=baz\n",
   171  			expected: resmaptest_test.NewRmBuilder(t, rf).Add(
   172  				map[string]interface{}{
   173  					"apiVersion": "v1",
   174  					"kind":       "ConfigMap",
   175  					"metadata": map[string]interface{}{
   176  						"name": "fileConfigMap",
   177  					},
   178  					"data": map[string]interface{}{
   179  						"app-init.ini": `FOO=bar
   180  BAR=baz
   181  `,
   182  					},
   183  				}).ResMap(),
   184  		},
   185  		{
   186  			description: "construct config map from literal",
   187  			input: []types.ConfigMapArgs{
   188  				{
   189  					GeneratorArgs: types.GeneratorArgs{
   190  						Name: "literalConfigMap",
   191  						KvPairSources: types.KvPairSources{
   192  							LiteralSources: []string{"a=x", "b=y", "c=\"Good Morning\"", "d=\"false\""},
   193  						},
   194  					},
   195  				},
   196  			},
   197  			expected: resmaptest_test.NewRmBuilder(t, rf).Add(
   198  				map[string]interface{}{
   199  					"apiVersion": "v1",
   200  					"kind":       "ConfigMap",
   201  					"metadata": map[string]interface{}{
   202  						"name": "literalConfigMap",
   203  					},
   204  					"data": map[string]interface{}{
   205  						"a": "x",
   206  						"b": "y",
   207  						"c": "Good Morning",
   208  						"d": "false",
   209  					},
   210  				}).ResMap(),
   211  		},
   212  
   213  		// TODO: add testcase for data coming from multiple sources like
   214  		// files/literal/env etc.
   215  	}
   216  	for _, tc := range testCases {
   217  		if tc.filepath != "" {
   218  			if fErr := fSys.WriteFile(tc.filepath, []byte(tc.content)); fErr != nil {
   219  				t.Fatalf("error adding file '%s': %v\n", tc.filepath, fErr)
   220  			}
   221  		}
   222  		r, err := rmF.NewResMapFromConfigMapArgs(kvLdr, tc.input)
   223  		require.NoError(t, err, tc.description)
   224  		r.RemoveBuildAnnotations()
   225  		rYaml, err := r.AsYaml()
   226  		require.NoError(t, err, tc.description)
   227  		tc.expected.RemoveBuildAnnotations()
   228  		expYaml, err := tc.expected.AsYaml()
   229  		require.NoError(t, err, tc.description)
   230  		assert.Equal(t, expYaml, rYaml)
   231  	}
   232  }
   233  
   234  func TestNewResMapFromSecretArgs(t *testing.T) {
   235  	secrets := []types.SecretArgs{
   236  		{
   237  			GeneratorArgs: types.GeneratorArgs{
   238  				Name: "apple",
   239  				KvPairSources: types.KvPairSources{
   240  					LiteralSources: []string{
   241  						"DB_USERNAME=admin",
   242  						"DB_PASSWORD=somepw",
   243  					},
   244  				},
   245  			},
   246  			Type: ifc.SecretTypeOpaque,
   247  		},
   248  	}
   249  	fSys := filesys.MakeFsInMemory()
   250  	fSys.Mkdir(filesys.SelfDir)
   251  
   252  	actual, err := rmF.NewResMapFromSecretArgs(
   253  		kv.NewLoader(
   254  			ldrpkg.NewFileLoaderAtRoot(fSys),
   255  			valtest_test.MakeFakeValidator()), secrets)
   256  	if err != nil {
   257  		t.Fatalf("unexpected error: %v", err)
   258  	}
   259  	actual.RemoveBuildAnnotations()
   260  	actYaml, err := actual.AsYaml()
   261  	require.NoError(t, err)
   262  
   263  	expected := resmaptest_test.NewRmBuilder(t, rf).Add(
   264  		map[string]interface{}{
   265  			"apiVersion": "v1",
   266  			"kind":       "Secret",
   267  			"metadata": map[string]interface{}{
   268  				"name": "apple",
   269  			},
   270  			"type": ifc.SecretTypeOpaque,
   271  			"data": map[string]interface{}{
   272  				"DB_USERNAME": base64.StdEncoding.EncodeToString([]byte("admin")),
   273  				"DB_PASSWORD": base64.StdEncoding.EncodeToString([]byte("somepw")),
   274  			},
   275  		}).ResMap()
   276  	expYaml, err := expected.AsYaml()
   277  	require.NoError(t, err)
   278  
   279  	assert.Equal(t, string(expYaml), string(actYaml))
   280  }
   281  
   282  func TestFromRNodeSlice(t *testing.T) {
   283  	type testcase struct {
   284  		input    string
   285  		expected ResMap
   286  	}
   287  	testcases := map[string]testcase{
   288  		"no resource": {
   289  			input:    "---",
   290  			expected: resmaptest_test.NewRmBuilder(t, rf).ResMap(),
   291  		},
   292  		"single resource": {
   293  			input: `apiVersion: rbac.authorization.k8s.io/v1
   294  kind: ClusterRole
   295  metadata:
   296    name: namespace-reader
   297  rules:
   298  - apiGroups:
   299    - ""
   300    resources:
   301    - namespaces
   302    verbs:
   303    - get
   304    - watch
   305    - list
   306        `,
   307  			expected: resmaptest_test.NewRmBuilder(t, rf).Add(
   308  				map[string]interface{}{
   309  					"apiVersion": "rbac.authorization.k8s.io/v1",
   310  					"kind":       "ClusterRole",
   311  					"metadata": map[string]interface{}{
   312  						"name": "namespace-reader",
   313  					},
   314  					"rules": []interface{}{
   315  						map[string]interface{}{
   316  							"apiGroups": []interface{}{
   317  								"",
   318  							},
   319  							"resources": []interface{}{
   320  								"namespaces",
   321  							},
   322  							"verbs": []interface{}{
   323  								"get",
   324  								"watch",
   325  								"list",
   326  							},
   327  						},
   328  					},
   329  				}).ResMap(),
   330  		},
   331  		"local config": {
   332  			// local config should be ignored
   333  			input: `apiVersion: v1
   334  kind: ConfigMap
   335  metadata:
   336    name: my-config
   337    annotations:
   338      config.kubernetes.io/local-config: 'true'
   339  `,
   340  			expected: resmaptest_test.NewRmBuilder(t, rf).ResMap(),
   341  		},
   342  	}
   343  	for name := range testcases {
   344  		tc := testcases[name]
   345  		t.Run(name, func(t *testing.T) {
   346  			rm, err := rmF.NewResMapFromRNodeSlice(
   347  				[]*yaml.RNode{yaml.MustParse(tc.input)})
   348  			if err != nil {
   349  				t.Fatalf("unexpected error in test case [%s]: %v", name, err)
   350  			}
   351  			if err = tc.expected.ErrorIfNotEqualLists(rm); err != nil {
   352  				t.Fatalf("error in test case [%s]: %s", name, err)
   353  			}
   354  		})
   355  	}
   356  }
   357  

View as plain text