O modelo do Helm não é compatível com a estrutura values.yaml

Aug 16 2020

Eu tenho o seguinte ingress.yaml:

spec:
{{- if .Values.ingress.tls }}
  tls:
  {{- range .Values.ingress.tls }}
    - hosts:
      {{- range .hosts }}
        - {{ . | quote }}
      {{- end }}
      secretName: {{ .secretName }}
  {{- end }}
{{- end }}
  rules:
  {{- range .Values.ingress.hosts }}
    - host: {{ .host }}                 // row 31
      http:
        paths:
        {{- range .paths }}
          - path: {{ . | quote }}
            backend:
              serviceName: {{ $fullName }}
              servicePort: {{ $svcPort }}
        {{- end }}
  {{- end }}
{{- end }}

E os seguintes valores para alimentar este template:

  hosts:
    host: "app.example.com"
    paths:
      - "/api"
      - "/oauth"

  tls:
    - secretName: "example-tls"
      hosts:
        - "*.app.example.com"
        - "dev.example.com"

Quando eu executo "helm install" ele falha em:

Erro: UPGRADE FAILED: template: templates/ingress.yaml:31:15: executando "templates/ingress.yaml" em <.host>: não é possível avaliar o host do campo na interface de tipo {}

Portanto, para mim, parece que os hosts devem ser uma lista, não um dicionário (devido à instrução de intervalo ). Então eu converto:

  hosts:
    - host: "app.example.com"
      paths:
        - "/api"
        - "/oauth"

Mas neste caso eu recebo:

aviso: o destino dos hosts é uma tabela. Ignorando valor não tabela [map[host:app.example.com paths:[/api /oauth]]]

e o mesmo erro acima em adição.

Como fazê-lo funcionar?

ATUALIZAÇÃO 1

Valores:

ingress:
  enabled: true

  rules:
    - host: c1.app.example.com
      paths:
        - /api
        - /oauth
    - host: c2.app.example.com
      paths:
        - /api
        - /oauth
  tls:
    - secretName: "example-tls"
      hosts:
        - "*.app.example.com"
        - "dev.example.com"

Modelo:

{{- if .Values.ingress.tls }}
  tls:
  {{- range .Values.ingress.tls }}
    - hosts:
      {{- range .hosts }}
        - {{ . | quote }}
      {{- end }}
      secretName: {{ .secretName }}
  {{- end }}
{{- end }}
  rules:
  {{- range .Values.ingress.rules }}
    - host: {{ .host | quote }}
      http:
        paths:
        {{- range .paths }}
          - path: {{ . | quote }}
            backend:
              serviceName: {{ $fullName }}
              servicePort: {{ $svcPort }}
        {{- end }}
  {{- end }}
{{- end }}

ATUALIZAÇÃO 2

Eu entendi que o problema não estava no código, mas na linha de comando. Eu alimentei com string em vez de array.

modelo de helm ... --set ingress.hosts.host=c1.app.example.com ...

Vou tentar descobrir como fornecer vários valores e atualizá-lo aqui.

ATUALIZAÇÃO 3

Eu apaguei os dados dos valores:

ingress:
  enabled: false

  rules:
    - host:

  tls:
    - secretName:
      hosts: []

Respostas

1 seshadri_c Aug 16 2020 at 15:36

O modelo está procurando por .Values.ingress.hosts, enquanto nos valores exibidos não há ingressprefixo. E como o rangeoperador está sendo usado, devemos ter uma lista de dicionário .

Além disso, antes de fazer um helm install, seria bom executar helm templateapenas para garantir que as definições YAML sejam renderizadas corretamente.

Considerando o conteúdo abaixo em values.yaml:

--- 
ingress: 
  hosts: 
    - 
      host: app1.example.com
      paths: 
        - /api
        - /oauth
    - 
      host: app2.example.com
      paths: 
        - /api1
        - /authz
  tls:
    - hosts:
      - "*.app.example.com"
      - "dev.example.com"
      secretName: "example-tls"

A execução helm templatedo comando resulta em (definido serviceNamecomo haproxy e servicePortcomo 8080 para ilustração):

spec:
  tls:
    - hosts:
        - "*.app.example.com"
        - "dev.example.com"
      secretName: example-tls
  rules:
    - host: app1.example.com                 // row 31
      http:
        paths:
          - path: "/api"
            backend:
              serviceName: haproxy
              servicePort: 8080
          - path: "/oauth"
            backend:
              serviceName: haproxy
              servicePort: 8080
    - host: app2.example.com                 // row 31
      # similar output for app2.example.com

1 MichaelA. Aug 27 2020 at 00:13

Respondendo a minha própria pergunta.

O problema estava na incompatibilidade da estrutura do modelo de entrada e nos argumentos da linha de comando que forneci para substituição de parâmetros.

Este é o ajuste adequado dos argumentos da linha de comando :

helm upgrade <some other options here>
--values ./values.yaml
--set ingress.enabled=True
--set ingress.tls[0].hosts[0]=app.example.com
--set ingress.tls[0].secretName=example-tls
--set ingress.rules[0].host=app.example.com

Isso preenche values.yaml :

ingress:
  enabled: false

  rules:
    - host:

  tls:
    - secretName:
      hosts: []

Para o modelo de entrada :

spec:
{{- if .Values.ingress.tls }}
  tls:
  {{- range .Values.ingress.tls }}
    - secretName: {{ .secretName }}
      hosts:
      {{- range .hosts }}
        - {{ . | quote }}
      {{- end }}
  {{- end }}
{{- end }}
  rules:
  {{- range .Values.ingress.rules }}
    - host: {{ .host | quote }}
      http:
        paths:
        - path: /api
          backend:
            serviceName: {{ $fullName }}
            servicePort: {{ $svcPort }}
  {{- end }}
{{- end }}