istio.io/istio@v0.0.0-20240520182934-d79c90f27776/operator/pkg/translate/translate_value_test.go (about)

     1  // Copyright Istio Authors
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package translate
    16  
    17  import (
    18  	"testing"
    19  
    20  	"sigs.k8s.io/yaml"
    21  
    22  	"istio.io/istio/operator/pkg/apis/istio"
    23  	"istio.io/istio/operator/pkg/apis/istio/v1alpha1"
    24  	"istio.io/istio/operator/pkg/util"
    25  	"istio.io/istio/pkg/util/protomarshal"
    26  )
    27  
    28  func TestValueToProto(t *testing.T) {
    29  	tests := []struct {
    30  		desc      string
    31  		valueYAML string
    32  		want      string
    33  		wantErr   string
    34  	}{
    35  		{
    36  			desc: "K8s resources translation",
    37  			valueYAML: `
    38  pilot:
    39    enabled: true
    40    rollingMaxSurge: 100%
    41    rollingMaxUnavailable: 25%
    42    resources:
    43      requests:
    44        cpu: 1000m
    45        memory: 1G
    46    replicaCount: 1
    47    nodeSelector:
    48      kubernetes.io/os: linux
    49    tolerations:
    50    - key: dedicated
    51      operator: Exists
    52      effect: NoSchedule
    53    - key: CriticalAddonsOnly
    54      operator: Exists
    55    autoscaleEnabled: true
    56    autoscaleMax: 3
    57    autoscaleMin: 1
    58    cpu:
    59      targetAverageUtilization: 80
    60    traceSampling: 1.0
    61    image: pilot
    62    env:
    63      GODEBUG: gctrace=1
    64  global:
    65    hub: docker.io/istio
    66    istioNamespace: istio-system
    67    tag: 1.2.3
    68    proxy:
    69      readinessInitialDelaySeconds: 2
    70  `,
    71  			want: `
    72  hub: docker.io/istio
    73  tag: 1.2.3
    74  components:
    75     pilot:
    76       enabled: true
    77       k8s:
    78         replicaCount: 1
    79         env:
    80         - name: GODEBUG
    81           value: gctrace=1
    82         nodeSelector:
    83            kubernetes.io/os: linux
    84         tolerations:
    85         - key: dedicated
    86           operator: Exists
    87           effect: NoSchedule
    88         - key: CriticalAddonsOnly
    89           operator: Exists
    90         resources:
    91            requests:
    92              cpu: 1000m
    93              memory: 1G
    94         strategy:
    95           rollingUpdate:
    96             maxSurge: 100%
    97             maxUnavailable: 25%
    98  values:
    99    global:
   100      istioNamespace: istio-system
   101      proxy:
   102        readinessInitialDelaySeconds: 2
   103    pilot:
   104      image: pilot
   105      autoscaleEnabled: true
   106      autoscaleMax: 3
   107      autoscaleMin: 1
   108      cpu:
   109        targetAverageUtilization: 80
   110      traceSampling: 1
   111  `,
   112  		},
   113  		{
   114  			desc: "All Enabled",
   115  			valueYAML: `
   116  global:
   117    hub: docker.io/istio
   118    istioNamespace: istio-system
   119    tag: 1.2.3
   120  pilot:
   121    enabled: true
   122  gateways:
   123    enabled: true
   124    istio-ingressgateway:
   125      rollingMaxSurge: 4
   126      rollingMaxUnavailable: 1
   127      resources:
   128        requests:
   129          cpu: 1000m
   130          memory: 1G
   131      enabled: true
   132  `,
   133  			want: `
   134  hub: docker.io/istio
   135  tag: 1.2.3
   136  components:
   137    pilot:
   138      enabled: true
   139    ingressGateways:
   140    - name: istio-ingressgateway
   141      enabled: true
   142      k8s:
   143        resources:
   144          requests:
   145            cpu: 1000m
   146            memory: 1G
   147        strategy:
   148          rollingUpdate:
   149            maxSurge: 4
   150            maxUnavailable: 1
   151  values:
   152    global:
   153      istioNamespace: istio-system
   154  `,
   155  		},
   156  		{
   157  			desc: "Some components Disabled",
   158  			valueYAML: `
   159  pilot:
   160    enabled: true
   161  global:
   162    hub: docker.io/istio
   163    istioNamespace: istio-system
   164    tag: 1.2.3
   165  `,
   166  			want: `
   167  hub: docker.io/istio
   168  tag: 1.2.3
   169  components:
   170     pilot:
   171       enabled: true
   172  values:
   173    global:
   174      istioNamespace: istio-system
   175  `,
   176  		},
   177  	}
   178  	tr := NewReverseTranslator()
   179  
   180  	for _, tt := range tests {
   181  		t.Run(tt.desc, func(t *testing.T) {
   182  			valueStruct := v1alpha1.Values{}
   183  			err := util.UnmarshalWithJSONPB(tt.valueYAML, &valueStruct, false)
   184  			if err != nil {
   185  				t.Fatalf("unmarshal(%s): got error %s", tt.desc, err)
   186  			}
   187  			gotSpec, err := tr.TranslateFromValueToSpec([]byte(tt.valueYAML), false)
   188  			if gotErr, wantErr := errToString(err), tt.wantErr; gotErr != wantErr {
   189  				t.Errorf("ValuesToProto(%s)(%v): gotErr:%s, wantErr:%s", tt.desc, tt.valueYAML, gotErr, wantErr)
   190  			}
   191  			if tt.wantErr == "" {
   192  				byteArray, err := protomarshal.Marshal(gotSpec)
   193  				if err != nil {
   194  					t.Errorf("failed to marshal translated IstioOperatorSpec: %s", err)
   195  				}
   196  				cpYaml, _ := yaml.JSONToYAML(byteArray)
   197  				if want := tt.want; !util.IsYAMLEqual(string(byteArray), want) {
   198  					t.Errorf("ValuesToProto(%s): got:\n%s\n\nwant:\n%s\nDiff:\n%s\n", tt.desc, string(cpYaml), want, util.YAMLDiff(string(byteArray), want))
   199  				}
   200  
   201  			}
   202  		})
   203  	}
   204  }
   205  
   206  func TestValueToK8s(t *testing.T) {
   207  	tests := []struct {
   208  		desc      string
   209  		inIOPSpec string
   210  		want      string
   211  		wantErr   string
   212  	}{
   213  		{
   214  			desc: "pilot env k8s setting with values",
   215  			inIOPSpec: `
   216  spec:
   217    components:
   218      pilot:
   219        k8s:
   220          nodeSelector:
   221            master: "true"
   222          env:
   223          - name: EXTERNAL_CA
   224            value: ISTIOD_RA_KUBERNETES_API
   225          - name: K8S_SIGNER
   226            value: kubernetes.io/legacy-unknown
   227    values:
   228      pilot:
   229        enabled: true
   230        rollingMaxSurge: 100%
   231        rollingMaxUnavailable: 25%
   232        resources:
   233          requests:
   234            cpu: 1000m
   235            memory: 1G
   236        replicaCount: 1
   237        nodeSelector:
   238          kubernetes.io/os: linux
   239        tolerations:
   240        - key: dedicated
   241          operator: Exists
   242          effect: NoSchedule
   243        - key: CriticalAddonsOnly
   244          operator: Exists
   245        autoscaleEnabled: true
   246        autoscaleMax: 3
   247        autoscaleMin: 1
   248        cpu:
   249          targetAverageUtilization: 80
   250        memory:
   251          targetAverageUtilization: 80
   252        traceSampling: 1.0
   253        image: pilot
   254        env:
   255          GODEBUG: gctrace=1
   256      global:
   257        hub: docker.io/istio
   258        tag: 1.2.3
   259        istioNamespace: istio-system
   260        proxy:
   261          readinessInitialDelaySeconds: 2
   262  `,
   263  			want: `
   264  spec:
   265    components:
   266      pilot:
   267        k8s:
   268          env:
   269          - name: EXTERNAL_CA
   270            value: ISTIOD_RA_KUBERNETES_API
   271          - name: K8S_SIGNER
   272            value: kubernetes.io/legacy-unknown
   273          - name: GODEBUG
   274            value: gctrace=1
   275          nodeSelector:
   276            master: "true"
   277            kubernetes.io/os: linux
   278          replicaCount: 1
   279          resources:
   280            requests:
   281              cpu: 1000m
   282              memory: 1G
   283          strategy:
   284            rollingUpdate:
   285              maxSurge: 100%
   286              maxUnavailable: 25%
   287          tolerations:
   288          - effect: NoSchedule
   289            key: dedicated
   290            operator: Exists
   291          - key: CriticalAddonsOnly
   292            operator: Exists
   293    values:
   294      global:
   295        hub: docker.io/istio
   296        tag: 1.2.3
   297        istioNamespace: istio-system
   298        proxy:
   299          readinessInitialDelaySeconds: 2
   300      pilot:
   301        enabled: true
   302        rollingMaxSurge: 100%
   303        rollingMaxUnavailable: 25%
   304        resources:
   305          requests:
   306            cpu: 1000m
   307            memory: 1G
   308        replicaCount: 1
   309        nodeSelector:
   310          kubernetes.io/os: linux
   311        tolerations:
   312        - key: dedicated
   313          operator: Exists
   314          effect: NoSchedule
   315        - key: CriticalAddonsOnly
   316          operator: Exists
   317        autoscaleEnabled: true
   318        autoscaleMax: 3
   319        autoscaleMin: 1
   320        cpu:
   321          targetAverageUtilization: 80
   322        memory:
   323          targetAverageUtilization: 80
   324        traceSampling: 1.0
   325        image: pilot
   326        env:
   327          GODEBUG: gctrace=1
   328  `,
   329  		},
   330  		{
   331  			desc: "pilot no env k8s setting with values",
   332  			inIOPSpec: `
   333  spec:
   334    components:
   335      pilot:
   336        k8s:
   337          nodeSelector:
   338            master: "true"
   339    values:
   340      pilot:
   341        enabled: true
   342        rollingMaxSurge: 100%
   343        rollingMaxUnavailable: 25%
   344        resources:
   345          requests:
   346            cpu: 1000m
   347            memory: 1G
   348        replicaCount: 1
   349        nodeSelector:
   350          kubernetes.io/os: linux
   351        tolerations:
   352        - key: dedicated
   353          operator: Exists
   354          effect: NoSchedule
   355        - key: CriticalAddonsOnly
   356          operator: Exists
   357        autoscaleEnabled: true
   358        autoscaleMax: 3
   359        autoscaleMin: 1
   360        cpu:
   361          targetAverageUtilization: 80
   362        memory:
   363          targetAverageUtilization: 80
   364        traceSampling: 1.0
   365        image: pilot
   366        env:
   367          GODEBUG: gctrace=1
   368      global:
   369        hub: docker.io/istio
   370        tag: 1.2.3
   371        istioNamespace: istio-system
   372        proxy:
   373          readinessInitialDelaySeconds: 2
   374  `,
   375  			want: `
   376  spec:
   377    components:
   378      pilot:
   379        k8s:
   380          env:
   381          - name: GODEBUG
   382            value: gctrace=1
   383          nodeSelector:
   384            master: "true"
   385            kubernetes.io/os: linux
   386          replicaCount: 1
   387          resources:
   388            requests:
   389              cpu: 1000m
   390              memory: 1G
   391          strategy:
   392            rollingUpdate:
   393              maxSurge: 100%
   394              maxUnavailable: 25%
   395          tolerations:
   396          - effect: NoSchedule
   397            key: dedicated
   398            operator: Exists
   399          - key: CriticalAddonsOnly
   400            operator: Exists
   401    values:
   402      global:
   403        hub: docker.io/istio
   404        tag: 1.2.3
   405        istioNamespace: istio-system
   406        proxy:
   407          readinessInitialDelaySeconds: 2
   408      pilot:
   409        enabled: true
   410        rollingMaxSurge: 100%
   411        rollingMaxUnavailable: 25%
   412        resources:
   413          requests:
   414            cpu: 1000m
   415            memory: 1G
   416        replicaCount: 1
   417        nodeSelector:
   418          kubernetes.io/os: linux
   419        tolerations:
   420        - key: dedicated
   421          operator: Exists
   422          effect: NoSchedule
   423        - key: CriticalAddonsOnly
   424          operator: Exists
   425        autoscaleEnabled: true
   426        autoscaleMax: 3
   427        autoscaleMin: 1
   428        cpu:
   429          targetAverageUtilization: 80
   430        memory:
   431          targetAverageUtilization: 80
   432        traceSampling: 1.0
   433        image: pilot
   434        env:
   435          GODEBUG: gctrace=1
   436  `,
   437  		},
   438  		{
   439  			desc: "pilot k8s setting with empty env in values",
   440  			inIOPSpec: `
   441  spec:
   442    components:
   443      pilot:
   444        k8s:
   445          nodeSelector:
   446            master: "true"
   447          env:
   448          - name: SPIFFE_BUNDLE_ENDPOINTS
   449            value: "SPIFFE_BUNDLE_ENDPOINT"
   450    values:
   451      pilot:
   452        enabled: true
   453        rollingMaxSurge: 100%
   454        rollingMaxUnavailable: 25%
   455        resources:
   456          requests:
   457            cpu: 1000m
   458            memory: 1G
   459        replicaCount: 1
   460        nodeSelector:
   461          kubernetes.io/os: linux
   462        tolerations:
   463        - key: dedicated
   464          operator: Exists
   465          effect: NoSchedule
   466        - key: CriticalAddonsOnly
   467          operator: Exists
   468        autoscaleEnabled: true
   469        autoscaleMax: 3
   470        autoscaleMin: 1
   471        cpu:
   472          targetAverageUtilization: 80
   473        memory:
   474          targetAverageUtilization: 80
   475        traceSampling: 1.0
   476        image: pilot
   477        env: {}
   478      global:
   479        hub: docker.io/istio
   480        tag: 1.2.3
   481        istioNamespace: istio-system
   482        proxy:
   483          readinessInitialDelaySeconds: 2
   484  `,
   485  			want: `
   486  spec:
   487    components:
   488      pilot:
   489        k8s:
   490          env:
   491          - name: SPIFFE_BUNDLE_ENDPOINTS
   492            value: "SPIFFE_BUNDLE_ENDPOINT"
   493          nodeSelector:
   494            master: "true"
   495            kubernetes.io/os: linux
   496          replicaCount: 1
   497          resources:
   498            requests:
   499              cpu: 1000m
   500              memory: 1G
   501          strategy:
   502            rollingUpdate:
   503              maxSurge: 100%
   504              maxUnavailable: 25%
   505          tolerations:
   506          - effect: NoSchedule
   507            key: dedicated
   508            operator: Exists
   509          - key: CriticalAddonsOnly
   510            operator: Exists
   511    values:
   512      global:
   513        hub: docker.io/istio
   514        tag: 1.2.3
   515        istioNamespace: istio-system
   516        proxy:
   517          readinessInitialDelaySeconds: 2
   518      pilot:
   519        enabled: true
   520        rollingMaxSurge: 100%
   521        rollingMaxUnavailable: 25%
   522        resources:
   523          requests:
   524            cpu: 1000m
   525            memory: 1G
   526        replicaCount: 1
   527        nodeSelector:
   528          kubernetes.io/os: linux
   529        tolerations:
   530        - key: dedicated
   531          operator: Exists
   532          effect: NoSchedule
   533        - key: CriticalAddonsOnly
   534          operator: Exists
   535        autoscaleEnabled: true
   536        autoscaleMax: 3
   537        autoscaleMin: 1
   538        cpu:
   539          targetAverageUtilization: 80
   540        memory:
   541          targetAverageUtilization: 80
   542        traceSampling: 1.0
   543        image: pilot
   544        env: {}
   545  `,
   546  		},
   547  		{
   548  			desc: "pilot no env k8s setting with multiple env variables in values",
   549  			inIOPSpec: `
   550  spec:
   551    components:
   552      pilot:
   553        k8s:
   554          nodeSelector:
   555            master: "true"
   556    values:
   557      pilot:
   558        enabled: true
   559        rollingMaxSurge: 100%
   560        rollingMaxUnavailable: 25%
   561        resources:
   562          requests:
   563            cpu: 1000m
   564            memory: 1G
   565        replicaCount: 1
   566        nodeSelector:
   567          kubernetes.io/os: linux
   568        tolerations:
   569        - key: dedicated
   570          operator: Exists
   571          effect: NoSchedule
   572        - key: CriticalAddonsOnly
   573          operator: Exists
   574        autoscaleEnabled: true
   575        autoscaleMax: 3
   576        autoscaleMin: 1
   577        cpu:
   578          targetAverageUtilization: 80
   579        memory:
   580          targetAverageUtilization: 80
   581        traceSampling: 1.0
   582        image: pilot
   583        env:
   584          PILOT_ENABLE_ISTIO_TAGS: false
   585          PILOT_ENABLE_LEGACY_ISTIO_MUTUAL_CREDENTIAL_NAME: false
   586          PROXY_XDS_DEBUG_VIA_AGENT: false
   587      global:
   588        hub: docker.io/istio
   589        tag: 1.2.3
   590        istioNamespace: istio-system
   591        proxy:
   592          readinessInitialDelaySeconds: 2
   593  `,
   594  			want: `
   595  spec:
   596    components:
   597      pilot:
   598        k8s:
   599          env:
   600          - name: PILOT_ENABLE_ISTIO_TAGS
   601            value: "false"
   602          - name: PILOT_ENABLE_LEGACY_ISTIO_MUTUAL_CREDENTIAL_NAME
   603            value: "false"
   604          - name: PROXY_XDS_DEBUG_VIA_AGENT
   605            value: "false"
   606          nodeSelector:
   607            master: "true"
   608            kubernetes.io/os: linux
   609          replicaCount: 1
   610          resources:
   611            requests:
   612              cpu: 1000m
   613              memory: 1G
   614          strategy:
   615            rollingUpdate:
   616              maxSurge: 100%
   617              maxUnavailable: 25%
   618          tolerations:
   619          - effect: NoSchedule
   620            key: dedicated
   621            operator: Exists
   622          - key: CriticalAddonsOnly
   623            operator: Exists
   624    values:
   625      global:
   626        hub: docker.io/istio
   627        tag: 1.2.3
   628        istioNamespace: istio-system
   629        proxy:
   630          readinessInitialDelaySeconds: 2
   631      pilot:
   632        enabled: true
   633        rollingMaxSurge: 100%
   634        rollingMaxUnavailable: 25%
   635        resources:
   636          requests:
   637            cpu: 1000m
   638            memory: 1G
   639        replicaCount: 1
   640        nodeSelector:
   641          kubernetes.io/os: linux
   642        tolerations:
   643        - key: dedicated
   644          operator: Exists
   645          effect: NoSchedule
   646        - key: CriticalAddonsOnly
   647          operator: Exists
   648        autoscaleEnabled: true
   649        autoscaleMax: 3
   650        autoscaleMin: 1
   651        cpu:
   652          targetAverageUtilization: 80
   653        memory:
   654          targetAverageUtilization: 80
   655        traceSampling: 1.0
   656        image: pilot
   657        env:
   658          PILOT_ENABLE_ISTIO_TAGS: false
   659          PILOT_ENABLE_LEGACY_ISTIO_MUTUAL_CREDENTIAL_NAME: false
   660          PROXY_XDS_DEBUG_VIA_AGENT: false
   661  `,
   662  		},
   663  		{
   664  			desc: "pilot k8s setting with multiple env variables in values",
   665  			inIOPSpec: `
   666  spec:
   667    components:
   668      pilot:
   669        k8s:
   670          nodeSelector:
   671            master: "true"
   672          env:
   673          - name: SPIFFE_BUNDLE_ENDPOINTS
   674            value: "SPIFFE_BUNDLE_ENDPOINT"
   675    values:
   676      pilot:
   677        enabled: true
   678        rollingMaxSurge: 100%
   679        rollingMaxUnavailable: 25%
   680        resources:
   681          requests:
   682            cpu: 1000m
   683            memory: 1G
   684        replicaCount: 1
   685        nodeSelector:
   686          kubernetes.io/os: linux
   687        tolerations:
   688        - key: dedicated
   689          operator: Exists
   690          effect: NoSchedule
   691        - key: CriticalAddonsOnly
   692          operator: Exists
   693        autoscaleEnabled: true
   694        autoscaleMax: 3
   695        autoscaleMin: 1
   696        cpu:
   697          targetAverageUtilization: 80
   698        memory:
   699          targetAverageUtilization: 80
   700        traceSampling: 1.0
   701        image: pilot
   702        env:
   703          PILOT_ENABLE_ISTIO_TAGS: false
   704          PILOT_ENABLE_LEGACY_ISTIO_MUTUAL_CREDENTIAL_NAME: false
   705          PROXY_XDS_DEBUG_VIA_AGENT: false
   706      global:
   707        hub: docker.io/istio
   708        tag: 1.2.3
   709        istioNamespace: istio-system
   710        proxy:
   711          readinessInitialDelaySeconds: 2
   712  `,
   713  			want: `
   714  spec:
   715    components:
   716      pilot:
   717        k8s:
   718          env:
   719          - name: SPIFFE_BUNDLE_ENDPOINTS
   720            value: "SPIFFE_BUNDLE_ENDPOINT"
   721          - name: PILOT_ENABLE_ISTIO_TAGS
   722            value: "false"
   723          - name: PILOT_ENABLE_LEGACY_ISTIO_MUTUAL_CREDENTIAL_NAME
   724            value: "false"
   725          - name: PROXY_XDS_DEBUG_VIA_AGENT
   726            value: "false"
   727          nodeSelector:
   728            master: "true"
   729            kubernetes.io/os: linux
   730          replicaCount: 1
   731          resources:
   732            requests:
   733              cpu: 1000m
   734              memory: 1G
   735          strategy:
   736            rollingUpdate:
   737              maxSurge: 100%
   738              maxUnavailable: 25%
   739          tolerations:
   740          - effect: NoSchedule
   741            key: dedicated
   742            operator: Exists
   743          - key: CriticalAddonsOnly
   744            operator: Exists
   745    values:
   746      global:
   747        hub: docker.io/istio
   748        tag: 1.2.3
   749        istioNamespace: istio-system
   750        proxy:
   751          readinessInitialDelaySeconds: 2
   752      pilot:
   753        enabled: true
   754        rollingMaxSurge: 100%
   755        rollingMaxUnavailable: 25%
   756        resources:
   757          requests:
   758            cpu: 1000m
   759            memory: 1G
   760        replicaCount: 1
   761        nodeSelector:
   762          kubernetes.io/os: linux
   763        tolerations:
   764        - key: dedicated
   765          operator: Exists
   766          effect: NoSchedule
   767        - key: CriticalAddonsOnly
   768          operator: Exists
   769        autoscaleEnabled: true
   770        autoscaleMax: 3
   771        autoscaleMin: 1
   772        cpu:
   773          targetAverageUtilization: 80
   774        memory:
   775          targetAverageUtilization: 80
   776        traceSampling: 1.0
   777        image: pilot
   778        env:
   779          PILOT_ENABLE_ISTIO_TAGS: false
   780          PILOT_ENABLE_LEGACY_ISTIO_MUTUAL_CREDENTIAL_NAME: false
   781          PROXY_XDS_DEBUG_VIA_AGENT: false
   782  `,
   783  		},
   784  		{
   785  			desc: "ingressgateway k8s setting with values",
   786  			inIOPSpec: `
   787  spec:
   788    components:
   789      pilot:
   790        enabled: false
   791      ingressGateways:
   792      - namespace: istio-system
   793        name: istio-ingressgateway
   794        enabled: true
   795        k8s:
   796          service:
   797            externalTrafficPolicy: Local
   798          serviceAnnotations:
   799            manifest-generate: "testserviceAnnotation"
   800          securityContext:
   801            sysctls:
   802            - name: "net.ipv4.ip_local_port_range"
   803              value: "80 65535"
   804    values:
   805      gateways:
   806        istio-ingressgateway:
   807          serviceAnnotations: {}
   808          nodeSelector: {}
   809          tolerations: []
   810      global:
   811        hub: docker.io/istio
   812        tag: 1.2.3
   813        istioNamespace: istio-system
   814  `,
   815  			want: `
   816  spec:
   817    components:
   818      ingressGateways:
   819      - name: istio-ingressgateway
   820        namespace: istio-system
   821        enabled: true
   822        k8s:
   823          securityContext:
   824            sysctls:
   825            - name: net.ipv4.ip_local_port_range
   826              value: "80 65535"
   827          service:
   828            externalTrafficPolicy: Local
   829          serviceAnnotations:
   830            manifest-generate: testserviceAnnotation
   831      pilot:
   832        enabled: false
   833    values:
   834      gateways:
   835        istio-ingressgateway:
   836          serviceAnnotations: {}
   837          nodeSelector: {}
   838          tolerations: []
   839      global:
   840        hub: docker.io/istio
   841        tag: 1.2.3
   842        istioNamespace: istio-system
   843  `,
   844  		},
   845  		{
   846  			desc: "pilot env k8s setting with non-empty hpa values",
   847  			inIOPSpec: `
   848  spec:
   849    revision: canary
   850    components:
   851      pilot:
   852        enabled: true
   853    values:
   854      pilot:
   855        autoscaleMin: 1
   856        autoscaleMax: 3
   857        cpu:
   858          targetAverageUtilization: 80
   859        memory:
   860          targetAverageUtilization: 80
   861  `,
   862  			want: `
   863  spec:
   864    revision: canary
   865    components:
   866      pilot:
   867        enabled: true
   868    values:
   869      pilot:
   870        autoscaleMin: 1
   871        autoscaleMax: 3
   872        cpu:
   873          targetAverageUtilization: 80
   874        memory:
   875          targetAverageUtilization: 80
   876  `,
   877  		},
   878  	}
   879  	tr := NewReverseTranslator()
   880  
   881  	for _, tt := range tests {
   882  		t.Run(tt.desc, func(t *testing.T) {
   883  			_, err := istio.UnmarshalIstioOperator(tt.inIOPSpec, false)
   884  			if err != nil {
   885  				t.Fatalf("unmarshal(%s): got error %s", tt.desc, err)
   886  			}
   887  			gotSpec, err := tr.TranslateK8SfromValueToIOP(tt.inIOPSpec)
   888  			if gotErr, wantErr := errToString(err), tt.wantErr; gotErr != wantErr {
   889  				t.Errorf("ValuesToK8s(%s)(%v): gotErr:%s, wantErr:%s", tt.desc, tt.inIOPSpec, gotErr, wantErr)
   890  			}
   891  			if tt.wantErr == "" {
   892  				if want := tt.want; !util.IsYAMLEqual(gotSpec, want) {
   893  					t.Errorf("ValuesToK8s(%s): got:\n%s\n\nwant:\n%s\nDiff:\n%s\n", tt.desc, gotSpec, want, util.YAMLDiff(gotSpec, want))
   894  				}
   895  			}
   896  		})
   897  	}
   898  }
   899  
   900  // errToString returns the string representation of err and the empty string if
   901  // err is nil.
   902  func errToString(err error) string {
   903  	if err == nil {
   904  		return ""
   905  	}
   906  	return err.Error()
   907  }