Helm .yaml file scanning is erroring

Running SonarCloud scanning of Helm .yaml files in an Azure DevOps .yaml pipeline

I’m seeing errors on several of the .yaml files. The actual error simply says: “Template evaluation failed”
Turning on verbose logging gives more detail, but confusingly the extra detail is referencing a different .yaml file!

The ‘other’ .yaml file gives the following (DEBUG) messages just before and after the ERROR message occurs in the logs.

The extra DEBUG messages mention this other .yaml file. No extra detail is provided about the file that actually errored!!

DEBUG: [sonar-helm-for-iac] Failed to read input: error reading content: strconv.Atoi: parsing "<other .yaml file>": invalid syntax
DEBUG: [sonar-helm-for-iac] Writing 110 bytes to stdout
**ERROR: Failed to evaluate Helm file Docker/helm/enterprise/templates/Config/<erroring .yaml file>: Template evaluation failed**
DEBUG: The pipe has been ended
DEBUG: org.sonar.iac.common.extension.ParseException: Failed to evaluate Helm file Docker/helm/enterprise/templates/Config/<erroring .yaml file>: Template evaluation failed

Any help that can get us to the point where our Helm .yaml files can be scanned without errors would be greatly appreciated!

More complete logs providing full context and call stack:

2024-04-17T18:01:09.8145357Z 18:01:09.813 DEBUG: Helm content detected in file 'Docker/helm/enterprise/templates/Config/serv-web-config.yaml'
2024-04-17T18:01:09.8195182Z 18:01:09.819 DEBUG: Executing: [C:\a\1\s\.scannerwork\.sonartmp\9999754383023744101\sonar-helm-for-iac-windows-amd64]
2024-04-17T18:01:09.8632895Z 18:01:09.862 DEBUG: [sonar-helm-for-iac] Reading 48 lines of file templates/Config/serv-web-config.yaml from stdin
2024-04-17T18:01:09.8633435Z 18:01:09.862 DEBUG: [sonar-helm-for-iac] Reading 69 lines of file templates/Deployment/serv-app-deployment.yaml from stdin
2024-04-17T18:01:09.8634192Z 18:01:09.862 DEBUG: [sonar-helm-for-iac] Failed to read input: error reading content: strconv.Atoi: parsing "templates/Deployment/serv-web-deployment.yaml": invalid syntax
2024-04-17T18:01:09.8635619Z 18:01:09.862 DEBUG: [sonar-helm-for-iac] Writing 110 bytes to stdout
2024-04-17T18:01:09.8693220Z ##[error]18:01:09.864 ERROR: Failed to evaluate Helm file Docker/helm/enterprise/templates/Config/serv-web-config.yaml: Template evaluation failed
2024-04-17T18:01:09.8694390Z 18:01:09.864 ERROR: Failed to evaluate Helm file Docker/helm/enterprise/templates/Config/serv-web-config.yaml: Template evaluation failed
2024-04-17T18:01:09.8694695Z 18:01:09.864 DEBUG: The pipe has been ended
2024-04-17T18:01:09.8695936Z 18:01:09.864 DEBUG: org.sonar.iac.common.extension.ParseException: Failed to evaluate Helm file Docker/helm/enterprise/templates/Config/serv-web-config.yaml: Template evaluation failed
2024-04-17T18:01:09.8696715Z at org.sonar.iac.kubernetes.plugin.HelmProcessor.parseExceptionFor(HelmProcessor.java:143)
2024-04-17T18:01:09.8697360Z at org.sonar.iac.kubernetes.plugin.HelmProcessor.evaluateHelmTemplate(HelmProcessor.java:138)
2024-04-17T18:01:09.8697617Z at org.sonar.iac.kubernetes.plugin.HelmProcessor.processHelmTemplate(HelmProcessor.java:95)
2024-04-17T18:01:09.8698154Z at org.sonar.iac.kubernetes.plugin.HelmProcessor.process(HelmProcessor.java:74)
2024-04-17T18:01:09.8698359Z at org.sonar.iac.kubernetes.plugin.KubernetesParser.evaluateAndParseHelmFile(KubernetesParser.java:148)
2024-04-17T18:01:09.8698697Z at org.sonar.iac.kubernetes.plugin.KubernetesParser.parseHelmFile(KubernetesParser.java:84)
2024-04-17T18:01:09.8698898Z at org.sonar.iac.kubernetes.plugin.KubernetesParser.lambda$parse$1(KubernetesParser.java:62)
2024-04-17T18:01:09.8699110Z at org.sonar.iac.kubernetes.plugin.KubernetesParserStatistics.recordHelmFile(KubernetesParserStatistics.java:43)
2024-04-17T18:01:09.8699318Z at org.sonar.iac.kubernetes.plugin.KubernetesParser.parse(KubernetesParser.java:62)
2024-04-17T18:01:09.8699506Z at org.sonar.iac.kubernetes.plugin.KubernetesParser.parse(KubernetesParser.java:38)
2024-04-17T18:01:09.8699699Z at org.sonar.iac.common.extension.IacSensor$Analyzer.lambda$analyseFile$0(IacSensor.java:217)
2024-04-17T18:01:09.8700206Z at org.sonar.iac.common.extension.DurationStatistics.time(DurationStatistics.java:75)
2024-04-17T18:01:09.8700412Z at org.sonar.iac.common.extension.IacSensor$Analyzer.analyseFile(IacSensor.java:215)
2024-04-17T18:01:09.8700606Z at org.sonar.iac.common.extension.IacSensor$Analyzer.analyseFiles(IacSensor.java:192)
2024-04-17T18:01:09.8700792Z at org.sonar.iac.common.extension.IacSensor.execute(IacSensor.java:111)
2024-04-17T18:01:09.8700972Z at org.sonar.scanner.sensor.AbstractSensorWrapper.analyse(AbstractSensorWrapper.java:62)
2024-04-17T18:01:09.8701168Z at org.sonar.scanner.sensor.ModuleSensorsExecutor.execute(ModuleSensorsExecutor.java:75)
2024-04-17T18:01:09.8701374Z at org.sonar.scanner.sensor.ModuleSensorsExecutor.lambda$execute$1(ModuleSensorsExecutor.java:48)
2024-04-17T18:01:09.8701586Z at org.sonar.scanner.sensor.ModuleSensorsExecutor.withModuleStrategy(ModuleSensorsExecutor.java:66)
2024-04-17T18:01:09.8701788Z at org.sonar.scanner.sensor.ModuleSensorsExecutor.execute(ModuleSensorsExecutor.java:48)
2024-04-17T18:01:09.8702368Z at org.sonar.scanner.scan.ModuleScanContainer.doAfterStart(ModuleScanContainer.java:64)
2024-04-17T18:01:09.8702574Z at org.sonar.core.platform.ComponentContainer.startComponents(ComponentContainer.java:123)
2024-04-17T18:01:09.8702776Z at org.sonar.core.platform.ComponentContainer.execute(ComponentContainer.java:109)
2024-04-17T18:01:09.8702968Z at org.sonar.scanner.scan.ProjectScanContainer.scan(ProjectScanContainer.java:192)
2024-04-17T18:01:09.8703164Z at org.sonar.scanner.scan.ProjectScanContainer.scanRecursively(ProjectScanContainer.java:188)
2024-04-17T18:01:09.8703710Z at org.sonar.scanner.scan.ProjectScanContainer.doAfterStart(ProjectScanContainer.java:159)
2024-04-17T18:01:09.8703902Z at org.sonar.core.platform.ComponentContainer.startComponents(ComponentContainer.java:123)
2024-04-17T18:01:09.8704100Z at org.sonar.core.platform.ComponentContainer.execute(ComponentContainer.java:109)
2024-04-17T18:01:09.8704294Z at org.sonar.scanner.bootstrap.ScannerContainer.doAfterStart(ScannerContainer.java:397)
2024-04-17T18:01:09.8704491Z at org.sonar.core.platform.ComponentContainer.startComponents(ComponentContainer.java:123)
2024-04-17T18:01:09.8704688Z at org.sonar.core.platform.ComponentContainer.execute(ComponentContainer.java:109)
2024-04-17T18:01:09.8704872Z at org.sonar.scanner.bootstrap.GlobalContainer.doAfterStart(GlobalContainer.java:125)
2024-04-17T18:01:09.8705066Z at org.sonar.core.platform.ComponentContainer.startComponents(ComponentContainer.java:123)
2024-04-17T18:01:09.8705325Z at org.sonar.core.platform.ComponentContainer.execute(ComponentContainer.java:109)
2024-04-17T18:01:09.8705778Z at org.sonar.batch.bootstrapper.Batch.doExecute(Batch.java:57)
2024-04-17T18:01:09.8706214Z at org.sonar.batch.bootstrapper.Batch.execute(Batch.java:51)
2024-04-17T18:01:09.8706661Z at org.sonarsource.scanner.api.internal.batch.BatchIsolatedLauncher.execute(BatchIsolatedLauncher.java:46)
2024-04-17T18:01:09.8706878Z at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103)
2024-04-17T18:01:09.8707063Z at java.base/java.lang.reflect.Method.invoke(Method.java:580)
2024-04-17T18:01:09.8707559Z at org.sonarsource.scanner.api.internal.IsolatedLauncherProxy.invoke(IsolatedLauncherProxy.java:60)
2024-04-17T18:01:09.8707771Z at jdk.proxy1/jdk.proxy1.$Proxy0.execute(Unknown Source)
2024-04-17T18:01:09.8708202Z at org.sonarsource.scanner.api.EmbeddedScanner.doExecute(EmbeddedScanner.java:189)
2024-04-17T18:01:09.8708671Z at org.sonarsource.scanner.api.EmbeddedScanner.execute(EmbeddedScanner.java:138)
2024-04-17T18:01:09.8708849Z at org.sonarsource.scanner.cli.Main.execute(Main.java:126)
2024-04-17T18:01:09.8709003Z at org.sonarsource.scanner.cli.Main.execute(Main.java:81)
2024-04-17T18:01:09.8709156Z at org.sonarsource.scanner.cli.Main.main(Main.java:62)

And here is the content of the 2 .yaml files in question:

serv-web-config (the file that is erroring):

apiVersion: v1
kind: ConfigMap
metadata:
  name: {{ .Release.Name }}-servicing-app
  namespace: default
  labels:
    app: {{ .Release.Name }}-servicing-app
data:
  {{- if .Values.servicingAppIdentifier -}}
  IDENTIFIER: {{ .Values.servicing | quote }}
  {{ else }}
  IDENTIFIER: {{ print .Values.identifierPrefix "_ServicingApp" | quote }}
  {{ end -}}
  {{- if or .Values.servicingRemotePath .Values.remotePath -}}
  {{ if .Values.servicingRemotePath -}}
  REMOTE_PATH: {{ .Values.servicingRemotePath | quote }}
  {{ else }}
  REMOTE_PATH: {{ print .Values.remotePath "\\Servicing" | squote }}
  {{ end }}
  {{- end }}
  CERTIFICATE_FILENAME: {{ coalesce (.Values.certs).appFileName (.Values.certs).filename | quote }}
  CERTIFICATE_PASSWORD: {{ coalesce (.Values.certs).appPassword (.Values.certs).password | quote }}
  CERTIFICATE_THUMBPRINT: {{ coalesce (.Values.certs).appThumbprint (.Values.certs).thumbprint | quote }}

  SERVICING_APP_SERVER_MACHINE_KEY: {{ (.Values.machineKeys).servicingApp | quote }}

  DB_ADMIN_USERID: {{ coalesce ((.Values.dbConnections).servicing).adminUserName (.Values.dbConnections).adminUserName | quote }}
  DB_ADMIN_PASSWORD: {{ coalesce ((.Values.dbConnections).servicing).adminPassword (.Values.dbConnections).adminPassword | quote }}

  {{- if or ((.Values.dbConnections).servicing).saPassword (.Values.dbConnections).saPassword }}
  DB_SA_PASSWORD: {{ coalesce ((.Values.dbConnections).servicing).saPassword (.Values.dbConnections).saPassword | quote }}
  {{- end }}

  {{- if (.Values.dbConnections).aspState }}

  ASP_STATE_SERVER: {{ coalesce (((.Values.dbConnections).aspState).servicingApp).server (((.Values.dbConnections).aspState).app).server (((.Values.dbConnections).aspState).servicing).server ((.Values.dbConnections).aspState).server (.Values.dbConnections).dbServer | quote }}
  {{- $instance := coalesce (((.Values.dbConnections).aspState).servicingApp).instance (((.Values.dbConnections).aspState).app).instance (((.Values.dbConnections).aspState).servicing).instance ((.Values.dbConnections).aspState).instance  }}
  {{- if $instance  }}
  ASP_STATE_INSTANCE: {{ $instance | quote }}
  {{- end }}
  ASP_STATE_DB_NAME: {{ coalesce (((.Values.dbConnections).aspState).servicingApp).dbName (((.Values.dbConnections).aspState).app).dbName (((.Values.dbConnections).aspState).servicing).dbName ((.Values.dbConnections).aspState).dbName | quote }}
  ASP_STATE_USERNAME: {{ coalesce (((.Values.dbConnections).aspState).servicingApp).userName (((.Values.dbConnections).aspState).app).userName (((.Values.dbConnections).aspState).servicing).userName ((.Values.dbConnections).aspState).userName | quote }}
  ASP_STATE_PASSWORD: {{ coalesce (((.Values.dbConnections).aspState).servicingApp).password (((.Values.dbConnections).aspState).app).password (((.Values.dbConnections).aspState).servicing).password ((.Values.dbConnections).aspState).password | quote }}
  {{- end }}

  {{- if and (.Values.dbConnections).seedData (coalesce (((.Values.dbConnections).seedData).servicing).enabled ((.Values.dbConnections).seedData).enabled) }}

  SEED_DATA_SERVICING_CONNECTION_STRING: {{ coalesce (((.Values.dbConnections).seedData).servicing).connectionString ((.Values.dbConnections).seedData).connectionString | quote }}
  {{- if or (((.Values.dbConnections).seedData).servicing).tag ((.Values.dbConnections).seedData).tag }}
  SEED_DATA_SERVICING_TAG: {{ coalesce (((.Values.dbConnections).seedData).servicing).tag ((.Values.dbConnections).seedData).tag | quote }}
  {{- end }}
  {{- if or (((.Values.dbConnections).seedData).servicing).instanceType ((.Values.dbConnections).seedData).instanceType }}
  SEED_DATA_SERVICING_INSTANCE_TYPE: {{ coalesce (((.Values.dbConnections).seedData).servicing).instanceType ((.Values.dbConnections).seedData).instanceType | quote }}
  {{- end }}
  {{- end -}}

  {{- if and .Values.dprEnvVars .Values.dprEnvVars.servicing }}
  {{ range $key, $val := .Values.dprEnvVars.servicing }}
  VAR_SETTING_{{ $key }}: {{ $val | quote }}
  {{- end -}}
  {{- end }}

  {{- if and .Values.dprEnvVars .Values.dprEnvVars.app }}
  {{ range $key, $val := .Values.dprEnvVars.app }}
  VAR_SETTING_{{ $key }}: {{ $val | quote }}
  {{- end -}}
  {{- end }}

  {{- if and .Values.dprEnvVars .Values.dprEnvVars.servicingApp }}
  {{ range $key, $val := .Values.dprEnvVars.servicingApp }}
  VAR_SETTING_{{ $key }}: {{ $val | quote }}
  {{- end -}}
  {{- end }}

serv-web-deployment (the other file mentioned in the verbose logs):

apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: {{ .Release.Name }}-servicing-web
  name: {{ .Release.Name }}-servicing-web
  namespace: default
spec:
  replicas: {{ coalesce (.Values.replicas).servicingWeb (.Values.replicas).all }}
  selector:
    matchLabels:
      app: {{ .Release.Name }}-servicing-web
  template:
    metadata:
      labels:
        app: {{ .Release.Name }}-servicing-web
    spec:
      securityContext:
        windowsOptions:
          gmsaCredentialSpecName: aks-gmsa-spec
      containers:
        - name: {{ .Release.Name }}-servicing-web
          {{- if (.Values.image).servicingWebFull }}
          image: {{ (.Values.image).servicingWebFull }}
          {{ else }}
          image: {{ print (.Values.image).repo "/" (.Values.image).name "_servicing-frontend:" (.Values.image).version }}
          {{ end -}}
          imagePullPolicy: Always
          resources:
            limits:
              memory: "25288Mi"
              cpu: "2"
            requests:
              memory: "2168Mi"
              cpu: "1"
          envFrom:
            - configMapRef:
                name: {{ .Release.Name }}-common
                optional: false
            - configMapRef:
                name: {{ .Release.Name }}-servicing-web
                optional: false
          volumeMounts:
            - name: azurefile
              mountPath: "Z:"
      affinity:
        nodeAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
            nodeSelectorTerms:
              - matchExpressions:
                  - key: appType
                    operator: In
                    values:
                      - {{ .Values.affinity }}
      tolerations:
      - key: "kubernetes.azure.com/scalesetpriority"
        operator: "Equal"
        value: "spot"
        effect: "NoSchedule" 
      volumes:
        - name: azurefile
          csi:
            driver: file.csi.azure.com
            volumeAttributes:
              secretName: dpr-disk-secret # required
              shareName: dprshares # required
              mountOptions: "dir_mode=0777,file_mode=0777,cache=strict,actimeo=30" # optional
      nodeSelector:
        kubernetes.io/os: windows

Hi @RIchardHart

Welcome to the community and thanks for reporting!

We are aware of this issue, see SONARIAC-1392. The different YAML file is referenced in logs because to evaluate the template, all files from the Chart directory are required to be read (similar to what the helm command is doing).

For now, I can only suggest to try to exclude the file from analysis, by setting:
sonar.exclusions=templates/Deployment/serv-web-deployment.yaml.

Best Regards
Marcin Stachniuk