...

Source file src/sigs.k8s.io/kustomize/api/krusty/generatormergeandreplace_test.go

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

     1  // Copyright 2019 The Kubernetes Authors.
     2  // SPDX-License-Identifier: Apache-2.0
     3  
     4  package krusty_test
     5  
     6  import (
     7  	"strings"
     8  	"testing"
     9  
    10  	kusttest_test "sigs.k8s.io/kustomize/api/testutils/kusttest"
    11  )
    12  
    13  func TestSimpleBase(t *testing.T) {
    14  	th := kusttest_test.MakeHarness(t)
    15  	th.WriteK("app/base", `
    16  namePrefix: team-foo-
    17  commonLabels:
    18    app: mynginx
    19    org: example.com
    20    team: foo
    21  commonAnnotations:
    22    note: This is a test annotation
    23  resources:
    24    - service.yaml
    25    - deployment.yaml
    26    - networkpolicy.yaml
    27  `)
    28  	th.WriteF("app/base/service.yaml", `
    29  apiVersion: v1
    30  kind: Service
    31  metadata:
    32    name: nginx
    33    labels:
    34      app: nginx
    35  spec:
    36    ports:
    37      - port: 80
    38    selector:
    39      app: nginx
    40  `)
    41  	th.WriteF("app/base/networkpolicy.yaml", `
    42  apiVersion: networking.k8s.io/v1
    43  kind: NetworkPolicy
    44  metadata:
    45    name: nginx
    46  spec:
    47    podSelector:
    48      matchExpressions:
    49        - {key: app, operator: In, values: [test]}
    50    ingress:
    51      - from:
    52          - podSelector:
    53              matchLabels:
    54                app: nginx
    55  `)
    56  	th.WriteF("app/base/deployment.yaml", `
    57  apiVersion: apps/v1
    58  kind: Deployment
    59  metadata:
    60    name: nginx
    61    labels:
    62      app: nginx
    63  spec:
    64    template:
    65      metadata:
    66        labels:
    67          app: nginx
    68      spec:
    69        containers:
    70        - name: nginx
    71          image: nginx
    72  `)
    73  	m := th.Run("app/base", th.MakeDefaultOptions())
    74  	th.AssertActualEqualsExpected(m, `
    75  apiVersion: v1
    76  kind: Service
    77  metadata:
    78    annotations:
    79      note: This is a test annotation
    80    labels:
    81      app: mynginx
    82      org: example.com
    83      team: foo
    84    name: team-foo-nginx
    85  spec:
    86    ports:
    87    - port: 80
    88    selector:
    89      app: mynginx
    90      org: example.com
    91      team: foo
    92  ---
    93  apiVersion: apps/v1
    94  kind: Deployment
    95  metadata:
    96    annotations:
    97      note: This is a test annotation
    98    labels:
    99      app: mynginx
   100      org: example.com
   101      team: foo
   102    name: team-foo-nginx
   103  spec:
   104    selector:
   105      matchLabels:
   106        app: mynginx
   107        org: example.com
   108        team: foo
   109    template:
   110      metadata:
   111        annotations:
   112          note: This is a test annotation
   113        labels:
   114          app: mynginx
   115          org: example.com
   116          team: foo
   117      spec:
   118        containers:
   119        - image: nginx
   120          name: nginx
   121  ---
   122  apiVersion: networking.k8s.io/v1
   123  kind: NetworkPolicy
   124  metadata:
   125    annotations:
   126      note: This is a test annotation
   127    labels:
   128      app: mynginx
   129      org: example.com
   130      team: foo
   131    name: team-foo-nginx
   132  spec:
   133    ingress:
   134    - from:
   135      - podSelector:
   136          matchLabels:
   137            app: mynginx
   138            org: example.com
   139            team: foo
   140    podSelector:
   141      matchExpressions:
   142      - key: app
   143        operator: In
   144        values:
   145        - test
   146  `)
   147  }
   148  
   149  func makeBaseWithGenerators(th kusttest_test.Harness) {
   150  	th.WriteK("app", `
   151  namePrefix: team-foo-
   152  commonLabels:
   153    app: mynginx
   154    org: example.com
   155    team: foo
   156  commonAnnotations:
   157    note: This is a test annotation
   158  resources:
   159    - deployment.yaml
   160    - service.yaml
   161  configMapGenerator:
   162  - name: configmap-in-base
   163    literals:
   164    - foo=bar
   165  secretGenerator:
   166  - name: secret-in-base
   167    literals:
   168    - username=admin
   169    - password=somepw
   170  `)
   171  	th.WriteF("app/deployment.yaml", `
   172  apiVersion: apps/v1
   173  kind: Deployment
   174  metadata:
   175    name: nginx
   176    labels:
   177      app: nginx
   178  spec:
   179    template:
   180      metadata:
   181        labels:
   182          app: nginx
   183      spec:
   184        containers:
   185        - name: nginx
   186          image: nginx
   187          volumeMounts:
   188          - name: nginx-persistent-storage
   189            mountPath: /tmp/ps
   190        volumes:
   191        - name: nginx-persistent-storage
   192          emptyDir: {}
   193        - configMap:
   194            name: configmap-in-base
   195          name: configmap-in-base
   196  `)
   197  	th.WriteF("app/service.yaml", `
   198  apiVersion: v1
   199  kind: Service
   200  metadata:
   201    name: nginx
   202    labels:
   203      app: nginx
   204  spec:
   205    ports:
   206      - port: 80
   207    selector:
   208      app: nginx
   209  `)
   210  }
   211  
   212  func TestBaseWithGeneratorsAlone(t *testing.T) {
   213  	th := kusttest_test.MakeHarness(t)
   214  	makeBaseWithGenerators(th)
   215  	m := th.Run("app", th.MakeDefaultOptions())
   216  	th.AssertActualEqualsExpected(m, `
   217  apiVersion: apps/v1
   218  kind: Deployment
   219  metadata:
   220    annotations:
   221      note: This is a test annotation
   222    labels:
   223      app: mynginx
   224      org: example.com
   225      team: foo
   226    name: team-foo-nginx
   227  spec:
   228    selector:
   229      matchLabels:
   230        app: mynginx
   231        org: example.com
   232        team: foo
   233    template:
   234      metadata:
   235        annotations:
   236          note: This is a test annotation
   237        labels:
   238          app: mynginx
   239          org: example.com
   240          team: foo
   241      spec:
   242        containers:
   243        - image: nginx
   244          name: nginx
   245          volumeMounts:
   246          - mountPath: /tmp/ps
   247            name: nginx-persistent-storage
   248        volumes:
   249        - emptyDir: {}
   250          name: nginx-persistent-storage
   251        - configMap:
   252            name: team-foo-configmap-in-base-798k5k7g9f
   253          name: configmap-in-base
   254  ---
   255  apiVersion: v1
   256  kind: Service
   257  metadata:
   258    annotations:
   259      note: This is a test annotation
   260    labels:
   261      app: mynginx
   262      org: example.com
   263      team: foo
   264    name: team-foo-nginx
   265  spec:
   266    ports:
   267    - port: 80
   268    selector:
   269      app: mynginx
   270      org: example.com
   271      team: foo
   272  ---
   273  apiVersion: v1
   274  data:
   275    foo: bar
   276  kind: ConfigMap
   277  metadata:
   278    annotations:
   279      note: This is a test annotation
   280    labels:
   281      app: mynginx
   282      org: example.com
   283      team: foo
   284    name: team-foo-configmap-in-base-798k5k7g9f
   285  ---
   286  apiVersion: v1
   287  data:
   288    password: c29tZXB3
   289    username: YWRtaW4=
   290  kind: Secret
   291  metadata:
   292    annotations:
   293      note: This is a test annotation
   294    labels:
   295      app: mynginx
   296      org: example.com
   297      team: foo
   298    name: team-foo-secret-in-base-bgd6bkgdm2
   299  type: Opaque
   300  `)
   301  }
   302  
   303  func TestMergeAndReplaceGenerators(t *testing.T) {
   304  	th := kusttest_test.MakeHarness(t)
   305  	makeBaseWithGenerators(th)
   306  	th.WriteF("overlay/deployment.yaml", `
   307  apiVersion: apps/v1
   308  kind: Deployment
   309  metadata:
   310    name: nginx
   311  spec:
   312    template:
   313      spec:
   314        volumes:
   315        - name: nginx-persistent-storage
   316          emptyDir: null
   317          gcePersistentDisk:
   318            pdName: nginx-persistent-storage
   319        - configMap:
   320            name: configmap-in-overlay
   321          name: configmap-in-overlay
   322  `)
   323  	th.WriteK("overlay", `
   324  namePrefix: staging-
   325  commonLabels:
   326    env: staging
   327    team: override-foo
   328  patchesStrategicMerge:
   329  - deployment.yaml
   330  resources:
   331  - ../app
   332  configMapGenerator:
   333  - name: configmap-in-overlay
   334    literals:
   335    - hello=world
   336  - name: configmap-in-base
   337    behavior: replace
   338    literals:
   339    - foo=override-bar
   340  secretGenerator:
   341  - name: secret-in-base
   342    behavior: merge
   343    literals:
   344    - proxy=haproxy
   345  `)
   346  	m := th.Run("overlay", th.MakeDefaultOptions())
   347  	th.AssertActualEqualsExpected(m, `
   348  apiVersion: apps/v1
   349  kind: Deployment
   350  metadata:
   351    annotations:
   352      note: This is a test annotation
   353    labels:
   354      app: mynginx
   355      env: staging
   356      org: example.com
   357      team: override-foo
   358    name: staging-team-foo-nginx
   359  spec:
   360    selector:
   361      matchLabels:
   362        app: mynginx
   363        env: staging
   364        org: example.com
   365        team: override-foo
   366    template:
   367      metadata:
   368        annotations:
   369          note: This is a test annotation
   370        labels:
   371          app: mynginx
   372          env: staging
   373          org: example.com
   374          team: override-foo
   375      spec:
   376        containers:
   377        - image: nginx
   378          name: nginx
   379          volumeMounts:
   380          - mountPath: /tmp/ps
   381            name: nginx-persistent-storage
   382        volumes:
   383        - gcePersistentDisk:
   384            pdName: nginx-persistent-storage
   385          name: nginx-persistent-storage
   386        - configMap:
   387            name: staging-configmap-in-overlay-dc6fm46dhm
   388          name: configmap-in-overlay
   389        - configMap:
   390            name: staging-team-foo-configmap-in-base-hc6g9dk6g9
   391          name: configmap-in-base
   392  ---
   393  apiVersion: v1
   394  kind: Service
   395  metadata:
   396    annotations:
   397      note: This is a test annotation
   398    labels:
   399      app: mynginx
   400      env: staging
   401      org: example.com
   402      team: override-foo
   403    name: staging-team-foo-nginx
   404  spec:
   405    ports:
   406    - port: 80
   407    selector:
   408      app: mynginx
   409      env: staging
   410      org: example.com
   411      team: override-foo
   412  ---
   413  apiVersion: v1
   414  data:
   415    foo: override-bar
   416  kind: ConfigMap
   417  metadata:
   418    annotations:
   419      note: This is a test annotation
   420    labels:
   421      app: mynginx
   422      env: staging
   423      org: example.com
   424      team: override-foo
   425    name: staging-team-foo-configmap-in-base-hc6g9dk6g9
   426  ---
   427  apiVersion: v1
   428  data:
   429    password: c29tZXB3
   430    proxy: aGFwcm94eQ==
   431    username: YWRtaW4=
   432  kind: Secret
   433  metadata:
   434    annotations:
   435      note: This is a test annotation
   436    labels:
   437      app: mynginx
   438      env: staging
   439      org: example.com
   440      team: override-foo
   441    name: staging-team-foo-secret-in-base-k2k4692t9g
   442  type: Opaque
   443  ---
   444  apiVersion: v1
   445  data:
   446    hello: world
   447  kind: ConfigMap
   448  metadata:
   449    labels:
   450      env: staging
   451      team: override-foo
   452    name: staging-configmap-in-overlay-dc6fm46dhm
   453  `)
   454  }
   455  
   456  func TestMergeAndReplaceDisableNameSuffixHashGenerators(t *testing.T) {
   457  	th := kusttest_test.MakeHarness(t)
   458  	th.WriteK("app", `
   459  namePrefix: team-foo-
   460  commonLabels:
   461    app: mynginx
   462    org: example.com
   463    team: foo
   464  commonAnnotations:
   465    note: This is a test annotation
   466  resources:
   467    - deployment.yaml
   468  configMapGenerator:
   469  - name: configmap-in-base
   470    literals:
   471    - foo=bar
   472  secretGenerator:
   473  - name: secret-in-base
   474    literals:
   475    - username=admin
   476    - password=somepw
   477  `)
   478  	th.WriteF("app/deployment.yaml", `
   479  apiVersion: apps/v1
   480  kind: Deployment
   481  metadata:
   482    name: nginx
   483    labels:
   484      app: nginx
   485  spec:
   486    template:
   487      metadata:
   488        labels:
   489          app: nginx
   490      spec:
   491        containers:
   492        - name: nginx
   493          image: nginx
   494          volumeMounts:
   495          - name: nginx-persistent-storage
   496            mountPath: /tmp/ps
   497        volumes:
   498        - name: nginx-persistent-storage
   499          emptyDir: {}
   500        - configMap:
   501            name: configmap-in-base
   502          name: configmap-in-base
   503  `)
   504  	th.WriteF("overlay/deployment.yaml", `
   505  apiVersion: apps/v1
   506  kind: Deployment
   507  metadata:
   508    name: nginx
   509  spec:
   510    template:
   511      spec:
   512        volumes:
   513        - name: nginx-persistent-storage
   514          emptyDir: null
   515          gcePersistentDisk:
   516            pdName: nginx-persistent-storage
   517        - configMap:
   518            name: configmap-in-overlay
   519          name: configmap-in-overlay
   520  `)
   521  	th.WriteK("overlay", `
   522  namePrefix: staging-
   523  commonLabels:
   524    env: staging
   525    team: override-foo
   526  patchesStrategicMerge:
   527  - deployment.yaml
   528  resources:
   529  - ../app
   530  configMapGenerator:
   531  - name: configmap-in-overlay
   532    literals:
   533    - hello=world
   534    options:
   535      disableNameSuffixHash: true
   536  - name: configmap-in-base
   537    behavior: replace
   538    literals:
   539    - foo=override-bar
   540    options:
   541      disableNameSuffixHash: true
   542  secretGenerator:
   543  - name: secret-in-base
   544    behavior: merge
   545    literals:
   546    - proxy=haproxy
   547    options:
   548      disableNameSuffixHash: true
   549  `)
   550  	m := th.Run("overlay", th.MakeDefaultOptions())
   551  	th.AssertActualEqualsExpected(m, `
   552  apiVersion: apps/v1
   553  kind: Deployment
   554  metadata:
   555    annotations:
   556      note: This is a test annotation
   557    labels:
   558      app: mynginx
   559      env: staging
   560      org: example.com
   561      team: override-foo
   562    name: staging-team-foo-nginx
   563  spec:
   564    selector:
   565      matchLabels:
   566        app: mynginx
   567        env: staging
   568        org: example.com
   569        team: override-foo
   570    template:
   571      metadata:
   572        annotations:
   573          note: This is a test annotation
   574        labels:
   575          app: mynginx
   576          env: staging
   577          org: example.com
   578          team: override-foo
   579      spec:
   580        containers:
   581        - image: nginx
   582          name: nginx
   583          volumeMounts:
   584          - mountPath: /tmp/ps
   585            name: nginx-persistent-storage
   586        volumes:
   587        - gcePersistentDisk:
   588            pdName: nginx-persistent-storage
   589          name: nginx-persistent-storage
   590        - configMap:
   591            name: staging-configmap-in-overlay
   592          name: configmap-in-overlay
   593        - configMap:
   594            name: staging-team-foo-configmap-in-base
   595          name: configmap-in-base
   596  ---
   597  apiVersion: v1
   598  data:
   599    foo: override-bar
   600  kind: ConfigMap
   601  metadata:
   602    annotations:
   603      note: This is a test annotation
   604    labels:
   605      app: mynginx
   606      env: staging
   607      org: example.com
   608      team: override-foo
   609    name: staging-team-foo-configmap-in-base
   610  ---
   611  apiVersion: v1
   612  data:
   613    password: c29tZXB3
   614    proxy: aGFwcm94eQ==
   615    username: YWRtaW4=
   616  kind: Secret
   617  metadata:
   618    annotations:
   619      note: This is a test annotation
   620    labels:
   621      app: mynginx
   622      env: staging
   623      org: example.com
   624      team: override-foo
   625    name: staging-team-foo-secret-in-base
   626  type: Opaque
   627  ---
   628  apiVersion: v1
   629  data:
   630    hello: world
   631  kind: ConfigMap
   632  metadata:
   633    labels:
   634      env: staging
   635      team: override-foo
   636    name: staging-configmap-in-overlay
   637  `)
   638  }
   639  
   640  func TestGeneratingIntoNamespaces(t *testing.T) {
   641  	th := kusttest_test.MakeHarness(t)
   642  	th.WriteK("app", `
   643  configMapGenerator:
   644  - name: test
   645    namespace: default
   646    literals:
   647      - key=value
   648  - name: test
   649    namespace: kube-system
   650    literals:
   651      - key=value
   652  secretGenerator:
   653  - name: test
   654    namespace: default
   655    literals:
   656    - username=admin
   657    - password=somepw
   658  - name: test
   659    namespace: kube-system
   660    literals:
   661    - username=admin
   662    - password=somepw
   663  `)
   664  	m := th.Run("app", th.MakeDefaultOptions())
   665  	th.AssertActualEqualsExpected(m, `
   666  apiVersion: v1
   667  data:
   668    key: value
   669  kind: ConfigMap
   670  metadata:
   671    name: test-t757gk2bmf
   672    namespace: default
   673  ---
   674  apiVersion: v1
   675  data:
   676    key: value
   677  kind: ConfigMap
   678  metadata:
   679    name: test-t757gk2bmf
   680    namespace: kube-system
   681  ---
   682  apiVersion: v1
   683  data:
   684    password: c29tZXB3
   685    username: YWRtaW4=
   686  kind: Secret
   687  metadata:
   688    name: test-bgd6bkgdm2
   689    namespace: default
   690  type: Opaque
   691  ---
   692  apiVersion: v1
   693  data:
   694    password: c29tZXB3
   695    username: YWRtaW4=
   696  kind: Secret
   697  metadata:
   698    name: test-bgd6bkgdm2
   699    namespace: kube-system
   700  type: Opaque
   701  `)
   702  }
   703  
   704  // Valid that conflict is detected is the name are identical
   705  // and namespace left to default
   706  func TestConfigMapGeneratingIntoSameNamespace(t *testing.T) {
   707  	th := kusttest_test.MakeHarness(t)
   708  	th.WriteK("app", `
   709  configMapGenerator:
   710  - name: test
   711    namespace: default
   712    literals:
   713    - key=value
   714  - name: test
   715    literals:
   716    - key=value
   717  `)
   718  	err := th.RunWithErr("app", th.MakeDefaultOptions())
   719  	if err == nil {
   720  		t.Fatalf("expected error")
   721  	}
   722  	if !strings.Contains(err.Error(), "behavior must be merge or replace") {
   723  		t.Fatalf("unexpected error %v", err)
   724  	}
   725  }
   726  
   727  // Valid that conflict is detected is the name are identical
   728  // and namespace left to default
   729  func TestSecretGeneratingIntoSameNamespace(t *testing.T) {
   730  	th := kusttest_test.MakeHarness(t)
   731  	th.WriteK("app", `
   732  secretGenerator:
   733  - name: test
   734    namespace: default
   735    literals:
   736    - username=admin
   737    - password=somepw
   738  - name: test
   739    literals:
   740    - username=admin
   741    - password=somepw
   742  `)
   743  	err := th.RunWithErr("app", th.MakeDefaultOptions())
   744  	if err == nil {
   745  		t.Fatalf("expected error")
   746  	}
   747  	if !strings.Contains(err.Error(), "behavior must be merge or replace") {
   748  		t.Fatalf("unexpected error %v", err)
   749  	}
   750  }
   751  

View as plain text