...

Source file src/sigs.k8s.io/kustomize/api/krusty/gvknpatch_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  	"testing"
     8  
     9  	"github.com/stretchr/testify/require"
    10  	kusttest_test "sigs.k8s.io/kustomize/api/testutils/kusttest"
    11  )
    12  
    13  // Regression test for https://github.com/kubernetes-sigs/kustomize/issues/3280
    14  // GVKN shouldn't change with default options
    15  func TestKeepOriginalGVKN(t *testing.T) {
    16  	th := kusttest_test.MakeHarness(t)
    17  	th.WriteF("deployment.yaml", `
    18  apiVersion: v1
    19  kind: Deployment
    20  metadata:
    21    name: old-name
    22  spec:
    23    template:
    24      spec:
    25        containers:
    26          - name: nginx
    27            image: nginx
    28  `)
    29  	th.WriteF("patch.yaml", `
    30  apiVersion: v1
    31  kind: StatefulSet
    32  metadata:
    33    name: new-name
    34  `)
    35  	th.WriteK(".", `
    36  resources:
    37  - deployment.yaml
    38  
    39  patches:
    40  - path: patch.yaml
    41    target:
    42      kind: Deployment
    43  `)
    44  	m := th.Run(".", th.MakeDefaultOptions())
    45  	th.AssertActualEqualsExpected(m, `
    46  apiVersion: v1
    47  kind: Deployment
    48  metadata:
    49    name: old-name
    50  spec:
    51    template:
    52      spec:
    53        containers:
    54        - image: nginx
    55          name: nginx
    56  `)
    57  }
    58  
    59  // https://github.com/kubernetes-sigs/kustomize/issues/3280
    60  // These tests document behavior that will change
    61  func TestChangeName(t *testing.T) {
    62  	th := kusttest_test.MakeHarness(t)
    63  	th.WriteF("deployment.yaml", `
    64  apiVersion: v1
    65  kind: Deployment
    66  metadata:
    67    name: old-name
    68  spec:
    69    template:
    70      spec:
    71        containers:
    72          - name: nginx
    73            image: nginx
    74  `)
    75  	th.WriteF("patch.yaml", `
    76  apiVersion: v1
    77  kind: Deployment
    78  metadata:
    79    name: new-name
    80  `)
    81  	th.WriteK(".", `
    82  resources:
    83  - deployment.yaml
    84  
    85  patches:
    86  - path: patch.yaml
    87    target:
    88      kind: Deployment
    89    options:
    90      allowNameChange: true
    91  `)
    92  	options := th.MakeDefaultOptions()
    93  	m := th.Run(".", options)
    94  	th.AssertActualEqualsExpected(m, `
    95  apiVersion: v1
    96  kind: Deployment
    97  metadata:
    98    name: new-name
    99  spec:
   100    template:
   101      spec:
   102        containers:
   103        - image: nginx
   104          name: nginx
   105  `)
   106  }
   107  
   108  func TestChangeKind(t *testing.T) {
   109  	th := kusttest_test.MakeHarness(t)
   110  	th.WriteF("deployment.yaml", `
   111  apiVersion: v1
   112  kind: Deployment
   113  metadata:
   114    name: old-name
   115  spec:
   116    template:
   117      spec:
   118        containers:
   119          - name: nginx
   120            image: nginx
   121  `)
   122  	th.WriteF("patch.yaml", `
   123  apiVersion: v1
   124  kind: StatefulSet
   125  metadata:
   126    name: old-name
   127  `)
   128  	th.WriteK(".", `
   129  resources:
   130  - deployment.yaml
   131  patches:
   132  - path: patch.yaml
   133    target:
   134      kind: Deployment
   135    options:
   136      allowKindChange: true
   137  `)
   138  	options := th.MakeDefaultOptions()
   139  	m := th.Run(".", options)
   140  	th.AssertActualEqualsExpected(m, `
   141  apiVersion: v1
   142  kind: StatefulSet
   143  metadata:
   144    name: old-name
   145  spec:
   146    template:
   147      spec:
   148        containers:
   149        - image: nginx
   150          name: nginx
   151  `)
   152  }
   153  
   154  func TestChangeNameAndKind(t *testing.T) {
   155  	th := kusttest_test.MakeHarness(t)
   156  	th.WriteF("deployment.yaml", `
   157  apiVersion: v1
   158  kind: Deployment
   159  metadata:
   160    name: old-name
   161  spec:
   162    template:
   163      spec:
   164        containers:
   165          - name: nginx
   166            image: nginx
   167  `)
   168  	th.WriteF("patch.yaml", `
   169  apiVersion: v1
   170  kind: StatefulSet
   171  metadata:
   172    name: new-name
   173  `)
   174  	th.WriteK(".", `
   175  resources:
   176  - deployment.yaml
   177  patches:
   178  - path: patch.yaml
   179    target:
   180      kind: Deployment
   181    options:
   182      allowNameChange: true
   183      allowKindChange: true
   184  `)
   185  	options := th.MakeDefaultOptions()
   186  	m := th.Run(".", options)
   187  	th.AssertActualEqualsExpected(m, `
   188  apiVersion: v1
   189  kind: StatefulSet
   190  metadata:
   191    name: new-name
   192  spec:
   193    template:
   194      spec:
   195        containers:
   196        - image: nginx
   197          name: nginx
   198  `)
   199  }
   200  
   201  // Should be able to refer to a resource with either its
   202  // original GVKN or its current one
   203  func TestPatchOriginalName(t *testing.T) {
   204  	th := kusttest_test.MakeHarness(t)
   205  	th.WriteF("base/deployment.yaml", `
   206  apiVersion: v1
   207  kind: Deployment
   208  metadata:
   209    name: old-name
   210  spec:
   211    template:
   212      spec:
   213        containers:
   214          - name: nginx
   215            image: nginx
   216  `)
   217  	th.WriteF("base/patch.yaml", `
   218  apiVersion: v1
   219  kind: Deployment
   220  metadata:
   221    name: new-name
   222  `)
   223  	th.WriteK("base", `
   224  resources:
   225  - deployment.yaml
   226  patches:
   227  - path: patch.yaml
   228    target:
   229      kind: Deployment
   230    options:
   231      allowNameChange: true
   232  `)
   233  	th.WriteK("overlay", `
   234  resources:
   235  - ../base
   236  patchesStrategicMerge:
   237  - depPatch.yaml
   238  `)
   239  	th.WriteF("overlay/depPatch.yaml", `
   240  apiVersion: v1
   241  kind: Deployment
   242  metadata:
   243    name: old-name
   244  spec:
   245    replicas: 999
   246  `)
   247  	options := th.MakeDefaultOptions()
   248  	m := th.Run("overlay", options)
   249  	th.AssertActualEqualsExpected(m, `
   250  apiVersion: v1
   251  kind: Deployment
   252  metadata:
   253    name: new-name
   254  spec:
   255    replicas: 999
   256    template:
   257      spec:
   258        containers:
   259        - image: nginx
   260          name: nginx
   261  `)
   262  }
   263  
   264  func TestPatchNewName(t *testing.T) {
   265  	th := kusttest_test.MakeHarness(t)
   266  	th.WriteF("base/deployment.yaml", `
   267  apiVersion: v1
   268  kind: Deployment
   269  metadata:
   270    name: old-name
   271  spec:
   272    template:
   273      spec:
   274        containers:
   275          - name: nginx
   276            image: nginx
   277  `)
   278  	th.WriteF("base/patch.yaml", `
   279  apiVersion: v1
   280  kind: Deployment
   281  metadata:
   282    name: new-name
   283  `)
   284  	th.WriteK("base", `
   285  resources:
   286  - deployment.yaml
   287  patches:
   288  - path: patch.yaml
   289    target:
   290      kind: Deployment
   291    options:
   292      allowNameChange: true
   293  `)
   294  	th.WriteK("overlay", `
   295  resources:
   296  - ../base
   297  patchesStrategicMerge:
   298  - depPatch.yaml
   299  `)
   300  	th.WriteF("overlay/depPatch.yaml", `
   301  apiVersion: v1
   302  kind: Deployment
   303  metadata:
   304    name: new-name
   305  spec:
   306    replicas: 999
   307  `)
   308  	options := th.MakeDefaultOptions()
   309  	m := th.Run("overlay", options)
   310  	th.AssertActualEqualsExpected(m, `
   311  apiVersion: v1
   312  kind: Deployment
   313  metadata:
   314    name: new-name
   315  spec:
   316    replicas: 999
   317    template:
   318      spec:
   319        containers:
   320        - image: nginx
   321          name: nginx
   322  `)
   323  }
   324  
   325  func TestPatchOriginalNameAndKind(t *testing.T) {
   326  	th := kusttest_test.MakeHarness(t)
   327  	th.WriteF("base/deployment.yaml", `
   328  apiVersion: v1
   329  kind: Deployment
   330  metadata:
   331    name: old-name
   332  spec:
   333    template:
   334      spec:
   335        containers:
   336          - name: nginx
   337            image: nginx
   338  `)
   339  	th.WriteF("base/patch.yaml", `
   340  apiVersion: v1
   341  kind: StatefulSet
   342  metadata:
   343    name: new-name
   344  `)
   345  	th.WriteK("base", `
   346  resources:
   347  - deployment.yaml
   348  patches:
   349  - path: patch.yaml
   350    target:
   351      kind: Deployment
   352    options:
   353      allowNameChange: true
   354      allowKindChange: true
   355  `)
   356  	th.WriteK("overlay", `
   357  resources:
   358  - ../base
   359  patchesStrategicMerge:
   360  - depPatch.yaml
   361  `)
   362  	th.WriteF("overlay/depPatch.yaml", `
   363  apiVersion: v1
   364  kind: Deployment
   365  metadata:
   366    name: old-name
   367  spec:
   368    replicas: 999
   369  `)
   370  	options := th.MakeDefaultOptions()
   371  	m := th.Run("overlay", options)
   372  	th.AssertActualEqualsExpected(m, `
   373  apiVersion: v1
   374  kind: StatefulSet
   375  metadata:
   376    name: new-name
   377  spec:
   378    replicas: 999
   379    template:
   380      spec:
   381        containers:
   382        - image: nginx
   383          name: nginx
   384  `)
   385  }
   386  
   387  func TestPatchNewNameAndKind(t *testing.T) {
   388  	th := kusttest_test.MakeHarness(t)
   389  	th.WriteF("base/deployment.yaml", `
   390  apiVersion: v1
   391  kind: Deployment
   392  metadata:
   393    name: old-name
   394  spec:
   395    template:
   396      spec:
   397        containers:
   398          - name: nginx
   399            image: nginx
   400  `)
   401  	th.WriteF("base/patch.yaml", `
   402  apiVersion: v1
   403  kind: StatefulSet
   404  metadata:
   405    name: new-name
   406  `)
   407  	th.WriteK("base", `
   408  resources:
   409  - deployment.yaml
   410  patches:
   411  - path: patch.yaml
   412    target:
   413      kind: Deployment
   414    options:
   415      allowNameChange: true
   416      allowKindChange: true
   417  `)
   418  	th.WriteK("overlay", `
   419  resources:
   420  - ../base
   421  patchesStrategicMerge:
   422  - depPatch.yaml
   423  `)
   424  	th.WriteF("overlay/depPatch.yaml", `
   425  apiVersion: v1
   426  kind: StatefulSet
   427  metadata:
   428    name: new-name
   429  spec:
   430    replicas: 999
   431  `)
   432  	options := th.MakeDefaultOptions()
   433  	m := th.Run("overlay", options)
   434  	th.AssertActualEqualsExpected(m, `
   435  apiVersion: v1
   436  kind: StatefulSet
   437  metadata:
   438    name: new-name
   439  spec:
   440    replicas: 999
   441    template:
   442      spec:
   443        containers:
   444        - image: nginx
   445          name: nginx
   446  `)
   447  }
   448  
   449  // Use original name, but new kind
   450  // Should fail, even after #3280 is done, because this ID is invalid
   451  func TestPatchOriginalNameAndNewKind(t *testing.T) {
   452  	th := kusttest_test.MakeHarness(t)
   453  	th.WriteF("base/deployment.yaml", `
   454  apiVersion: v1
   455  kind: Deployment
   456  metadata:
   457    name: old-name
   458  spec:
   459    template:
   460      spec:
   461        containers:
   462          - name: nginx
   463            image: nginx
   464  `)
   465  	th.WriteF("base/patch.yaml", `
   466  apiVersion: v1
   467  kind: StatefulSet
   468  metadata:
   469    name: new-name
   470  `)
   471  	th.WriteK("base", `
   472  resources:
   473  - deployment.yaml
   474  patches:
   475  - path: patch.yaml
   476    target:
   477      kind: Deployment
   478    options:
   479      allowNameChange: true
   480      allowKindChange: true
   481  `)
   482  	th.WriteK("overlay", `
   483  resources:
   484  - ../base
   485  patchesStrategicMerge:
   486  - depPatch.yaml
   487  `)
   488  	th.WriteF("overlay/depPatch.yaml", `
   489  apiVersion: v1
   490  kind: Deployment
   491  metadata:
   492    name: new-name
   493  spec:
   494    replicas: 999
   495  `)
   496  	options := th.MakeDefaultOptions()
   497  	// depPatch cannot find target with kind `Deployment` and name `new-name`
   498  	// because the resource never had this GVKN
   499  	require.Error(t, th.RunWithErr("overlay", options))
   500  }
   501  
   502  // Here is a structure of a kustomization of two components, component1
   503  // and component2, that both use a shared deployment definition, which
   504  // component2 adjusts by changing the kind via a patch. This test case
   505  // checks that it does not have a conflicting definition.
   506  // Currently documents broken behavior.
   507  //
   508  //                   root
   509  //              /            \
   510  //  component1/overlay  component2/overlay
   511  //             |              |
   512  //    component1/base    component2/base
   513  //              \            /
   514  //                   base
   515  //
   516  // This is the directory layout:
   517  //
   518  // ├── component1
   519  // │   ├── base
   520  // │   │   └── kustomization.yaml
   521  // │   └── overlay
   522  // │       └── kustomization.yaml
   523  // ├── component2
   524  // │   ├── base
   525  // │   │   └── kustomization.yaml
   526  // │   └── overlay
   527  // │       └── kustomization.yaml
   528  // ├── shared
   529  // │   ├── kustomization.yaml
   530  // │   └── deployment.yaml
   531  // ├── kustomization.yaml
   532  
   533  func TestBaseReuseNameAndKindConflict(t *testing.T) {
   534  	th := kusttest_test.MakeHarness(t)
   535  	th.WriteK("shared", `
   536  resources:
   537    - deployment.yaml
   538  `)
   539  	th.WriteF("shared/deployment.yaml", `
   540  apiVersion: v1
   541  kind: Deployment
   542  metadata:
   543    name: my-deploy
   544  spec:
   545    template:
   546      spec:
   547        containers:
   548          - name: nginx
   549            image: nginx
   550  `)
   551  
   552  	th.WriteK("component1/base", `
   553  resources:
   554    - ../../shared
   555  `)
   556  	th.WriteK("component1/overlay", `
   557  resources:
   558    - ../base
   559  namePrefix: overlay-
   560  `)
   561  
   562  	th.WriteK("component2/base", `
   563  resources:
   564    - ../../shared
   565  patches:
   566  - path: patch.yaml
   567    target:
   568      kind: Deployment
   569      name: my-deploy
   570    options:
   571      allowNameChange: true
   572      allowKindChange: true
   573  `)
   574  	th.WriteF("component2/base/patch.yaml", `
   575  apiVersion: v1
   576  kind: StatefulSet
   577  metadata:
   578    name: my-stateful-set
   579  `)
   580  	th.WriteK("component2/overlay", `
   581  resources:
   582    - ../base
   583  namePrefix: overlay-
   584  `)
   585  
   586  	th.WriteK(".", `
   587  resources:
   588    - component1/overlay
   589    - component2/overlay
   590  `)
   591  	options := th.MakeDefaultOptions()
   592  	m := th.Run(".", options)
   593  	th.AssertActualEqualsExpected(m, `
   594  apiVersion: v1
   595  kind: Deployment
   596  metadata:
   597    name: overlay-my-deploy
   598  spec:
   599    template:
   600      spec:
   601        containers:
   602        - image: nginx
   603          name: nginx
   604  ---
   605  apiVersion: v1
   606  kind: StatefulSet
   607  metadata:
   608    name: overlay-my-stateful-set
   609  spec:
   610    template:
   611      spec:
   612        containers:
   613        - image: nginx
   614          name: nginx
   615  `)
   616  }
   617  
   618  func TestNameReferenceAfterGvknChange(t *testing.T) {
   619  	th := kusttest_test.MakeHarness(t)
   620  	th.WriteF("configMap.yaml", `
   621  apiVersion: v1
   622  kind: ConfigMap
   623  metadata:
   624    name: old-name
   625  `)
   626  	th.WriteF("patch.yaml", `
   627  apiVersion: v1
   628  kind: ConfigMap
   629  metadata:
   630    name: new-name
   631  `)
   632  	th.WriteF("deployment.yaml", `
   633  apiVersion: v1
   634  kind: Deployment
   635  metadata:
   636    name: deploy
   637  spec:
   638    template:
   639      spec:
   640        containers:
   641        - env:
   642          - valueFrom:
   643              configMapKeyRef:
   644                name: old-name
   645                key: somekey
   646          envFrom:
   647          - configMapRef:
   648              name: old-name
   649              key: somekey
   650  `)
   651  	th.WriteK(".", `
   652  resources:
   653  - configMap.yaml
   654  - deployment.yaml
   655  patches:
   656  - path: patch.yaml
   657    target:
   658      kind: ConfigMap
   659    options:
   660      allowNameChange: true
   661  `)
   662  	m := th.Run(".", th.MakeDefaultOptions())
   663  	th.AssertActualEqualsExpected(m, `
   664  apiVersion: v1
   665  kind: ConfigMap
   666  metadata:
   667    name: new-name
   668  ---
   669  apiVersion: v1
   670  kind: Deployment
   671  metadata:
   672    name: deploy
   673  spec:
   674    template:
   675      spec:
   676        containers:
   677        - env:
   678          - valueFrom:
   679              configMapKeyRef:
   680                key: somekey
   681                name: new-name
   682          envFrom:
   683          - configMapRef:
   684              key: somekey
   685              name: new-name
   686  `)
   687  }
   688  
   689  func TestNameReferenceAfterJsonPatch(t *testing.T) {
   690  	th := kusttest_test.MakeHarness(t)
   691  	th.WriteF("resources.yaml", `
   692  apiVersion: v1
   693  data:
   694    bar: bar
   695  kind: ConfigMap
   696  metadata:
   697    name: cm
   698  ---
   699  apiVersion: apps/v1
   700  kind: StatefulSet
   701  metadata:
   702    name: foo
   703  spec:
   704    selector:
   705      matchLabels:
   706        foo: foo
   707    template:
   708      metadata:
   709        labels:
   710          foo: foo
   711      spec:
   712        containers:
   713        - name: foo
   714          image: example
   715          volumeMounts:
   716          - mountPath: /path
   717            name: myvol
   718        volumes:
   719        - configMap:
   720            name: cm
   721          name: myvol
   722  `)
   723  	th.WriteK(".", `
   724  namePrefix: foo-
   725  resources:
   726  - resources.yaml
   727  patches:
   728  - target:
   729      group: apps
   730      version: v1
   731      name: foo
   732    patch: |
   733      - op: replace
   734        path: /kind
   735        value: Deployment
   736  `)
   737  	m := th.Run(".", th.MakeDefaultOptions())
   738  	th.AssertActualEqualsExpected(m, `apiVersion: v1
   739  data:
   740    bar: bar
   741  kind: ConfigMap
   742  metadata:
   743    name: foo-cm
   744  ---
   745  apiVersion: apps/v1
   746  kind: Deployment
   747  metadata:
   748    name: foo-foo
   749  spec:
   750    selector:
   751      matchLabels:
   752        foo: foo
   753    template:
   754      metadata:
   755        labels:
   756          foo: foo
   757      spec:
   758        containers:
   759        - image: example
   760          name: foo
   761          volumeMounts:
   762          - mountPath: /path
   763            name: myvol
   764        volumes:
   765        - configMap:
   766            name: foo-cm
   767          name: myvol
   768  `)
   769  }
   770  
   771  func TestNameReferenceAfterJsonPatchConfigMapGenerator(t *testing.T) {
   772  	th := kusttest_test.MakeHarness(t)
   773  	th.WriteF("statefulset.yaml", `
   774  apiVersion: apps/v1
   775  kind: StatefulSet
   776  metadata:
   777    name: foo
   778  spec:
   779    selector:
   780      matchLabels:
   781        foo: foo
   782    template:
   783      metadata:
   784        labels:
   785          foo: foo
   786      spec:
   787        containers:
   788        - name: foo
   789          image: example
   790          volumeMounts:
   791          - mountPath: /path
   792            name: myvol
   793        volumes:
   794        - configMap:
   795            name: cm
   796          name: myvol
   797  `)
   798  	th.WriteK(".", `
   799  resources:
   800  - statefulset.yaml
   801  patches:
   802  - target:
   803      group: apps
   804      version: v1
   805      name: foo
   806    patch: |
   807      - op: replace
   808        path: /kind
   809        value: Deployment
   810  configMapGenerator:
   811  - name: cm
   812    literals:
   813    - bar=bar
   814  `)
   815  	m := th.Run(".", th.MakeDefaultOptions())
   816  	th.AssertActualEqualsExpected(m, `apiVersion: apps/v1
   817  kind: Deployment
   818  metadata:
   819    name: foo
   820  spec:
   821    selector:
   822      matchLabels:
   823        foo: foo
   824    template:
   825      metadata:
   826        labels:
   827          foo: foo
   828      spec:
   829        containers:
   830        - image: example
   831          name: foo
   832          volumeMounts:
   833          - mountPath: /path
   834            name: myvol
   835        volumes:
   836        - configMap:
   837            name: cm-8hm8224gfd
   838          name: myvol
   839  ---
   840  apiVersion: v1
   841  data:
   842    bar: bar
   843  kind: ConfigMap
   844  metadata:
   845    name: cm-8hm8224gfd
   846  `)
   847  }
   848  

View as plain text