...

Source file src/sigs.k8s.io/kustomize/api/filters/replacement/replacement_test.go

Documentation: sigs.k8s.io/kustomize/api/filters/replacement

     1  // Copyright 2021 The Kubernetes Authors.
     2  // SPDX-License-Identifier: Apache-2.0
     3  
     4  package replacement
     5  
     6  import (
     7  	"strings"
     8  	"testing"
     9  
    10  	"github.com/stretchr/testify/assert"
    11  	filtertest "sigs.k8s.io/kustomize/api/testutils/filtertest"
    12  	"sigs.k8s.io/kustomize/kyaml/yaml"
    13  )
    14  
    15  func TestFilter(t *testing.T) {
    16  	testCases := map[string]struct {
    17  		input        string
    18  		replacements string
    19  		expected     string
    20  		expectedErr  string
    21  	}{
    22  		"simple": {
    23  			input: `apiVersion: v1
    24  kind: Deployment
    25  metadata:
    26    name: deploy
    27  spec:
    28    template:
    29      spec:
    30        containers:
    31        - image: nginx:1.7.9
    32          name: nginx-tagged
    33        - image: postgres:1.8.0
    34          name: postgresdb
    35  `,
    36  			replacements: `replacements:
    37  - source:
    38      kind: Deployment
    39      name: deploy
    40      fieldPath: spec.template.spec.containers.0.image
    41    targets:
    42    - select:
    43        kind: Deployment
    44        name: deploy
    45      fieldPaths:
    46      - spec.template.spec.containers.1.image
    47  `,
    48  			expected: `apiVersion: v1
    49  kind: Deployment
    50  metadata:
    51    name: deploy
    52  spec:
    53    template:
    54      spec:
    55        containers:
    56        - image: nginx:1.7.9
    57          name: nginx-tagged
    58        - image: nginx:1.7.9
    59          name: postgresdb
    60  `,
    61  		},
    62  		"complex type": {
    63  			input: `apiVersion: v1
    64  kind: Pod
    65  metadata:
    66    name: pod
    67  spec:
    68    containers:
    69    - image: busybox
    70      name: myapp-container
    71  ---
    72  apiVersion: apps/v1
    73  kind: Deployment
    74  metadata:
    75    name: deploy2
    76  spec:
    77    template:
    78      spec:
    79        containers: {}
    80  ---
    81  apiVersion: apps/v1
    82  kind: Deployment
    83  metadata:
    84    name: deploy3
    85  spec:
    86    template:
    87      spec:
    88        containers: {}
    89  `,
    90  			replacements: `replacements:
    91  - source:
    92      kind: Pod
    93      name: pod
    94      fieldPath: spec.containers
    95    targets:
    96    - select:
    97        kind: Deployment
    98      fieldPaths:
    99      - spec.template.spec.containers
   100  `,
   101  			expected: `apiVersion: v1
   102  kind: Pod
   103  metadata:
   104    name: pod
   105  spec:
   106    containers:
   107    - image: busybox
   108      name: myapp-container
   109  ---
   110  apiVersion: apps/v1
   111  kind: Deployment
   112  metadata:
   113    name: deploy2
   114  spec:
   115    template:
   116      spec:
   117        containers:
   118        - image: busybox
   119          name: myapp-container
   120  ---
   121  apiVersion: apps/v1
   122  kind: Deployment
   123  metadata:
   124    name: deploy3
   125  spec:
   126    template:
   127      spec:
   128        containers:
   129        - image: busybox
   130          name: myapp-container
   131  `,
   132  		},
   133  		"from ConfigMap": {
   134  			input: `apiVersion: apps/v1
   135  kind: Deployment
   136  metadata:
   137    name: deploy
   138    labels:
   139      foo: bar
   140  spec:
   141    template:
   142      metadata:
   143        labels:
   144          foo: bar
   145      spec:
   146        containers:
   147          - name: command-demo-container
   148            image: debian
   149            command: ["printenv"]
   150            args:
   151              - HOSTNAME
   152              - PORT
   153          - name: busybox
   154            image: busybox:latest
   155            args:
   156              - echo
   157              - HOSTNAME
   158              - PORT
   159  ---
   160  apiVersion: v1
   161  kind: ConfigMap
   162  metadata:
   163    name: cm
   164  data:
   165    HOSTNAME: example.com
   166    PORT: 8080
   167  `,
   168  			replacements: `replacements:
   169  - source:
   170      kind: ConfigMap
   171      name: cm
   172      fieldPath: data.HOSTNAME
   173    targets:
   174    - select:
   175        kind: Deployment
   176      fieldPaths:
   177      - spec.template.spec.containers.0.args.0
   178      - spec.template.spec.containers.1.args.1
   179  - source:
   180      kind: ConfigMap
   181      name: cm
   182      fieldPath: data.PORT
   183    targets:
   184    - select:
   185        kind: Deployment
   186      fieldPaths:
   187      - spec.template.spec.containers.0.args.1
   188      - spec.template.spec.containers.1.args.2
   189  `,
   190  			expected: `apiVersion: apps/v1
   191  kind: Deployment
   192  metadata:
   193    name: deploy
   194    labels:
   195      foo: bar
   196  spec:
   197    template:
   198      metadata:
   199        labels:
   200          foo: bar
   201      spec:
   202        containers:
   203        - name: command-demo-container
   204          image: debian
   205          command: ["printenv"]
   206          args:
   207          - example.com
   208          - "8080"
   209        - name: busybox
   210          image: busybox:latest
   211          args:
   212          - echo
   213          - example.com
   214          - "8080"
   215  ---
   216  apiVersion: v1
   217  kind: ConfigMap
   218  metadata:
   219    name: cm
   220  data:
   221    HOSTNAME: example.com
   222    PORT: 8080
   223  `,
   224  		},
   225  		"multiple matches for source select": {
   226  			input: `apiVersion: v1
   227  kind: Deployment
   228  metadata:
   229    name: deploy1
   230  spec:
   231    template:
   232      spec:
   233        containers:
   234        - image: nginx:1.7.9
   235          name: nginx-tagged
   236        - image: postgres:1.8.0
   237          name: postgresdb
   238  ---
   239  apiVersion: v1
   240  kind: Deployment
   241  metadata:
   242    name: deploy2
   243  spec:
   244    template:
   245      spec:
   246        containers:
   247        - image: nginx:1.7.9
   248          name: nginx-tagged
   249        - image: postgres:1.8.0
   250          name: postgresdb
   251  ---
   252  apiVersion: v1
   253  kind: Deployment
   254  metadata:
   255    name: deploy3
   256  spec:
   257    template:
   258      spec:
   259        containers:
   260        - image: nginx:1.7.9
   261          name: nginx-tagged
   262        - image: postgres:1.8.0
   263          name: postgresdb
   264  `,
   265  			replacements: `replacements:
   266  - source:
   267      kind: Deployment
   268    targets:
   269    - select:
   270        kind: Deployment
   271  `,
   272  			expectedErr: "multiple matches for selector Deployment.[noVer].[noGrp]/[noName].[noNs]",
   273  		},
   274  		"replacement has no source": {
   275  			input: `apiVersion: v1
   276  kind: Deployment
   277  metadata:
   278    name: deploy
   279  spec:
   280    template:
   281      spec:
   282        containers:
   283        - image: nginx:1.7.9
   284          name: nginx-tagged
   285        - image: postgres:1.8.0
   286          name: postgresdb
   287  `,
   288  			replacements: `replacements:
   289  - targets:
   290    - select:
   291        kind: Deployment
   292  `,
   293  			expectedErr: "replacements must specify a source and at least one target",
   294  		},
   295  		"field paths with key-value pairs": {
   296  			input: `apiVersion: v1
   297  kind: Deployment
   298  metadata:
   299    name: deploy1
   300  spec:
   301    template:
   302      spec:
   303        containers:
   304        - image: nginx:1.7.9
   305          name: nginx-tagged
   306        - image: postgres:1.8.0
   307          name: postgresdb
   308  ---
   309  apiVersion: v1
   310  kind: Deployment
   311  metadata:
   312    name: deploy2
   313  spec:
   314    template:
   315      spec:
   316        containers:
   317        - image: nginx:1.7.9
   318          name: nginx-tagged
   319        - image: postgres:1.8.0
   320          name: postgresdb
   321  `,
   322  			replacements: `replacements:
   323  - source:
   324      kind: Deployment
   325      name: deploy2
   326      fieldPath: spec.template.spec.containers.[name=nginx-tagged].image
   327    targets:
   328    - select:
   329        kind: Deployment
   330        name: deploy1
   331      fieldPaths:
   332      - spec.template.spec.containers.[name=postgresdb].image
   333  `,
   334  			expected: `apiVersion: v1
   335  kind: Deployment
   336  metadata:
   337    name: deploy1
   338  spec:
   339    template:
   340      spec:
   341        containers:
   342        - image: nginx:1.7.9
   343          name: nginx-tagged
   344        - image: nginx:1.7.9
   345          name: postgresdb
   346  ---
   347  apiVersion: v1
   348  kind: Deployment
   349  metadata:
   350    name: deploy2
   351  spec:
   352    template:
   353      spec:
   354        containers:
   355        - image: nginx:1.7.9
   356          name: nginx-tagged
   357        - image: postgres:1.8.0
   358          name: postgresdb
   359  `,
   360  		},
   361  		"select by group and version": {
   362  			input: `apiVersion: my-group-1/v1
   363  kind: Custom
   364  metadata:
   365    name: my-name
   366  spec:
   367    template:
   368      spec:
   369        containers:
   370        - image: nginx:1.7.9
   371          name: nginx-tagged
   372        - image: postgres:1.8.0
   373          name: postgresdb
   374  ---
   375  apiVersion: my-group-2/v2
   376  kind: Custom
   377  metadata:
   378    name: my-name
   379  spec:
   380    template:
   381      spec:
   382        containers:
   383        - image: nginx:1.7.9
   384          name: nginx-tagged
   385        - image: postgres:1.8.0
   386          name: postgresdb
   387  ---
   388  apiVersion: my-group-3/v3
   389  kind: Custom
   390  metadata:
   391    name: my-name
   392  spec:
   393    template:
   394      spec:
   395        containers:
   396        - image: nginx:1.7.9
   397          name: nginx-tagged
   398        - image: postgres:1.8.0
   399          name: postgresdb
   400  `,
   401  			replacements: `replacements:
   402  - source:
   403      group: my-group-2
   404      fieldPath: spec.template.spec.containers.0.image
   405    targets:
   406    - select:
   407        version: v3
   408      fieldPaths:
   409      - spec.template.spec.containers.1.image
   410  `,
   411  			expected: `apiVersion: my-group-1/v1
   412  kind: Custom
   413  metadata:
   414    name: my-name
   415  spec:
   416    template:
   417      spec:
   418        containers:
   419        - image: nginx:1.7.9
   420          name: nginx-tagged
   421        - image: postgres:1.8.0
   422          name: postgresdb
   423  ---
   424  apiVersion: my-group-2/v2
   425  kind: Custom
   426  metadata:
   427    name: my-name
   428  spec:
   429    template:
   430      spec:
   431        containers:
   432        - image: nginx:1.7.9
   433          name: nginx-tagged
   434        - image: postgres:1.8.0
   435          name: postgresdb
   436  ---
   437  apiVersion: my-group-3/v3
   438  kind: Custom
   439  metadata:
   440    name: my-name
   441  spec:
   442    template:
   443      spec:
   444        containers:
   445        - image: nginx:1.7.9
   446          name: nginx-tagged
   447        - image: nginx:1.7.9
   448          name: postgresdb
   449  `,
   450  		},
   451  		// regression test for missing metadata handling
   452  		"missing metadata": {
   453  			input: `spec:
   454    template:
   455      spec:
   456        containers:
   457        - image: nginx:1.7.9
   458          name: nginx-tagged
   459        - image: postgres:1.8.0
   460          name: postgresdb
   461  ---
   462  apiVersion: my-group/v1
   463  kind: Custom
   464  metadata:
   465    name: my-name-1
   466  spec:
   467    template:
   468      spec:
   469        containers:
   470        - image: nginx:1.7.9
   471          name: nginx-tagged
   472        - image: postgres:1.8.0
   473          name: postgresdb
   474  ---
   475  apiVersion: my-group/v1
   476  kind: Custom
   477  metadata:
   478    name: my-name-2
   479  spec:
   480    template:
   481      spec:
   482        containers:
   483        - image: nginx:1.7.9
   484          name: nginx-tagged
   485        - image: postgres:1.8.0
   486          name: postgresdb
   487  `,
   488  			replacements: `replacements:
   489  - source:
   490      name: my-name-1
   491      fieldPath: spec.template.spec.containers.0.image
   492    targets:
   493    - select:
   494        name: my-name-2
   495      fieldPaths:
   496      - spec.template.spec.containers.1.image
   497  `,
   498  			expected: `spec:
   499    template:
   500      spec:
   501        containers:
   502        - image: nginx:1.7.9
   503          name: nginx-tagged
   504        - image: postgres:1.8.0
   505          name: postgresdb
   506  ---
   507  apiVersion: my-group/v1
   508  kind: Custom
   509  metadata:
   510    name: my-name-1
   511  spec:
   512    template:
   513      spec:
   514        containers:
   515        - image: nginx:1.7.9
   516          name: nginx-tagged
   517        - image: postgres:1.8.0
   518          name: postgresdb
   519  ---
   520  apiVersion: my-group/v1
   521  kind: Custom
   522  metadata:
   523    name: my-name-2
   524  spec:
   525    template:
   526      spec:
   527        containers:
   528        - image: nginx:1.7.9
   529          name: nginx-tagged
   530        - image: nginx:1.7.9
   531          name: postgresdb
   532  `,
   533  		},
   534  		"reject 1": {
   535  			input: `apiVersion: v1
   536  kind: Deployment
   537  metadata:
   538    name: deploy1
   539  spec:
   540    template:
   541      spec:
   542        containers:
   543        - image: nginx:1.7.9
   544          name: nginx-tagged
   545        - image: postgres:1.8.0
   546          name: postgresdb
   547  ---
   548  apiVersion: v1
   549  kind: Deployment
   550  metadata:
   551    name: deploy2
   552  spec:
   553    template:
   554      spec:
   555        containers:
   556        - image: nginx:1.7.9
   557          name: nginx-tagged
   558        - image: postgres:1.8.0
   559          name: postgresdb
   560  ---
   561  apiVersion: v1
   562  kind: Deployment
   563  metadata:
   564    name: deploy3
   565  spec:
   566    template:
   567      spec:
   568        containers:
   569        - image: nginx:1.7.9
   570          name: nginx-tagged
   571        - image: postgres:1.8.0
   572          name: postgresdb
   573  `,
   574  			replacements: `replacements:
   575  - source:
   576      kind: Deployment
   577      name: deploy2
   578      fieldPath: spec.template.spec.containers.0.image
   579    targets:
   580    - select:
   581        kind: Deployment
   582      reject:
   583      - name: deploy2
   584      - name: deploy3
   585      fieldPaths:
   586      - spec.template.spec.containers.1.image
   587  `,
   588  			expected: `apiVersion: v1
   589  kind: Deployment
   590  metadata:
   591    name: deploy1
   592  spec:
   593    template:
   594      spec:
   595        containers:
   596        - image: nginx:1.7.9
   597          name: nginx-tagged
   598        - image: nginx:1.7.9
   599          name: postgresdb
   600  ---
   601  apiVersion: v1
   602  kind: Deployment
   603  metadata:
   604    name: deploy2
   605  spec:
   606    template:
   607      spec:
   608        containers:
   609        - image: nginx:1.7.9
   610          name: nginx-tagged
   611        - image: postgres:1.8.0
   612          name: postgresdb
   613  ---
   614  apiVersion: v1
   615  kind: Deployment
   616  metadata:
   617    name: deploy3
   618  spec:
   619    template:
   620      spec:
   621        containers:
   622        - image: nginx:1.7.9
   623          name: nginx-tagged
   624        - image: postgres:1.8.0
   625          name: postgresdb
   626  `,
   627  		},
   628  		"reject 2": {
   629  			input: `apiVersion: v1
   630  kind: Deployment
   631  metadata:
   632    name: my-name
   633  spec:
   634    template:
   635      spec:
   636        containers:
   637        - image: nginx:1.7.9
   638          name: nginx-tagged
   639        - image: postgres:1.8.0
   640          name: postgresdb
   641  ---
   642  apiVersion: v1
   643  kind: StatefulSet
   644  metadata:
   645    name: my-name
   646  spec:
   647    template:
   648      spec:
   649        containers:
   650        - image: nginx:1.7.9
   651          name: nginx-tagged
   652        - image: postgres:1.8.0
   653          name: postgresdb
   654  `,
   655  			replacements: `replacements:
   656  - source:
   657      kind: Deployment
   658      fieldPath: spec.template.spec.containers.0.image
   659    targets:
   660    - select:
   661        version: v1
   662      reject:
   663      - kind: Deployment
   664        name: my-name
   665      fieldPaths:
   666      - spec.template.spec.containers.1.image
   667  `,
   668  			expected: `apiVersion: v1
   669  kind: Deployment
   670  metadata:
   671    name: my-name
   672  spec:
   673    template:
   674      spec:
   675        containers:
   676        - image: nginx:1.7.9
   677          name: nginx-tagged
   678        - image: postgres:1.8.0
   679          name: postgresdb
   680  ---
   681  apiVersion: v1
   682  kind: StatefulSet
   683  metadata:
   684    name: my-name
   685  spec:
   686    template:
   687      spec:
   688        containers:
   689        - image: nginx:1.7.9
   690          name: nginx-tagged
   691        - image: nginx:1.7.9
   692          name: postgresdb
   693  `,
   694  		},
   695  		// the only difference in the inputs between this and the previous test
   696  		// is the dash before `name: my-name` on line 733
   697  		"reject 3": {
   698  			input: `apiVersion: v1
   699  kind: Deployment
   700  metadata:
   701    name: my-name
   702  spec:
   703    template:
   704      spec:
   705        containers:
   706        - image: nginx:1.7.9
   707          name: nginx-tagged
   708        - image: postgres:1.8.0
   709          name: postgresdb
   710  ---
   711  apiVersion: v1
   712  kind: StatefulSet
   713  metadata:
   714    name: my-name
   715  spec:
   716    template:
   717      spec:
   718        containers:
   719        - image: nginx:1.7.9
   720          name: nginx-tagged
   721        - image: postgres:1.8.0
   722          name: postgresdb
   723  `,
   724  			replacements: `replacements:
   725  - source:
   726      kind: Deployment
   727      fieldPath: spec.template.spec.containers.0.image
   728    targets:
   729    - select:
   730        version: v1
   731      reject:
   732      - kind: Deployment
   733      - name: my-name
   734      fieldPaths:
   735      - spec.template.spec.containers.1.image
   736  `,
   737  			expected: `apiVersion: v1
   738  kind: Deployment
   739  metadata:
   740    name: my-name
   741  spec:
   742    template:
   743      spec:
   744        containers:
   745        - image: nginx:1.7.9
   746          name: nginx-tagged
   747        - image: postgres:1.8.0
   748          name: postgresdb
   749  ---
   750  apiVersion: v1
   751  kind: StatefulSet
   752  metadata:
   753    name: my-name
   754  spec:
   755    template:
   756      spec:
   757        containers:
   758        - image: nginx:1.7.9
   759          name: nginx-tagged
   760        - image: postgres:1.8.0
   761          name: postgresdb
   762  `,
   763  		},
   764  		"partial string replacement - replace": {
   765  			input: `apiVersion: v1
   766  kind: Deployment
   767  metadata:
   768    name: deploy1
   769  spec:
   770    template:
   771      spec:
   772        containers:
   773        - image: nginx:1.7.9
   774          name: nginx-tagged
   775        - image: postgres:1.8.0
   776          name: postgresdb
   777  ---
   778  apiVersion: v1
   779  kind: Deployment
   780  metadata:
   781    name: deploy2
   782  spec:
   783    template:
   784      spec:
   785        containers:
   786        - image: nginx:1.7.9
   787          name: nginx-tagged
   788        - image: postgres:1.8.0
   789          name: postgresdb
   790  `,
   791  			replacements: `replacements:
   792  - source:
   793      kind: Deployment
   794      name: deploy2
   795      fieldPath: spec.template.spec.containers.0.image
   796      options:
   797        delimiter: ':'
   798    targets:
   799    - select:
   800        kind: Deployment
   801        name: deploy1
   802      fieldPaths:
   803      - spec.template.spec.containers.1.image
   804      options:
   805        delimiter: ':'
   806  `,
   807  			expected: `apiVersion: v1
   808  kind: Deployment
   809  metadata:
   810    name: deploy1
   811  spec:
   812    template:
   813      spec:
   814        containers:
   815        - image: nginx:1.7.9
   816          name: nginx-tagged
   817        - image: nginx:1.8.0
   818          name: postgresdb
   819  ---
   820  apiVersion: v1
   821  kind: Deployment
   822  metadata:
   823    name: deploy2
   824  spec:
   825    template:
   826      spec:
   827        containers:
   828        - image: nginx:1.7.9
   829          name: nginx-tagged
   830        - image: postgres:1.8.0
   831          name: postgresdb
   832  `,
   833  		},
   834  		"partial string replacement - prefix": {
   835  			input: `apiVersion: v1
   836  kind: Pod
   837  metadata:
   838    name: pod1
   839  spec:
   840    volumes:
   841    - projected:
   842        sources:
   843        - configMap:
   844            name: myconfigmap
   845            items:
   846            - key: config
   847              path: my/group
   848  ---
   849  apiVersion: v1
   850  kind: Pod
   851  metadata:
   852    name: pod2
   853  spec:
   854    volumes:
   855    - projected:
   856        sources:
   857        - configMap:
   858            name: myconfigmap
   859            items:
   860            - key: config
   861              path: group/config
   862  `,
   863  			replacements: `replacements:
   864  - source:
   865      kind: Pod
   866      name: pod1
   867      fieldPath: spec.volumes.0.projected.sources.0.configMap.items.0.path
   868      options:
   869        delimiter: '/'
   870        index: 0
   871    targets:
   872    - select:
   873        kind: Pod
   874        name: pod2
   875      fieldPaths:
   876      - spec.volumes.0.projected.sources.0.configMap.items.0.path
   877      options:
   878        delimiter: '/'
   879        index: -1
   880  `,
   881  			expected: `apiVersion: v1
   882  kind: Pod
   883  metadata:
   884    name: pod1
   885  spec:
   886    volumes:
   887    - projected:
   888        sources:
   889        - configMap:
   890            name: myconfigmap
   891            items:
   892            - key: config
   893              path: my/group
   894  ---
   895  apiVersion: v1
   896  kind: Pod
   897  metadata:
   898    name: pod2
   899  spec:
   900    volumes:
   901    - projected:
   902        sources:
   903        - configMap:
   904            name: myconfigmap
   905            items:
   906            - key: config
   907              path: my/group/config
   908  `,
   909  		},
   910  		"partial string replacement - suffix": {
   911  			input: `apiVersion: v1
   912  kind: Pod
   913  metadata:
   914    name: pod1
   915  spec:
   916    volumes:
   917    - projected:
   918        sources:
   919        - configMap:
   920            name: myconfigmap
   921            items:
   922            - key: config
   923              path: my/group
   924  ---
   925  apiVersion: v1
   926  kind: Pod
   927  metadata:
   928    name: pod2
   929  spec:
   930    volumes:
   931    - projected:
   932        sources:
   933        - configMap:
   934            name: myconfigmap
   935            items:
   936            - key: config
   937              path: group/config
   938  `,
   939  			replacements: `replacements:
   940  - source:
   941      kind: Pod
   942      name: pod2
   943      fieldPath: spec.volumes.0.projected.sources.0.configMap.items.0.path
   944      options:
   945        delimiter: '/'
   946        index: 1
   947    targets:
   948    - select:
   949        kind: Pod
   950        name: pod1
   951      fieldPaths:
   952      - spec.volumes.0.projected.sources.0.configMap.items.0.path
   953      options:
   954        delimiter: '/'
   955        index: 2
   956  `,
   957  			expected: `apiVersion: v1
   958  kind: Pod
   959  metadata:
   960    name: pod1
   961  spec:
   962    volumes:
   963    - projected:
   964        sources:
   965        - configMap:
   966            name: myconfigmap
   967            items:
   968            - key: config
   969              path: my/group/config
   970  ---
   971  apiVersion: v1
   972  kind: Pod
   973  metadata:
   974    name: pod2
   975  spec:
   976    volumes:
   977    - projected:
   978        sources:
   979        - configMap:
   980            name: myconfigmap
   981            items:
   982            - key: config
   983              path: group/config
   984  `,
   985  		},
   986  		"partial string replacement - last element": {
   987  			input: `apiVersion: v1
   988  kind: Pod
   989  metadata:
   990    name: pod1
   991  spec:
   992    volumes:
   993    - projected:
   994        sources:
   995        - configMap:
   996            name: myconfigmap
   997            items:
   998            - key: config
   999              path: my/group1
  1000  ---
  1001  apiVersion: v1
  1002  kind: Pod
  1003  metadata:
  1004    name: pod2
  1005  spec:
  1006    volumes:
  1007    - projected:
  1008        sources:
  1009        - configMap:
  1010            name: myconfigmap
  1011            items:
  1012            - key: config
  1013              path: group2
  1014  `,
  1015  			replacements: `replacements:
  1016  - source:
  1017      kind: Pod
  1018      name: pod2
  1019      fieldPath: spec.volumes.0.projected.sources.0.configMap.items.0.path
  1020      options:
  1021        delimiter: '/'
  1022        index: 0
  1023    targets:
  1024    - select:
  1025        kind: Pod
  1026        name: pod1
  1027      fieldPaths:
  1028      - spec.volumes.0.projected.sources.0.configMap.items.0.path
  1029      options:
  1030        delimiter: '/'
  1031        index: 1
  1032  `,
  1033  			expected: `apiVersion: v1
  1034  kind: Pod
  1035  metadata:
  1036    name: pod1
  1037  spec:
  1038    volumes:
  1039    - projected:
  1040        sources:
  1041        - configMap:
  1042            name: myconfigmap
  1043            items:
  1044            - key: config
  1045              path: my/group2
  1046  ---
  1047  apiVersion: v1
  1048  kind: Pod
  1049  metadata:
  1050    name: pod2
  1051  spec:
  1052    volumes:
  1053    - projected:
  1054        sources:
  1055        - configMap:
  1056            name: myconfigmap
  1057            items:
  1058            - key: config
  1059              path: group2
  1060  `,
  1061  		},
  1062  		"partial string replacement - first element": {
  1063  			input: `apiVersion: v1
  1064  kind: Pod
  1065  metadata:
  1066    name: pod1
  1067  spec:
  1068    volumes:
  1069    - projected:
  1070        sources:
  1071        - configMap:
  1072            name: myconfigmap
  1073            items:
  1074            - key: config
  1075              path: group1/config
  1076  ---
  1077  apiVersion: v1
  1078  kind: Pod
  1079  metadata:
  1080    name: pod2
  1081  spec:
  1082    volumes:
  1083    - projected:
  1084        sources:
  1085        - configMap:
  1086            name: myconfigmap
  1087            items:
  1088            - key: config
  1089              path: group2
  1090  `,
  1091  			replacements: `replacements:
  1092  - source:
  1093      kind: Pod
  1094      name: pod2
  1095      fieldPath: spec.volumes.0.projected.sources.0.configMap.items.0.path
  1096      options:
  1097        delimiter: '/'
  1098        index: 0
  1099    targets:
  1100    - select:
  1101        kind: Pod
  1102        name: pod1
  1103      fieldPaths:
  1104      - spec.volumes.0.projected.sources.0.configMap.items.0.path
  1105      options:
  1106        delimiter: '/'
  1107        index: 0
  1108  `,
  1109  			expected: `apiVersion: v1
  1110  kind: Pod
  1111  metadata:
  1112    name: pod1
  1113  spec:
  1114    volumes:
  1115    - projected:
  1116        sources:
  1117        - configMap:
  1118            name: myconfigmap
  1119            items:
  1120            - key: config
  1121              path: group2/config
  1122  ---
  1123  apiVersion: v1
  1124  kind: Pod
  1125  metadata:
  1126    name: pod2
  1127  spec:
  1128    volumes:
  1129    - projected:
  1130        sources:
  1131        - configMap:
  1132            name: myconfigmap
  1133            items:
  1134            - key: config
  1135              path: group2
  1136  `,
  1137  		},
  1138  		"options.index out of bounds": {
  1139  			input: `apiVersion: v1
  1140  kind: Pod
  1141  metadata:
  1142    name: pod1
  1143  spec:
  1144    volumes:
  1145    - projected:
  1146        sources:
  1147        - configMap:
  1148            name: myconfigmap
  1149            items:
  1150            - key: config
  1151              path: my/group1
  1152  ---
  1153  apiVersion: v1
  1154  kind: Pod
  1155  metadata:
  1156    name: pod2
  1157  spec:
  1158    volumes:
  1159    - projected:
  1160        sources:
  1161        - configMap:
  1162            name: myconfigmap
  1163            items:
  1164            - key: config
  1165              path: group2
  1166  `,
  1167  			replacements: `replacements:
  1168  - source:
  1169      kind: Pod
  1170      name: pod2
  1171      fieldPath: spec.volumes.0.projected.sources.0.configMap.items.0.path
  1172      options:
  1173        delimiter: '/'
  1174        index: -1
  1175    targets:
  1176    - select:
  1177        kind: Pod
  1178        name: pod1
  1179      fieldPaths:
  1180      - spec.volumes.0.projected.sources.0.configMap.items.0.path
  1181      options:
  1182        delimiter: '/'
  1183        index: 1
  1184  `,
  1185  			expectedErr: "options.index -1 is out of bounds for value group2",
  1186  		},
  1187  		"create": {
  1188  			input: `apiVersion: v1
  1189  kind: Pod
  1190  metadata:
  1191    name: pod
  1192  spec:
  1193    containers:
  1194    - image: busybox
  1195      name: myapp-container
  1196  ---
  1197  apiVersion: apps/v1
  1198  kind: Deployment
  1199  metadata:
  1200    name: deploy1
  1201  `,
  1202  			replacements: `replacements:
  1203  - source:
  1204      kind: Pod
  1205      name: pod
  1206      fieldPath: spec.containers
  1207    targets:
  1208    - select:
  1209        name: deploy1
  1210      fieldPaths:
  1211      - spec.template.spec.containers
  1212      options:
  1213        create: true
  1214  `,
  1215  			expected: `apiVersion: v1
  1216  kind: Pod
  1217  metadata:
  1218    name: pod
  1219  spec:
  1220    containers:
  1221    - image: busybox
  1222      name: myapp-container
  1223  ---
  1224  apiVersion: apps/v1
  1225  kind: Deployment
  1226  metadata:
  1227    name: deploy1
  1228  spec:
  1229    template:
  1230      spec:
  1231        containers:
  1232        - image: busybox
  1233          name: myapp-container
  1234  `,
  1235  		},
  1236  		"complex type with delimiter in source": {
  1237  			input: `apiVersion: v1
  1238  kind: Pod
  1239  metadata:
  1240    name: pod
  1241  spec:
  1242    containers:
  1243    - image: busybox
  1244      name: myapp-container
  1245  ---
  1246  apiVersion: apps/v1
  1247  kind: Deployment
  1248  metadata:
  1249    name: deploy2
  1250  spec:
  1251    template:
  1252      spec:
  1253        containers: {}
  1254  ---
  1255  apiVersion: apps/v1
  1256  kind: Deployment
  1257  metadata:
  1258    name: deploy3
  1259  spec:
  1260    template:
  1261      spec:
  1262        containers: {}
  1263  `,
  1264  			replacements: `replacements:
  1265  - source:
  1266      kind: Pod
  1267      name: pod
  1268      fieldPath: spec.containers
  1269      options:
  1270        delimiter: "/"
  1271    targets:
  1272    - select:
  1273        kind: Deployment
  1274      fieldPaths:
  1275      - spec.template.spec.containers
  1276  `,
  1277  			expectedErr: "delimiter option can only be used with scalar nodes",
  1278  		},
  1279  		"complex type with delimiter in target": {
  1280  			input: `apiVersion: v1
  1281  kind: Pod
  1282  metadata:
  1283    name: pod
  1284  spec:
  1285    containers:
  1286    - image: busybox
  1287      name: myapp-container
  1288  ---
  1289  apiVersion: apps/v1
  1290  kind: Deployment
  1291  metadata:
  1292    name: deploy2
  1293  spec:
  1294    template:
  1295      spec:
  1296        containers: {}
  1297  ---
  1298  apiVersion: apps/v1
  1299  kind: Deployment
  1300  metadata:
  1301    name: deploy3
  1302  spec:
  1303    template:
  1304      spec:
  1305        containers: {}
  1306  `,
  1307  			replacements: `replacements:
  1308  - source:
  1309      kind: Pod
  1310      name: pod
  1311      fieldPath: spec.containers
  1312    targets:
  1313    - select:
  1314        kind: Deployment
  1315      fieldPaths:
  1316      - spec.template.spec.containers
  1317      options:
  1318        delimiter: "/"
  1319  `,
  1320  			expectedErr: "delimiter option can only be used with scalar nodes",
  1321  		},
  1322  		"mapping value contains '.' character": {
  1323  			input: `apiVersion: v1
  1324  kind: Custom
  1325  metadata:
  1326    name: custom
  1327    annotations:
  1328      a.b.c/d-e: source
  1329      f.g.h/i-j: target
  1330  `,
  1331  			replacements: `replacements:
  1332  - source:
  1333      name: custom
  1334      fieldPath: metadata.annotations.[a.b.c/d-e]
  1335    targets:
  1336    - select:
  1337        name: custom
  1338      fieldPaths:
  1339      - metadata.annotations.[f.g.h/i-j]
  1340  `,
  1341  			expected: `apiVersion: v1
  1342  kind: Custom
  1343  metadata:
  1344    name: custom
  1345    annotations:
  1346      a.b.c/d-e: source
  1347      f.g.h/i-j: source
  1348  `,
  1349  		},
  1350  		"list index contains '.' character": {
  1351  			input: `apiVersion: v1
  1352  kind: ConfigMap
  1353  metadata:
  1354    name: source
  1355  data:
  1356    value: example
  1357  ---
  1358  apiVersion: kubernetes-client.io/v1
  1359  kind: ExternalSecret
  1360  metadata:
  1361    name: some-secret
  1362  spec:
  1363    backendType: secretsManager
  1364    data:
  1365      - key: some-prefix-replaceme
  1366        name: .first
  1367        version: latest
  1368        property: first
  1369      - key: some-prefix-replaceme
  1370        name: second
  1371        version: latest
  1372        property: second
  1373  `,
  1374  			replacements: `replacements:
  1375  - source:
  1376      kind: ConfigMap
  1377      version: v1
  1378      name: source
  1379      fieldPath: data.value
  1380    targets:
  1381    - select:
  1382        group: kubernetes-client.io
  1383        version: v1
  1384        kind: ExternalSecret
  1385        name: some-secret
  1386      fieldPaths:
  1387      - spec.data.[name=.first].key
  1388      - spec.data.[name=second].key
  1389      options:
  1390        delimiter: "-"
  1391        index: 2
  1392  `,
  1393  			expected: `apiVersion: v1
  1394  kind: ConfigMap
  1395  metadata:
  1396    name: source
  1397  data:
  1398    value: example
  1399  ---
  1400  apiVersion: kubernetes-client.io/v1
  1401  kind: ExternalSecret
  1402  metadata:
  1403    name: some-secret
  1404  spec:
  1405    backendType: secretsManager
  1406    data:
  1407    - key: some-prefix-example
  1408      name: .first
  1409      version: latest
  1410      property: first
  1411    - key: some-prefix-example
  1412      name: second
  1413      version: latest
  1414      property: second`,
  1415  		},
  1416  		"one replacements target has multiple value": {
  1417  			input: `apiVersion: apps/v1
  1418  kind: Deployment
  1419  metadata:
  1420    labels:
  1421      app: sample-deploy
  1422    name: sample-deploy
  1423  spec:
  1424    replicas: 1
  1425    selector:
  1426      matchLabels:
  1427        app: sample-deploy
  1428    template:
  1429      metadata:
  1430        labels:
  1431          app: sample-deploy
  1432      spec:
  1433        containers:
  1434        - image: nginx
  1435          name: main
  1436          env:
  1437          - name: deployment-name
  1438            value: XXXXX
  1439          - name: foo
  1440            value: bar
  1441        - image: nginx
  1442          name: sidecar
  1443          env:
  1444          - name: deployment-name
  1445            value: YYYYY
  1446  `,
  1447  			replacements: `replacements:
  1448  - source:
  1449      kind: Deployment
  1450      name: sample-deploy
  1451      fieldPath: metadata.name
  1452    targets:
  1453    - select:
  1454        kind: Deployment
  1455      fieldPaths:
  1456      - spec.template.spec.containers.[image=nginx].env.[name=deployment-name].value
  1457  `,
  1458  			expected: `apiVersion: apps/v1
  1459  kind: Deployment
  1460  metadata:
  1461    labels:
  1462      app: sample-deploy
  1463    name: sample-deploy
  1464  spec:
  1465    replicas: 1
  1466    selector:
  1467      matchLabels:
  1468        app: sample-deploy
  1469    template:
  1470      metadata:
  1471        labels:
  1472          app: sample-deploy
  1473      spec:
  1474        containers:
  1475        - image: nginx
  1476          name: main
  1477          env:
  1478          - name: deployment-name
  1479            value: sample-deploy
  1480          - name: foo
  1481            value: bar
  1482        - image: nginx
  1483          name: sidecar
  1484          env:
  1485          - name: deployment-name
  1486            value: sample-deploy`,
  1487  		},
  1488  		"one replacements target should create multiple values": {
  1489  			input: `apiVersion: apps/v1
  1490  kind: Deployment
  1491  metadata:
  1492    labels:
  1493      app: sample-deploy
  1494    name: sample-deploy
  1495  spec:
  1496    replicas: 1
  1497    selector:
  1498      matchLabels:
  1499        app: sample-deploy
  1500    template:
  1501      metadata:
  1502        labels:
  1503          app: sample-deploy
  1504      spec:
  1505        containers:
  1506        - image: other
  1507          name: do-not-modify-me
  1508          env:
  1509          - name: foo
  1510            value: bar
  1511        - image: nginx
  1512          name: main
  1513          env:
  1514          - name: foo
  1515            value: bar
  1516        - image: nginx
  1517          name: sidecar
  1518  `,
  1519  			replacements: `replacements:
  1520  - source:
  1521      kind: Deployment
  1522      name: sample-deploy
  1523      fieldPath: metadata.name
  1524    targets:
  1525    - select:
  1526        kind: Deployment
  1527      options:
  1528        create: true
  1529      fieldPaths:
  1530      - spec.template.spec.containers.[image=nginx].env.[name=deployment-name].value
  1531  `,
  1532  			expected: `apiVersion: apps/v1
  1533  kind: Deployment
  1534  metadata:
  1535    labels:
  1536      app: sample-deploy
  1537    name: sample-deploy
  1538  spec:
  1539    replicas: 1
  1540    selector:
  1541      matchLabels:
  1542        app: sample-deploy
  1543    template:
  1544      metadata:
  1545        labels:
  1546          app: sample-deploy
  1547      spec:
  1548        containers:
  1549        - image: other
  1550          name: do-not-modify-me
  1551          env:
  1552          - name: foo
  1553            value: bar
  1554        - image: nginx
  1555          name: main
  1556          env:
  1557          - name: foo
  1558            value: bar
  1559          - name: deployment-name
  1560            value: sample-deploy
  1561        - image: nginx
  1562          name: sidecar
  1563          env:
  1564          - name: deployment-name
  1565            value: sample-deploy`,
  1566  		},
  1567  		"index contains '*' character": {
  1568  			input: `apiVersion: apps/v1
  1569  kind: Deployment
  1570  metadata:
  1571    labels:
  1572      app: sample-deploy
  1573    name: sample-deploy
  1574  spec:
  1575    replicas: 1
  1576    selector:
  1577      matchLabels:
  1578        app: sample-deploy
  1579    template:
  1580      metadata:
  1581        labels:
  1582          app: sample-deploy
  1583      spec:
  1584        containers:
  1585        - image: nginx
  1586          name: main
  1587          env:
  1588          - name: deployment-name
  1589            value: XXXXX
  1590  `,
  1591  			replacements: `replacements:
  1592  - source:
  1593      kind: Deployment
  1594      name: sample-deploy
  1595      fieldPath: metadata.name
  1596    targets:
  1597    - select:
  1598        kind: Deployment
  1599      fieldPaths:
  1600      - spec.template.spec.containers.*.env.[name=deployment-name].value
  1601  `,
  1602  			expected: `apiVersion: apps/v1
  1603  kind: Deployment
  1604  metadata:
  1605    labels:
  1606      app: sample-deploy
  1607    name: sample-deploy
  1608  spec:
  1609    replicas: 1
  1610    selector:
  1611      matchLabels:
  1612        app: sample-deploy
  1613    template:
  1614      metadata:
  1615        labels:
  1616          app: sample-deploy
  1617      spec:
  1618        containers:
  1619        - image: nginx
  1620          name: main
  1621          env:
  1622          - name: deployment-name
  1623            value: sample-deploy`,
  1624  		},
  1625  		"list index contains '*' character": {
  1626  			input: `apiVersion: apps/v1
  1627  kind: Deployment
  1628  metadata:
  1629    labels:
  1630      app: sample-deploy
  1631    name: sample-deploy
  1632  spec:
  1633    replicas: 1
  1634    selector:
  1635      matchLabels:
  1636        app: sample-deploy
  1637    template:
  1638      metadata:
  1639        labels:
  1640          app: sample-deploy
  1641      spec:
  1642        containers:
  1643        - image: nginx
  1644          name: main
  1645          env:
  1646          - name: deployment-name
  1647            value: XXXXX
  1648          - name: foo
  1649            value: bar
  1650        - image: nginx
  1651          name: sidecar
  1652          env:
  1653          - name: deployment-name
  1654            value: YYYYY
  1655  `,
  1656  			replacements: `replacements:
  1657  - source:
  1658      kind: Deployment
  1659      name: sample-deploy
  1660      fieldPath: metadata.name
  1661    targets:
  1662    - select:
  1663        kind: Deployment
  1664      fieldPaths:
  1665      - spec.template.spec.containers.*.env.[name=deployment-name].value
  1666  `,
  1667  			expected: `apiVersion: apps/v1
  1668  kind: Deployment
  1669  metadata:
  1670    labels:
  1671      app: sample-deploy
  1672    name: sample-deploy
  1673  spec:
  1674    replicas: 1
  1675    selector:
  1676      matchLabels:
  1677        app: sample-deploy
  1678    template:
  1679      metadata:
  1680        labels:
  1681          app: sample-deploy
  1682      spec:
  1683        containers:
  1684        - image: nginx
  1685          name: main
  1686          env:
  1687          - name: deployment-name
  1688            value: sample-deploy
  1689          - name: foo
  1690            value: bar
  1691        - image: nginx
  1692          name: sidecar
  1693          env:
  1694          - name: deployment-name
  1695            value: sample-deploy`,
  1696  		},
  1697  		"index contains '*' character and create options": {
  1698  			input: `apiVersion: apps/v1
  1699  kind: Deployment
  1700  metadata:
  1701    labels:
  1702      app: sample-deploy
  1703    name: sample-deploy
  1704  spec:
  1705    replicas: 1
  1706    selector:
  1707      matchLabels:
  1708        app: sample-deploy
  1709    template:
  1710      metadata:
  1711        labels:
  1712          app: sample-deploy
  1713      spec:
  1714        containers:
  1715        - image: nginx
  1716          name: main
  1717          env:
  1718          - name: other-env
  1719            value: YYYYY
  1720  `,
  1721  			replacements: `replacements:
  1722  - source:
  1723      kind: Deployment
  1724      name: sample-deploy
  1725      fieldPath: metadata.name
  1726    targets:
  1727    - select:
  1728        kind: Deployment
  1729      fieldPaths:
  1730      - spec.template.spec.containers.*.env.[name=deployment-name].value
  1731      options:
  1732        create: true
  1733  `,
  1734  			expected: `apiVersion: apps/v1
  1735  kind: Deployment
  1736  metadata:
  1737    labels:
  1738      app: sample-deploy
  1739    name: sample-deploy
  1740  spec:
  1741    replicas: 1
  1742    selector:
  1743      matchLabels:
  1744        app: sample-deploy
  1745    template:
  1746      metadata:
  1747        labels:
  1748          app: sample-deploy
  1749      spec:
  1750        containers:
  1751        - image: nginx
  1752          name: main
  1753          env:
  1754          - name: other-env
  1755            value: YYYYY
  1756          - name: deployment-name
  1757            value: sample-deploy
  1758  `,
  1759  		},
  1760  		"Issue 1493: wildcard to create or replace field in all containers in all workloads": {
  1761  			input: `apiVersion: v1
  1762  kind: ConfigMap
  1763  metadata:
  1764    name: policy
  1765  data:
  1766    restart: OnFailure
  1767  ---
  1768  apiVersion: v1
  1769  kind: Pod
  1770  metadata:
  1771    name: pod1
  1772  spec:
  1773    containers:
  1774    - image: nginx
  1775      name: main
  1776    - image: nginx
  1777      name: sidecar
  1778      imagePullPolicy: Always
  1779  ---
  1780  apiVersion: v1
  1781  kind: Pod
  1782  metadata:
  1783    name: pod2
  1784  spec:
  1785    containers:
  1786    - image: nginx
  1787      name: main
  1788      imagePullPolicy: Always
  1789    - image: nginx
  1790      name: sidecar
  1791  `,
  1792  			replacements: `replacements:
  1793  - source:
  1794      kind: ConfigMap
  1795      name: policy
  1796      fieldPath: data.restart
  1797    targets:
  1798    - select:
  1799        kind: Pod
  1800      fieldPaths:
  1801      - spec.containers.*.imagePullPolicy
  1802      options:
  1803        create: true
  1804  `,
  1805  			expected: `apiVersion: v1
  1806  kind: ConfigMap
  1807  metadata:
  1808    name: policy
  1809  data:
  1810    restart: OnFailure
  1811  ---
  1812  apiVersion: v1
  1813  kind: Pod
  1814  metadata:
  1815    name: pod1
  1816  spec:
  1817    containers:
  1818    - image: nginx
  1819      name: main
  1820      imagePullPolicy: OnFailure
  1821    - image: nginx
  1822      name: sidecar
  1823      imagePullPolicy: OnFailure
  1824  ---
  1825  apiVersion: v1
  1826  kind: Pod
  1827  metadata:
  1828    name: pod2
  1829  spec:
  1830    containers:
  1831    - image: nginx
  1832      name: main
  1833      imagePullPolicy: OnFailure
  1834    - image: nginx
  1835      name: sidecar
  1836      imagePullPolicy: OnFailure
  1837  `,
  1838  		},
  1839  		"multiple field paths in target": {
  1840  			input: `apiVersion: v1
  1841  kind: ConfigMap
  1842  metadata:
  1843    name: source
  1844  data:
  1845    value: example
  1846  ---
  1847  apiVersion: kubernetes-client.io/v1
  1848  kind: ExternalSecret
  1849  metadata:
  1850    name: some-secret
  1851  spec:
  1852    backendType: secretsManager
  1853    data:
  1854      - key: some-prefix-replaceme
  1855        name: first
  1856        version: latest
  1857        property: first
  1858      - key: some-prefix-replaceme
  1859        name: second
  1860        version: latest
  1861        property: second
  1862      - key: some-prefix-replaceme
  1863        name: third
  1864        version: latest
  1865        property: third
  1866  `,
  1867  			replacements: `replacements:
  1868  - source:
  1869      kind: ConfigMap
  1870      version: v1
  1871      name: source
  1872      fieldPath: data.value
  1873    targets:
  1874    - select:
  1875        group: kubernetes-client.io
  1876        version: v1
  1877        kind: ExternalSecret
  1878        name: some-secret
  1879      fieldPaths:
  1880      - spec.data.0.key
  1881      - spec.data.1.key
  1882      - spec.data.2.key
  1883      options:
  1884        delimiter: "-"
  1885        index: 2
  1886  `,
  1887  			expected: `apiVersion: v1
  1888  kind: ConfigMap
  1889  metadata:
  1890    name: source
  1891  data:
  1892    value: example
  1893  ---
  1894  apiVersion: kubernetes-client.io/v1
  1895  kind: ExternalSecret
  1896  metadata:
  1897    name: some-secret
  1898  spec:
  1899    backendType: secretsManager
  1900    data:
  1901    - key: some-prefix-example
  1902      name: first
  1903      version: latest
  1904      property: first
  1905    - key: some-prefix-example
  1906      name: second
  1907      version: latest
  1908      property: second
  1909    - key: some-prefix-example
  1910      name: third
  1911      version: latest
  1912      property: third
  1913  `,
  1914  		},
  1915  		"using a previous ID": {
  1916  			input: `apiVersion: v1
  1917  kind: Deployment
  1918  metadata:
  1919    name: pre-deploy
  1920    annotations:
  1921      internal.config.kubernetes.io/previousNames: deploy,deploy
  1922      internal.config.kubernetes.io/previousKinds: CronJob,Deployment
  1923      internal.config.kubernetes.io/previousNamespaces: default,default
  1924  spec:
  1925    template:
  1926      spec:
  1927        containers:
  1928        - image: nginx:1.7.9
  1929          name: nginx-tagged
  1930        - image: postgres:1.8.0
  1931          name: postgresdb
  1932  `,
  1933  			replacements: `replacements:
  1934  - source:
  1935      kind: CronJob
  1936      name: deploy
  1937      fieldPath: spec.template.spec.containers.0.image
  1938    targets:
  1939    - select:
  1940        kind: Deployment
  1941        name: deploy
  1942      fieldPaths:
  1943      - spec.template.spec.containers.1.image
  1944  `,
  1945  			expected: `apiVersion: v1
  1946  kind: Deployment
  1947  metadata:
  1948    name: pre-deploy
  1949    annotations:
  1950      internal.config.kubernetes.io/previousNames: deploy,deploy
  1951      internal.config.kubernetes.io/previousKinds: CronJob,Deployment
  1952      internal.config.kubernetes.io/previousNamespaces: default,default
  1953  spec:
  1954    template:
  1955      spec:
  1956        containers:
  1957        - image: nginx:1.7.9
  1958          name: nginx-tagged
  1959        - image: nginx:1.7.9
  1960          name: postgresdb
  1961  `,
  1962  		},
  1963  		"replacement source.fieldPath does not exist": {
  1964  			input: `apiVersion: v1
  1965  kind: ConfigMap
  1966  metadata:
  1967    name: ports-from
  1968  data:
  1969    grpcPort: 8080
  1970  ---
  1971  apiVersion: v1
  1972  kind: ConfigMap
  1973  metadata:
  1974    name: ports-to
  1975  data:
  1976    grpcPort: 8081
  1977  `,
  1978  			replacements: `replacements:
  1979  - source:
  1980      kind: ConfigMap
  1981      name: ports-from
  1982      fieldPath: data.httpPort
  1983    targets:
  1984    - select:
  1985        kind: ConfigMap
  1986        name: ports-to
  1987      fieldPaths:
  1988      - data.grpcPort
  1989      options:
  1990        create: true
  1991  `,
  1992  			expectedErr: "fieldPath `data.httpPort` is missing for replacement source ConfigMap.[noVer].[noGrp]/ports-from.[noNs]",
  1993  		},
  1994  		"annotationSelector": {
  1995  			input: `apiVersion: v1
  1996  kind: Deployment
  1997  metadata:
  1998    name: deploy-1
  1999    annotations:
  2000      foo: bar-1
  2001  spec:
  2002    template:
  2003      spec:
  2004        containers:
  2005        - image: nginx:1.7.9
  2006          name: nginx-tagged
  2007        - image: postgres:1.8.0
  2008          name: postgresdb
  2009  ---
  2010  apiVersion: v1
  2011  kind: Deployment
  2012  metadata:
  2013    name: deploy-2
  2014    annotations:
  2015      foo: bar-2
  2016  spec:
  2017    template:
  2018      spec:
  2019        containers:
  2020        - image: nginx:1.7.9
  2021          name: nginx-tagged
  2022        - image: postgres:1.8.0
  2023          name: postgresdb
  2024  
  2025  `,
  2026  			replacements: `replacements:
  2027  - source:
  2028      kind: Deployment
  2029      name: deploy-1
  2030      fieldPath: spec.template.spec.containers.0.image
  2031    targets:
  2032    - select:
  2033        annotationSelector: foo=bar-1
  2034      fieldPaths:
  2035      - spec.template.spec.containers.1.image
  2036  `,
  2037  			expected: `apiVersion: v1
  2038  kind: Deployment
  2039  metadata:
  2040    name: deploy-1
  2041    annotations:
  2042      foo: bar-1
  2043  spec:
  2044    template:
  2045      spec:
  2046        containers:
  2047        - image: nginx:1.7.9
  2048          name: nginx-tagged
  2049        - image: nginx:1.7.9
  2050          name: postgresdb
  2051  ---
  2052  apiVersion: v1
  2053  kind: Deployment
  2054  metadata:
  2055    name: deploy-2
  2056    annotations:
  2057      foo: bar-2
  2058  spec:
  2059    template:
  2060      spec:
  2061        containers:
  2062        - image: nginx:1.7.9
  2063          name: nginx-tagged
  2064        - image: postgres:1.8.0
  2065          name: postgresdb
  2066  `,
  2067  		},
  2068  		"labelSelector": {
  2069  			input: `apiVersion: v1
  2070  kind: Deployment
  2071  metadata:
  2072    name: deploy-1
  2073    labels:
  2074      foo: bar-1
  2075  spec:
  2076    template:
  2077      spec:
  2078        containers:
  2079        - image: nginx:1.7.9
  2080          name: nginx-tagged
  2081        - image: postgres:1.8.0
  2082          name: postgresdb
  2083  ---
  2084  apiVersion: v1
  2085  kind: Deployment
  2086  metadata:
  2087    name: deploy-2
  2088    labels:
  2089      foo: bar-2
  2090  spec:
  2091    template:
  2092      spec:
  2093        containers:
  2094        - image: nginx:1.7.9
  2095          name: nginx-tagged
  2096        - image: postgres:1.8.0
  2097          name: postgresdb
  2098  
  2099  `,
  2100  			replacements: `replacements:
  2101  - source:
  2102      kind: Deployment
  2103      name: deploy-1
  2104      fieldPath: spec.template.spec.containers.0.image
  2105    targets:
  2106    - select:
  2107        labelSelector: foo=bar-1
  2108      fieldPaths:
  2109      - spec.template.spec.containers.1.image
  2110  `,
  2111  			expected: `apiVersion: v1
  2112  kind: Deployment
  2113  metadata:
  2114    name: deploy-1
  2115    labels:
  2116      foo: bar-1
  2117  spec:
  2118    template:
  2119      spec:
  2120        containers:
  2121        - image: nginx:1.7.9
  2122          name: nginx-tagged
  2123        - image: nginx:1.7.9
  2124          name: postgresdb
  2125  ---
  2126  apiVersion: v1
  2127  kind: Deployment
  2128  metadata:
  2129    name: deploy-2
  2130    labels:
  2131      foo: bar-2
  2132  spec:
  2133    template:
  2134      spec:
  2135        containers:
  2136        - image: nginx:1.7.9
  2137          name: nginx-tagged
  2138        - image: postgres:1.8.0
  2139          name: postgresdb
  2140  `,
  2141  		},
  2142  		"reject via labelSelector": {
  2143  			input: `apiVersion: v1
  2144  kind: Deployment
  2145  metadata:
  2146    name: deploy-1
  2147    labels:
  2148      foo: bar-1
  2149  spec:
  2150    template:
  2151      spec:
  2152        containers:
  2153        - image: nginx:1.7.9
  2154          name: nginx-tagged
  2155        - image: postgres:1.8.0
  2156          name: postgresdb
  2157  ---
  2158  apiVersion: v1
  2159  kind: Deployment
  2160  metadata:
  2161    name: deploy-2
  2162    labels:
  2163      foo: bar-2
  2164  spec:
  2165    template:
  2166      spec:
  2167        containers:
  2168        - image: nginx:1.7.9
  2169          name: nginx-tagged
  2170        - image: postgres:1.8.0
  2171          name: postgresdb
  2172  
  2173  `,
  2174  			replacements: `replacements:
  2175  - source:
  2176      kind: Deployment
  2177      name: deploy-1
  2178      fieldPath: spec.template.spec.containers.0.image
  2179    targets:
  2180    - select:
  2181        kind: Deployment
  2182      reject:
  2183      - labelSelector: foo=bar-2
  2184      fieldPaths:
  2185      - spec.template.spec.containers.1.image
  2186  `,
  2187  			expected: `apiVersion: v1
  2188  kind: Deployment
  2189  metadata:
  2190    name: deploy-1
  2191    labels:
  2192      foo: bar-1
  2193  spec:
  2194    template:
  2195      spec:
  2196        containers:
  2197        - image: nginx:1.7.9
  2198          name: nginx-tagged
  2199        - image: nginx:1.7.9
  2200          name: postgresdb
  2201  ---
  2202  apiVersion: v1
  2203  kind: Deployment
  2204  metadata:
  2205    name: deploy-2
  2206    labels:
  2207      foo: bar-2
  2208  spec:
  2209    template:
  2210      spec:
  2211        containers:
  2212        - image: nginx:1.7.9
  2213          name: nginx-tagged
  2214        - image: postgres:1.8.0
  2215          name: postgresdb
  2216  `,
  2217  		},
  2218  		"string source -> integer target": {
  2219  			input: `apiVersion: v1
  2220  kind: ConfigMap
  2221  metadata:
  2222    name: config
  2223  data:
  2224    PORT: "8080"
  2225  ---
  2226  apiVersion: apps/v1
  2227  kind: Pod
  2228  metadata:
  2229    name: pod
  2230  spec:
  2231    containers:
  2232    - image: busybox
  2233      name: myapp-container
  2234      ports:
  2235      - containerPort: 80
  2236  `,
  2237  			replacements: `replacements:
  2238  - source:
  2239      kind: ConfigMap
  2240      name: config
  2241      fieldPath: data.PORT
  2242    targets:
  2243    - select:
  2244        kind: Pod
  2245      fieldPaths:
  2246      - spec.containers.0.ports.0.containerPort
  2247  `,
  2248  			expected: `apiVersion: v1
  2249  kind: ConfigMap
  2250  metadata:
  2251    name: config
  2252  data:
  2253    PORT: "8080"
  2254  ---
  2255  apiVersion: apps/v1
  2256  kind: Pod
  2257  metadata:
  2258    name: pod
  2259  spec:
  2260    containers:
  2261    - image: busybox
  2262      name: myapp-container
  2263      ports:
  2264      - containerPort: 8080
  2265  `,
  2266  		},
  2267  		"string source -> boolean target": {
  2268  			input: `apiVersion: v1
  2269  kind: ConfigMap
  2270  metadata:
  2271    name: config
  2272  data:
  2273    MOUNT_TOKEN: "true"
  2274  ---
  2275  apiVersion: apps/v1
  2276  kind: Pod
  2277  metadata:
  2278    name: pod
  2279  spec:
  2280    containers:
  2281    - image: busybox
  2282      name: myapp-container
  2283      automountServiceAccountToken: false
  2284  `,
  2285  			replacements: `replacements:
  2286  - source:
  2287      kind: ConfigMap
  2288      name: config
  2289      fieldPath: data.MOUNT_TOKEN
  2290    targets:
  2291    - select:
  2292        kind: Pod
  2293      fieldPaths:
  2294      - spec.containers.0.automountServiceAccountToken
  2295  `,
  2296  			expected: `apiVersion: v1
  2297  kind: ConfigMap
  2298  metadata:
  2299    name: config
  2300  data:
  2301    MOUNT_TOKEN: "true"
  2302  ---
  2303  apiVersion: apps/v1
  2304  kind: Pod
  2305  metadata:
  2306    name: pod
  2307  spec:
  2308    containers:
  2309    - image: busybox
  2310      name: myapp-container
  2311      automountServiceAccountToken: true
  2312  `,
  2313  		},
  2314  		// TODO: This is inconsistent with expectations; creating a numerical string would be
  2315  		// expected, unless we had knowledge of the intended type of the field to be
  2316  		// created.
  2317  		"numerical string source -> integer creation": {
  2318  			input: `apiVersion: v1
  2319  kind: ConfigMap
  2320  metadata:
  2321    name: config
  2322  data:
  2323    PORT: "8080"
  2324  ---
  2325  apiVersion: apps/v1
  2326  kind: Pod
  2327  metadata:
  2328    name: pod
  2329  spec:
  2330    containers:
  2331    - image: busybox
  2332      name: myapp-container
  2333      ports:
  2334      - protocol: TCP
  2335  `,
  2336  			replacements: `replacements:
  2337  - source:
  2338      kind: ConfigMap
  2339      name: config
  2340      fieldPath: data.PORT
  2341    targets:
  2342    - select:
  2343        kind: Pod
  2344      fieldPaths:
  2345      - spec.containers.0.ports.0.containerPort
  2346      - spec.containers.0.ports.0.name
  2347      options:
  2348        create: true
  2349  `,
  2350  			expected: `apiVersion: v1
  2351  kind: ConfigMap
  2352  metadata:
  2353    name: config
  2354  data:
  2355    PORT: "8080"
  2356  ---
  2357  apiVersion: apps/v1
  2358  kind: Pod
  2359  metadata:
  2360    name: pod
  2361  spec:
  2362    containers:
  2363    - image: busybox
  2364      name: myapp-container
  2365      ports:
  2366      - protocol: TCP
  2367        containerPort: 8080
  2368        name: 8080
  2369  `,
  2370  		},
  2371  		"integer source -> string target": {
  2372  			input: `apiVersion: v1
  2373  kind: ConfigMap
  2374  metadata:
  2375    name: config
  2376  data:
  2377    PORT: "8080"
  2378  ---
  2379  apiVersion: apps/v1
  2380  kind: Pod
  2381  metadata:
  2382    name: pod
  2383  spec:
  2384    containers:
  2385    - image: busybox
  2386      name: myapp-container
  2387      ports:
  2388      - containerPort: 80
  2389  `,
  2390  			replacements: `replacements:
  2391  - source:
  2392      kind: Pod
  2393      name: pod
  2394      fieldPath: spec.containers.0.ports.0.containerPort
  2395    targets:
  2396    - select:
  2397        kind: ConfigMap
  2398      fieldPaths:
  2399      - data.PORT
  2400  `,
  2401  			expected: `apiVersion: v1
  2402  kind: ConfigMap
  2403  metadata:
  2404    name: config
  2405  data:
  2406    PORT: "80"
  2407  ---
  2408  apiVersion: apps/v1
  2409  kind: Pod
  2410  metadata:
  2411    name: pod
  2412  spec:
  2413    containers:
  2414    - image: busybox
  2415      name: myapp-container
  2416      ports:
  2417      - containerPort: 80
  2418  `,
  2419  		},
  2420  		"boolean source -> string target": {
  2421  			input: `apiVersion: v1
  2422  kind: ConfigMap
  2423  metadata:
  2424    name: config
  2425  data:
  2426    MOUNT_TOKEN: "true"
  2427  ---
  2428  apiVersion: apps/v1
  2429  kind: Pod
  2430  metadata:
  2431    name: pod
  2432  spec:
  2433    containers:
  2434    - image: busybox
  2435      name: myapp-container
  2436      automountServiceAccountToken: false
  2437  `,
  2438  			replacements: `replacements:
  2439  - source:
  2440      kind: Pod
  2441      name: pod
  2442      fieldPath: spec.containers.0.automountServiceAccountToken
  2443    targets:
  2444    - select:
  2445        kind: ConfigMap
  2446      fieldPaths:
  2447      - data.MOUNT_TOKEN
  2448  `,
  2449  			expected: `apiVersion: v1
  2450  kind: ConfigMap
  2451  metadata:
  2452    name: config
  2453  data:
  2454    MOUNT_TOKEN: "false"
  2455  ---
  2456  apiVersion: apps/v1
  2457  kind: Pod
  2458  metadata:
  2459    name: pod
  2460  spec:
  2461    containers:
  2462    - image: busybox
  2463      name: myapp-container
  2464      automountServiceAccountToken: false
  2465  `,
  2466  		},
  2467  		// TODO: This result is expected, but we should create a string and not an
  2468  		// integer if we could know that the target type should be one. As a result,
  2469  		// the actual ConfigMap produces here cannot be applied.
  2470  		"integer source -> integer creation": {
  2471  			input: `apiVersion: v1
  2472  kind: ConfigMap
  2473  metadata:
  2474    name: config
  2475  data:
  2476    FOO: "Bar"
  2477  ---
  2478  apiVersion: apps/v1
  2479  kind: Pod
  2480  metadata:
  2481    name: pod
  2482  spec:
  2483    containers:
  2484    - image: busybox
  2485      name: myapp-container
  2486      ports:
  2487      - containerPort: 80
  2488  `,
  2489  			replacements: `replacements:
  2490  - source:
  2491      kind: Pod
  2492      name: pod
  2493      fieldPath: spec.containers.0.ports.0.containerPort
  2494    targets:
  2495    - select:
  2496        kind: ConfigMap
  2497      fieldPaths:
  2498      - data.PORT
  2499      options:
  2500        create: true
  2501  `,
  2502  			expected: `apiVersion: v1
  2503  kind: ConfigMap
  2504  metadata:
  2505    name: config
  2506  data:
  2507    FOO: "Bar"
  2508    PORT: 80
  2509  ---
  2510  apiVersion: apps/v1
  2511  kind: Pod
  2512  metadata:
  2513    name: pod
  2514  spec:
  2515    containers:
  2516    - image: busybox
  2517      name: myapp-container
  2518      ports:
  2519      - containerPort: 80
  2520  `,
  2521  		},
  2522  		"replace an existing mapping value": {
  2523  			input: `apiVersion: batch/v1
  2524  kind: Job
  2525  metadata:
  2526    name: hello
  2527  spec:
  2528    template:
  2529      spec:
  2530        containers:
  2531        - image: busybox
  2532          name: myapp-container
  2533        restartPolicy: old
  2534  ---
  2535  apiVersion: v1
  2536  kind: Pod
  2537  metadata:
  2538    name: my-pod
  2539  spec:
  2540    containers:
  2541      - image: busybox
  2542        name: myapp-container
  2543    restartPolicy: new
  2544  `,
  2545  			replacements: `replacements:
  2546  - source:
  2547      kind: Pod
  2548      name: my-pod
  2549      fieldPath: spec
  2550    targets:
  2551    - select:
  2552        name: hello
  2553        kind: Job
  2554      fieldPaths:
  2555       - spec.template.spec
  2556      options:
  2557        create: true
  2558  `,
  2559  			expected: `apiVersion: batch/v1
  2560  kind: Job
  2561  metadata:
  2562    name: hello
  2563  spec:
  2564    template:
  2565      spec:
  2566        containers:
  2567        - image: busybox
  2568          name: myapp-container
  2569        restartPolicy: new
  2570  ---
  2571  apiVersion: v1
  2572  kind: Pod
  2573  metadata:
  2574    name: my-pod
  2575  spec:
  2576    containers:
  2577    - image: busybox
  2578      name: myapp-container
  2579    restartPolicy: new
  2580  `,
  2581  		},
  2582  		"issue4761 - path not in target with create: true": {
  2583  			input: `
  2584  ---
  2585  apiVersion: networking.istio.io/v1alpha3
  2586  kind: EnvoyFilter
  2587  metadata:
  2588    name: request-id
  2589  spec:
  2590    configPatches:
  2591      - applyTo: NETWORK_FILTER
  2592      - applyTo: NETWORK_FILTER
  2593  ---
  2594  apiVersion: v1
  2595  kind: ConfigMap
  2596  metadata:
  2597    name: istio-version
  2598    annotations:
  2599      config.kubernetes.io/local-config: true
  2600  data:
  2601    ISTIO_REGEX: '^1\.14.*'
  2602  `,
  2603  			replacements: `
  2604  replacements:
  2605    - source:
  2606        kind: ConfigMap
  2607        name: istio-version
  2608        fieldPath: data.ISTIO_REGEX
  2609      targets:
  2610        - select:
  2611            kind: EnvoyFilter
  2612          fieldPaths:
  2613            - spec.configPatches.0.match.proxy.proxyVersion
  2614            - spec.configPatches.1.match.proxy.proxyVersion
  2615            - spec.configPatches.2.match.proxy.proxyVersion
  2616            - spec.configPatches.3.match.proxy.proxyVersion
  2617          options:
  2618            create: true
  2619  `,
  2620  			expected: `
  2621  apiVersion: networking.istio.io/v1alpha3
  2622  kind: EnvoyFilter
  2623  metadata:
  2624    name: request-id
  2625  spec:
  2626    configPatches:
  2627    - applyTo: NETWORK_FILTER
  2628      match:
  2629        proxy:
  2630          proxyVersion: ^1\.14.*
  2631    - applyTo: NETWORK_FILTER
  2632      match:
  2633        proxy:
  2634          proxyVersion: ^1\.14.*
  2635    - match:
  2636        proxy:
  2637          proxyVersion: ^1\.14.*
  2638    - match:
  2639        proxy:
  2640          proxyVersion: ^1\.14.*
  2641  ---
  2642  apiVersion: v1
  2643  kind: ConfigMap
  2644  metadata:
  2645    name: istio-version
  2646    annotations:
  2647      config.kubernetes.io/local-config: true
  2648  data:
  2649    ISTIO_REGEX: '^1\.14.*'
  2650  `,
  2651  		},
  2652  		"issue4761 - path not in target with create: false": {
  2653  			input: `
  2654  ---
  2655  apiVersion: networking.istio.io/v1alpha3
  2656  kind: EnvoyFilter
  2657  metadata:
  2658    name: request-id
  2659  spec:
  2660    configPatches:
  2661      - applyTo: NETWORK_FILTER
  2662      - applyTo: NETWORK_FILTER
  2663  ---
  2664  apiVersion: v1
  2665  kind: ConfigMap
  2666  metadata:
  2667    name: istio-version
  2668    annotations:
  2669      config.kubernetes.io/local-config: true
  2670  data:
  2671    ISTIO_REGEX: '^1\.14.*'
  2672  `,
  2673  			replacements: `
  2674  replacements:
  2675    - source:
  2676        kind: ConfigMap
  2677        name: istio-version
  2678        fieldPath: data.ISTIO_REGEX
  2679      targets:
  2680        - select:
  2681            kind: EnvoyFilter
  2682          fieldPaths:
  2683            - spec.configPatches.0.match.proxy.proxyVersion
  2684            - spec.configPatches.1.match.proxy.proxyVersion
  2685            - spec.configPatches.2.match.proxy.proxyVersion
  2686            - spec.configPatches.3.match.proxy.proxyVersion
  2687          options:
  2688            create: false
  2689  `,
  2690  			expectedErr: "unable to find field \"spec.configPatches.0.match.proxy.proxyVersion\" in replacement target",
  2691  		},
  2692  		"issue4761 - wildcard solution": {
  2693  			input: `
  2694  ---
  2695  apiVersion: networking.istio.io/v1alpha3
  2696  kind: EnvoyFilter
  2697  metadata:
  2698    name: request-id
  2699  spec:
  2700    configPatches:
  2701      - applyTo: NETWORK_FILTER
  2702      - applyTo: NETWORK_FILTER
  2703  ---
  2704  apiVersion: v1
  2705  kind: ConfigMap
  2706  metadata:
  2707    name: istio-version
  2708    annotations:
  2709      config.kubernetes.io/local-config: true
  2710  data:
  2711    ISTIO_REGEX: '^1\.14.*'
  2712  `,
  2713  			replacements: `
  2714  replacements:
  2715    - source:
  2716        kind: ConfigMap
  2717        name: istio-version
  2718        fieldPath: data.ISTIO_REGEX
  2719      targets:
  2720        - select:
  2721            kind: EnvoyFilter
  2722          fieldPaths:
  2723            - spec.configPatches.*.match.proxy.proxyVersion
  2724          options:
  2725            create: true
  2726  `,
  2727  			expected: `
  2728  apiVersion: networking.istio.io/v1alpha3
  2729  kind: EnvoyFilter
  2730  metadata:
  2731    name: request-id
  2732  spec:
  2733    configPatches:
  2734    - applyTo: NETWORK_FILTER
  2735      match:
  2736        proxy:
  2737          proxyVersion: ^1\.14.*
  2738    - applyTo: NETWORK_FILTER
  2739      match:
  2740        proxy:
  2741          proxyVersion: ^1\.14.*
  2742  ---
  2743  apiVersion: v1
  2744  kind: ConfigMap
  2745  metadata:
  2746    name: istio-version
  2747    annotations:
  2748      config.kubernetes.io/local-config: true
  2749  data:
  2750    ISTIO_REGEX: '^1\.14.*'
  2751  `,
  2752  		},
  2753  		"append to sequence using index": {
  2754  			input: `apiVersion: networking.k8s.io/v1
  2755  kind: Ingress
  2756  metadata:
  2757    name: myingress
  2758  spec:
  2759    rules:
  2760      - host: myingress.example.com
  2761        http:
  2762          paths:
  2763            - path: /
  2764              pathType: Prefix
  2765              backend:
  2766                service:
  2767                  name: my-svc
  2768                  port:
  2769                    number: 80
  2770  `,
  2771  			replacements: `replacements:
  2772    - source:
  2773        kind: Ingress
  2774        name: myingress
  2775        fieldPath: spec.rules.0.host
  2776      targets:
  2777        - select:
  2778            kind: Ingress
  2779            name: myingress
  2780          fieldPaths:
  2781            - spec.tls.0.hosts.0
  2782            - spec.tls.0.secretName          
  2783          options:
  2784            create: true
  2785  `,
  2786  			expected: `apiVersion: networking.k8s.io/v1
  2787  kind: Ingress
  2788  metadata:
  2789    name: myingress
  2790  spec:
  2791    rules:
  2792    - host: myingress.example.com
  2793      http:
  2794        paths:
  2795        - path: /
  2796          pathType: Prefix
  2797          backend:
  2798            service:
  2799              name: my-svc
  2800              port:
  2801                number: 80
  2802    tls:
  2803    - hosts:
  2804      - myingress.example.com
  2805      secretName: myingress.example.com`,
  2806  		},
  2807  		"fail to append to sequence using a distant index": {
  2808  			input: `apiVersion: networking.k8s.io/v1
  2809  kind: Ingress
  2810  metadata:
  2811    name: myingress
  2812  spec:
  2813    rules:
  2814      - host: myingress.example.com
  2815  `,
  2816  			replacements: `replacements:
  2817    - source:
  2818        kind: Ingress
  2819        name: myingress
  2820        fieldPath: spec.rules.0.host
  2821      targets:
  2822        - select:
  2823            kind: Ingress
  2824            name: myingress
  2825          fieldPaths:
  2826            - spec.tls.5.hosts.5
  2827            - spec.tls.5.secretName
  2828          options:
  2829            create: true
  2830  `,
  2831  			expectedErr: "unable to find or create field \"spec.tls.5.hosts.5\" in replacement target: index 5 specified but only 0 elements found",
  2832  		},
  2833  	}
  2834  
  2835  	for tn, tc := range testCases {
  2836  		t.Run(tn, func(t *testing.T) {
  2837  			f := Filter{}
  2838  			err := yaml.Unmarshal([]byte(tc.replacements), &f)
  2839  			if !assert.NoError(t, err) {
  2840  				t.FailNow()
  2841  			}
  2842  			actual, err := filtertest.RunFilterE(t, tc.input, f)
  2843  			if err != nil {
  2844  				if tc.expectedErr == "" {
  2845  					t.Errorf("unexpected error: %s\n", err.Error())
  2846  					t.FailNow()
  2847  				}
  2848  				if !assert.Contains(t, err.Error(), tc.expectedErr) {
  2849  					t.FailNow()
  2850  				}
  2851  			}
  2852  			if !assert.Equal(t, strings.TrimSpace(tc.expected), strings.TrimSpace(actual)) {
  2853  				t.FailNow()
  2854  			}
  2855  		})
  2856  	}
  2857  }
  2858  

View as plain text