Error calling eq incompatible types for comparison

I was going through the getting started and in the section on flow control and if a value is commented out in my values.yaml (in this case the drink attribute), adding flow control eq operator thro...

Just leaving a comment here since between #6376 and this issue, this is the one that’s more obviously related to the Chart Template Guide / getting started example, and as of Helm 3.5.2 and today’s guide, the guide has the same issue. I ran through all the suggestions in #6376 and this issue to understand what works and what doesn’t, a good learning experience for a Helm newbie like myself. FWIW:

Variations that work in Helm 3.5.2 (personally I think the first variation is easiest to understand):

  {{if eq (.Values.favorite.drink | default "") "coffee"}}mug: "true"{{ end }}

  {{ if eq (default "" .Values.favorite.drink) "coffee" }}mug: "true"{{ end }}

  {{if eq (.Values.favorite.drink | toString) "coffee"}}mug: "true"{{ end }}

{{- if .Values.favorite.drink }}
{{- if eq .Values.favorite.drink "coffee" }}
  mug: "true"
{{- end }}
{{- end }}

Variations with error calling eq: incompatible types for comparison (the first variation is the one from the Chart Template Guide):

  {{ if eq .Values.favorite.drink "coffee" }}mug: "true"{{ end }}

  {{ if eq (default .Values.favorite.drink "") "coffee" }}mug: "true"{{ end }}

  {{- if and (.Values.favorite.drink) (eq .Values.favorite.drink "coffee") }}mug: "true"{{ end }}

Variation with drink is not a method but has arguments:

  {{ if .Values.favorite.drink and eq .Values.favorite.drink "coffee" }}mug: "true"{{ end }}

Variation with can't give argument to non-function .Values.favorite.drink:

  {{ if ( .Values.favorite.drink ) and eq .Values.favorite.drink "coffee" }}mug: "true"{{ end }}

I have to check if my application container in a replication controller runs on a certain port. Here is the command with the go template string that I’m using.

kubectl get rc my-rc --namespace=nightly --template='{{range .spec.template.spec.containers}}{{if .ports}}{{range .ports}}{{if .containerPort}}{{if eq .containerPort 5445}}{{end}}{{end}}{{end}}{{end}}{{end}}'

I think it is not a string comparison since it is a port. even string comparison throws an error «error calling eq: incompatible types for comparison'»

I could just fetch an array of container ports and do the comparison outside but want to get it done inside the go template.

I am new to Go lang. Appreciate any suggestions to accomplish this using template string or using a template file.. Thanks

asked Mar 5, 2016 at 18:34

Srikanth's user avatar

Inspecting the .containerPort with printf "%T" .containerPort shows that it’s a float64. if you compare your port with a trailing 5445.0 it should work.

You also have some unnecessary if statements.

--template='{{range .spec.template.spec.containers}}{{range .ports}}{{if eq .containerPort 5445.0}}True{{end}}{{end}}{{end}}'

Your example was also missing the -o="go-template" flag to specify the output as a Go template.

answered Mar 5, 2016 at 18:47

jmaloney's user avatar

jmaloneyjmaloney

11.2k2 gold badges36 silver badges29 bronze badges

2

У меня есть шаблон диаграммы, содержащий эту строку

  {{- if eq $.Values.global.environment "dev" }}

При запуске helm lint это не удается:

> helm lint my-services/
==> Linting my-services/
[INFO] Chart.yaml: icon is recommended
[ERROR] templates/: render error in "my-services/templates/istio-gateway.yaml": template: acquiring-services/templates/istio-gateway.yaml:64:9: executing "my-services/templates/istio-gateway.yaml" at <eq $.Values.global.e...>: error calling eq: invalid type for comparison

Интересно, что у меня такое же сравнение — только с другой строкой — в строке 8, что совсем не проблема. Удаление ошибочной линии способствует успешному прохождению ворса

helm lint my-services/
==> Linting my-services/
[INFO] Chart.yaml: icon is recommended

1 chart(s) linted, no failures

Вот соответствующий yaml -файл:

kind: VirtualService
metadata:
  name: acquiring-gateway-virtualservice
  namespace: {{ default $.Release.Namespace }}
spec:
  hosts:
  {{- if eq $.Release.Namespace $.Values.global.defaultNamespace }}
  {{- if eq $.Values.global.environment "prd" }}
  - {{ $.Values.global.ingressName }}.{{$.Values.global.environment}}.sc.intra
  {{- else }}
  - {{ $.Values.global.ingressName }}.svc.{{$.Values.global.environment}}.sc.intra
  {{- end }}
  {{- else }}
  - {{ $.Values.global.ingressName }}-{{ default $.Release.Namespace }}.svc.{{$.Values.global.environment}}.sc.intra
  {{- end }}
  gateways:
  - acquiring-gateway
  http:
  - match:
    - uri:
        prefix: /uaa

        prefix: /uaa/
    route:
    - destination:
        port:
          number: 80
        host: auth-server.{{ $.Release.Namespace }}.svc.cluster.local
    corsPolicy:
      allowOrigin:
      - '*'
      allowMethods:
      - OPTIONS
        - GET
        - PUT
        - POST
        - PATCH
      allowHeaders:
      - authorization

  {{- if eq $.Values.global.environment "dev" }}
  - match:

Также следование предложению под # 2979 не помогает

Вывод helm version :

Client: &version.Version{SemVer:"v2.12.3", GitCommit:"eecf22f77df5f65c823aacd2dbd30ae6c65f186e", GitTreeState:"clean"}
Server: &version.Version{SemVer:"v2.12.3", GitCommit:"eecf22f77df5f65c823aacd2dbd30ae6c65f186e", GitTreeState:"clean"}

Вывод kubectl version :

N / A

Облачный провайдер / платформа (AKS, GKE, Minikube и т. Д.):

На месте

Все 11 Комментарий

Когда global.environment не задано, устанавливается значение nil . Строка и значение nil являются несовместимыми типами, поэтому их нельзя сравнивать на равенство.

Вероятно, вам нужно следующее:

{{- if eq (default $.Values.global.environment "prod") "dev" }}

Таким образом, если global.environment не задано, оно все равно сравнивается со строковым значением.

Если значения считаются «необязательными», диаграмма должна сначала проверить и определить, не установлено ли значение.

Это поможет?

Я предполагаю, что логика оценки текста / шаблона будет заключаться в том, что если первый оператор if оценивается как ложный, то ветвь закорачивается. Первый оператор if мог никогда не выполняться.

Хорошо, если я сделаю это

#{{- if eq $.Release.Namespace $.Values.global.defaultNamespace }}
{{- if eq $.Values.global.environment "prd" }}
- {{ $.Values.global.ingressName }}.{{$.Values.global.environment}}.sc.intra
{{- else }}
- {{ $.Values.global.ingressName }}.svc.{{$.Values.global.environment}}.intra
{{- end }}
#{{- else }}
#- {{ $.Values.global.ingressName }}-{{ default $.Release.Namespace }}.svc.{{$.Values.global.environment}}.intra
#{{- end }}

lint не жалуется.

helm template тоже жаловался? Мне также любопытно, можно ли это воспроизвести сейчас, когда мы компилируем с Go 1.14, поскольку это почти на 100% проблема с методом Go text/template оценки условного оператора.

Если мы сможем свести это к минимально воспроизводимому случаю, я, возможно, смогу проследить его дальше. И это гораздо интереснее, если lint терпит неудачу, а template — нет.

Для чего это стоит. Я вижу, как мне кажется, ту же проблему:
Error: UPGRADE FAILED: template: ota-tdx/templates/kong-consumers.yaml:30:44: executing "ota-tdx/templates/kong-consumers.yaml" at <eq .Values.app.configMap.DEMO_MODE "1">: error calling eq: incompatible types for comparison

Мой шаблон шлема

{{- if and (.Values.app.configMap.DEMO_MODE) (eq .Values.app.configMap.DEMO_MODE "1") }}

Версия Helm

version.BuildInfo{Version:"v3.3.0", GitCommit:"8a4aeec08d67a7b84472007529e8097ec3742105", GitTreeState:"dirty", GoVersion:"go1.14.7"}

Обходной путь (СУПЕР УЖАСНО ВСТАВЛЕННЫЙ !!!!: sob:)

-{{- if (.Values.app.configMap.DEMO_MODE) and eq .Values.app.configMap.DEMO_MODE "1" }}
+{{- if .Values.app.configMap.DEMO_MODE }}
+{{- if eq .Values.app.configMap.DEMO_MODE "1" }}
...
-{{- end }}
+{{- end }}
+{{- end }}

@bclouser Я if оператор and будет работать на большинстве языков, но я не уверен, виноват ли здесь Helm или Go.

Это будет ограничение, установленное с помощью text/template , который является языком шаблонов, используемым Helm для визуализации шаблонов. Так что это ограничение, установленное разработчиками Go.

https://golang.org/pkg/text/template/

Заключение, поскольку это то, что мы не можем изменить … Скорее это дизайнерское решение, принятое авторами Go. Я предложил обходной путь, который представляет собой все, что мы можем сделать на данный момент. Если другие нашли другие решения, опубликуйте их здесь. Спасибо!

Спасибо за ссылку @bacongobbler.

Действительно, отрывок из документации для and гласит:

Returns the boolean AND of its arguments by returning the
    first empty argument or the last argument, that is,
    "and x y" behaves as "if x then y else x". All the
    arguments are evaluated.

Я могу подтвердить, что обходной путь if eq (default <.variable> <fallback_value>) <comparison_value> работает.

Насколько я могу судить, рекомендуемый обходной путь неверен. default принимает резервное значение в качестве первого аргумента, а не второго:

В шаблонах часто используется функция default function: default DEFAULT_VALUE GIVEN_VALUE .

https://helm.sh/docs/chart_template_guide/functions_and_pipelines/#using -the-default-function

Т.е. должно быть:

{{- if eq (default "prod" $.Values.global.environment) "dev" }}

и нет:

{{- if eq (default $.Values.global.environment "prod") "dev" }}

Другой (более интуитивный) синтаксис:

{{- if eq ($.Values.global.environment | default "prod") "dev" }}

PS Я не понимаю, как опция if eq (default <.variable> <fallback_value>) <comparison_value> могла работать в тесте @phillycheeze .

Была ли эта страница полезной?

0 / 5 — 0 рейтинги

Article ID:360035987652

1 minute readKnowledge base

Issue

  • I have an issue when installing / upgrading CloudBees Core from the cloudbees/cloudbees-core helm chart:

Error: render error in "cloudbees-core/templates/cjoc-statefulset.yaml": template: cloudbees-core/templates/cjoc-statefulset.yaml:119:24: executing "cloudbees-core/templates/cjoc-statefulset.yaml" at <eq .Values.OperationsCenter.RunAsUser 0.0>: error calling eq: incompatible types for comparison

Environment

  • CloudBees CI (CloudBees Core) on Modern Cloud Platforms

  • Helm 2.15.0

Related Issue(s)

  • helm/helm issue #6708

  • helm/helm PR #6010 (Regression)

  • helm/helm PR #6749 (Fix)

Resolution

There is a known issue helm issue #6708 introduced in Helm / Tiller 2.15.0 that causes template generation to fail when comparing numeric value types.
This issue has been fixed in Helm / Tiller 2.15.1.

The solution is to:

  • Upgrade helm (client) to version 2.15.1 or later (the method depends on how it is installed)

  • Upgrade tiller (server) with helm init --upgrade

I have a chart template which contains this line

  {{- if eq $.Values.global.environment "dev" }}

When running helm lint this fails:

> helm lint my-services/
==> Linting my-services/
[INFO] Chart.yaml: icon is recommended
[ERROR] templates/: render error in "my-services/templates/istio-gateway.yaml": template: acquiring-services/templates/istio-gateway.yaml:64:9: executing "my-services/templates/istio-gateway.yaml" at <eq $.Values.global.e...>: error calling eq: invalid type for comparison

Interestingly I have the same comparison — just with another string — in line 8, which is not a problem at all. Removing the erronous line makes lint passing successfully

helm lint my-services/
==> Linting my-services/
[INFO] Chart.yaml: icon is recommended

1 chart(s) linted, no failures

Here the relevant yaml-file:

kind: VirtualService
metadata:
  name: acquiring-gateway-virtualservice
  namespace: {{ default $.Release.Namespace }}
spec:
  hosts:
  {{- if eq $.Release.Namespace $.Values.global.defaultNamespace }}
  {{- if eq $.Values.global.environment "prd" }}
  - {{ $.Values.global.ingressName }}.{{$.Values.global.environment}}.sc.intra
  {{- else }}
  - {{ $.Values.global.ingressName }}.svc.{{$.Values.global.environment}}.sc.intra
  {{- end }}
  {{- else }}
  - {{ $.Values.global.ingressName }}-{{ default $.Release.Namespace }}.svc.{{$.Values.global.environment}}.sc.intra
  {{- end }}
  gateways:
  - acquiring-gateway
  http:
  - match:
    - uri:
        prefix: /uaa

        prefix: /uaa/
    route:
    - destination:
        port:
          number: 80
        host: auth-server.{{ $.Release.Namespace }}.svc.cluster.local
    corsPolicy:
      allowOrigin:
      - '*'
      allowMethods:
      - OPTIONS
        - GET
        - PUT
        - POST
        - PATCH
      allowHeaders:
      - authorization

  {{- if eq $.Values.global.environment "dev" }}
  - match:

Also following the suggestion under #2979 does not help

Output of helm version:

Client: &version.Version{SemVer:"v2.12.3", GitCommit:"eecf22f77df5f65c823aacd2dbd30ae6c65f186e", GitTreeState:"clean"}
Server: &version.Version{SemVer:"v2.12.3", GitCommit:"eecf22f77df5f65c823aacd2dbd30ae6c65f186e", GitTreeState:"clean"}

Output of kubectl version:

N/A

Cloud Provider/Platform (AKS, GKE, Minikube etc.):

On-Premise

News

March 23, 2015

11 minutes Read

Most Docker users are aware of the docker inspect command which is used to get metadata on a container or image, and may have used the -f argument to pull out some specific data, for example using docker inspect -f to get a container’s IP Address. However, a lot of users seem confused by the syntax of this feature and very few people take full advantage of it (most people seem to pipe the output through grep, which is effective but messy). In this post, I’ll look into how the -f argument works and show some examples of how to use it.

Put simply, the -f argument takes a Go template as input and runs it against the metadata for the given containers or images. The first problem is the phrase «Go template» is rather nebulous, at least to anyone inexperienced in Go — my first feeling was atavistic fear from the memory of C++ templates. Thankfully, Go templates has nothing in common with C++ templates or generics, and is in fact a template engine that takes a data source and a template pattern and combines the two to produce an output document. This idea should be very familiar to most web developers and common examples of template engines include Jinga2 (commonly used with Python and Flask), Mustache and JavaServer Pages. The concept is perhaps best explained by a simple example:

  
docker inspect -f 'Hello from container ' jenkins
(out) Hello from container /jenkins

As we can see, the argument to -f is a simple pattern (or template) that we want to apply to the metadata of container. In fact, we don’t even have to do anything with the metadata:

  
docker inspect -f "This is a bit pointless" jenkins
(out) This is a bit pointless

But, if we learn a bit of Go templating magic, things that were once tricky become much simpler. For example, to find the names of all containers with a non-zero exit code:



docker inspect -f ' ' $(docker ps -aq)
(out) /tender_colden 1
(out) /clever_mcclintock 126
(out) # <- empty line
(out) /grave_bartik 1

(Unfortunately Docker prints a new-line for each container, whether it matches the if or not).

Or to find the host directory for the volume /var/jenkins_home in my jenkins-data container:

  
docker inspect -f '' jenkins-data
(out) /var/lib/docker/vfs/dir/5a6f7b306b96af38723fc4d31def1cc515a0d75c785f3462482f60b730533b1a

At the moment, both of these examples are probably a little hard to parse. There are a few basics you need to understand before you can get started with your own templates.

Directives

The syntax is used for processing directives. Anything outside of the curly brackets will be output literally.

The . Context

A «.» stands for the «current context». Most of the time this is the whole data structure for the metadata of the container, but it can be rebound in certain cirumstances, including using the with action:

  
docker inspect -f '' jenkins
(out) 6331
docker inspect -f '  ' jenkins
(out) 6331

You can always get the root context by using $. e.g.

  
docker inspect -f '  has pid  ' jenkins
(out) /jenkins has pid 6331

Note that it is perfectly valid to use a «.» by itself, the following will just output the full data completely unformatted:

  
docker inspect -f '' jenkins
(out) ...

Data Types

The inspect data seems to consist of floats, strings and booleans. These can be tested and compared using various functions. At the moment, it seems that all numbers are floats, although Go templates do support integers, which would seem to be more appropriate in most cases (I’ve submitted an issue about this). Use double quotes when working with strings.

Values which appear as «null» appear to be not present in the data at all, and can’t be compared:

  
docker inspect -f '' jenkins
(out) NO VALUE HERE!
docker inspect -f '' jenkins
(out) FATA[0000] template: :1:2: executing "" at eq .ExecIDs .ExecIDs: error calling eq: invalid type for comparison

Data Structures

The inspect data uses maps and arrays. Maps are normally easy, you can just chain stuff together to access inner maps as we’ve seen already:

  
docker inspect -f '' jenkins
(out) 0

However, this isn’t possible if the key for the map isn’t in a suitable format (for example, if it uses a non alphanumeric character). If that’s the case, you can use the index function as we did in the volumes example:

  
docker inspect -f '' jenkins-data
(out) /var/lib/docker/vfs/dir/5a6f7b306b96af38723fc4d31def1cc515a0d75c785f3462482f60b730533b1a

You can also use index to get an array entry by number:

  
docker inspect -f '' jenkins
(out) [/var/run/docker.sock:/var/run/docker.sock /usr/bin/docker:/usr/bin/docker]
docker inspect -f '' jenkins
(out) /usr/bin/docker:/usr/bin/docker

Functions

Apart from index, there are a few more functions that are likely to be useful. The logical functions and, or and not are available and operate largely as expected, returning a boolean result. Note that as they are functions, they cannot be used infix i.e:

  
docker inspect -f '' jenkins
(out) true

Not:

  
docker inspect -f 'true' jenkins
(out) FATA[0000] template: :1:2: executing "" at <true>: can't give argument to non-function true

The following comparison functions are available:

  • eq (equals)
  • ne (not equal)
  • lt (less than)
  • le (less than or equal to)
  • gt (greater than)
  • ge (greater than or equal to)

They can compare strings, floats or integers:

  
docker inspect -f '' jenkins
(out) true
docker inspect -f '' jenkins
(out) true
docker inspect -f '' jenkins
(out) true
$ docker inspect -f '' jenkins
(out) false

But note that output types have to match, and numbers in Docker seem to be all floats, despite how they are printed:

  
docker inspect -f '' jenkins
(out) FATA[0000] template: :1:2: executing "" at <eq "4.5" 4.5>: error calling eq: incompatible types for comparison
docker inspect -f '' jenkins
(out) FATA[0000] template: :1:2: executing "" at <gt .State.Pid 1>: error calling gt: incompatible types for comparison 
docker inspect -f '' jenkins
(out) true

UPDATE: This seems to have been fixed; now both integers and floats will work correctly e.g:

  
docker inspect -f '' redis
(out) true
docker inspect -f '' redis
(out) true

(This was tested in Docker 1.7).

There is also a json function for generating JSON:

  
docker inspect -f '' jenkins
(out) {"50000/tcp":null,"8080/tcp":[{"HostIp":"0.0.0.0","HostPort":"8080"}]}

So you can combine templates with the jq tool, which you may be more familiar with:

  
docker inspect -f json .State}}' jenkins-data | jq '.StartedAt'
(out) "2015-03-15T20:26:30.526796706Z"

Of course, the default output of docker inspect is also JSON, so this also works:

  
docker inspect jenkins-data | jq '.[] | .State.StartedAt'
(out) "2015-03-15T20:26:30.526796706Z"

There are a few more functions listed in the official Go documentation, but it weirdly seems to be missing the json function (which I learnt from Nathan LeClaire’s blog) — if someone knows the reason for this, please let me know!

If Statements

Conditional statements can be handled with an if statement and normally use one of the previous comparison functions:

  
docker inspect -f ' 
Normal Exit
 
Not a Normal Exit 
 
Still Not a Normal Exit 
' jenkins
(out) Normal Exit

Note the statement is required to terminate the if. The else if and else parts are optional.

Conclusion

I think this covers most of the stuff you are likely to need when using templates with docker inspect, but there are more features available, such as using range to iterate over data, defining your own functions and using pipes.

I have yet to find a good, complete reference to using Go templates. The best I have found so far is a chapter from a the free e-book «Network programming with Go» by Jan Newmarch.

There is also the official Go documentation, but it is little terse and hard to follow, especially if you’re not a Go programmer.

Понравилась статья? Поделить с друзьями:
  • Error calling context method 1c
  • Error calling callablestatement getmoreresults
  • Error calling api lsacallauthenticationpackage ticket granting ticket substatus 1312
  • Error called object is not a function or function pointer
  • Error callback was already called