Helm debug unknown field - kubernetes

I'm trying to install Kritis using :
azureuser#Azure:~/kritis/docs/standalone$ helm install kritis https://storage.googleapis.com/kritis-charts/repository/kritis-charts-0.2.0.tgz --set certificates.ca="$(cat ca.crt)" --set certificates.cert="$(cat kritis.crt)" --set certificates.key="$(cat kritis.key)" --debug
But I'm getting the next error:
install.go:148: [debug] Original chart version: ""
install.go:165: [debug] CHART PATH: /home/azureuser/.cache/helm/repository/kritis-charts-0.2.0.tgz
Error: unable to build kubernetes objects from release manifest: error validating "": error validating data: ValidationError(ClusterRole.metadata): unknown field "kritis.grafeas.io/install" in io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta
helm.go:76: [debug] error validating "": error validating data: ValidationError(ClusterRole.metadata): unknown field "kritis.grafeas.io/install" in io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta
helm.sh/helm/v3/pkg/kube.scrubValidationError
/home/circleci/helm.sh/helm/pkg/kube/client.go:520
helm.sh/helm/v3/pkg/kube.(*Client).Build
/home/circleci/helm.sh/helm/pkg/kube/client.go:135
Is there a way to know exactly on which file the error is being triggered? and what exactly that error means?
The original chart files are available here : https://github.com/grafeas/kritis/blob/master/kritis-charts/templates/preinstall/clusterrolebinding.yaml

You cant get from where exactly this coming from but this output is giving some clues regarding that.
In your error message we have some useful information:
helm.go:76: [debug] error validating "": error validating data: ValidationError(ClusterRole.metadata): unknown field "kritis.grafeas.io/install" in io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta
error validating ""
ClusterRole
kritis.grafeas
You can download your chart and dig into it for these terms using cat as follows:
$ wget https://storage.googleapis.com/kritis-charts/repository/kritis-charts-0.2.0.tgz
$ tar xzvf kritis-charts-0.2.0.tgz
$ cd kritis-charts/
If your grep for kritis.grafeas.io/install, you can see a "variable" being set:
$ grep -R "kritis.grafeas.io/install" *
values.yaml:kritisInstallLabel: "kritis.grafeas.io/install"
Now we can grep this variable and check what we can find:
$ grep -R "kritisInstallLabel" *
templates/rbac.yaml: {{ .Values.kritisInstallLabel }}: ""
templates/rbac.yaml: {{ .Values.kritisInstallLabel }}: ""
templates/kritis-server-deployment.yaml: {{ .Values.kritisInstallLabel }}: ""
templates/preinstall/pod.yaml: {{ .Values.kritisInstallLabel }}: ""
templates/preinstall/pod.yaml: - {{ .Values.kritisInstallLabel }}
templates/preinstall/serviceaccount.yaml: {{ .Values.kritisInstallLabel }}: ""
templates/preinstall/clusterrolebinding.yaml: {{ .Values.kritisInstallLabel }}: ""
templates/postinstall/pod.yaml: {{ .Values.kritisInstallLabel }}: ""
templates/postinstall/pod.yaml: - {{ .Values.kritisInstallLabel }}
templates/secrets.yaml: {{ .Values.kritisInstallLabel }}: ""
templates/predelete/pod.yaml: {{ .Values.kritisInstallLabel }}: ""
templates/kritis-server-service.yaml: {{ .Values.kritisInstallLabel }}: ""
values.yaml:kritisInstallLabel: "kritis.grafeas.io/install"
In this output we can see a rbac.yaml file. That matches with one of the terms we are looking for (ClusterRole):
If we read this file, we can see the ClusterRole and a line referring to kritisInstallLabel:
- apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRoleBinding
metadata:
name: {{ .Values.clusterRoleBindingName }}
labels:
{{ .Values.kritisInstallLabel }}: ""
{{ .Values.kritisInstallLabel }}: "" will be translated as .Values.kritis.grafeas.io/install by helm and that's where your error is coming from.

Related

Helm not using values override?

I'm using sub-charts. Here's my directory structure
/path/microservice-base-chart
/path/myApp
I have this values.yaml for my "base" (generic) chart
# Default region and repository
aws_region: us-east-1
repository: 012234567890.dkr.ecr.us-east-1.amazonaws.com
repositories:
us-east-1: 01234567890.dkr.ecr.us-east-1.amazonaws.com
eu-north-1: 98765432109.dkr.ecr.eu-north-1.amazonaws.com
image:
name: ""
version: ""
...and this in the base chart's templates/_helpers.yaml file
{{/*
Get the repository from the AWS region
*/}}
{{- define "microservice-base-chart.reponame" -}}
{{- $repo := index .Values.repositories .Values.aws_region | default .Values.repository }}
{{- printf "%s" $repo }}
{{- end }}
...and this in the base chart's templates/deployment.yaml file
apiVersion: apps/v1
kind: Deployment
...
spec:
...
template:
...
spec:
...
containers:
- name: {{ .Values.image.name }}
image: {{ include "microservice-base-chart.reponame" . }}/{{ .Values.image.name }}:{{ .Values.image.version }}
I have this in the Chart.yaml of a sub chart that uses the base chart.
dependencies:
- alias: microservice-0
name: microservice-base-chart
version: "0.1.0"
repository: file://../microservice-base-chart
...and this in the values.yaml of a sub chart
microservice-0:
image:
name: myApp
version: 1.2.3
However, when I run this, where I set aws_region
$ helm install marcom-stats-svc microservice-chart/ \
--set image.aws_region=eu-north-1 \
--set microservice-0.image.version=2.0.0 \
--dry-run --debug
I get this for the image name of the above deployment.yaml template
image: 01234567890.dkr.ecr.us-east-1.amazonaws.com/myApp:2.0.0
instead of the expected
image: 98765432109.dkr.ecr.eu-north-1.amazonaws.com/myApp:2.0.0
What am I missing? TIA

In a Helm template function, how can I iterate through a dictionary, and return the value of a key?

I have the following values.yaml file
# Default region and repository
aws_region: us-east-1
repository: 01234567890.dkr.ecr.us-east-1.amazonaws.com
repositories:
us-east-1: 01234567890.dkr.ecr.us-east-1.amazonaws.com
eu-north-1: 98765432109.dkr.ecr.eu-north-1.amazonaws.com
image:
name: "ms-0"
...
I wrote a function to return the value from the repositories dictionary based on the key, which is an AWS region.
{{/*
Get the repository from the AWS region
*/}}
{{- define "microservice-base-chart.reponame" -}}
{{- $repo := default .Values.repository }}
{{- range $key, $value := .Values.repositories }}
{{- if .eq $key .Values.aws_region }}
{{- $repo = $value }}
{{- end }}
{{- end }}
{{- printf "%s" $repo }}
{{- end }}
And then I want to use the function in, say my deployment.yaml template
apiVersion: apps/v1
kind: Deployment
...
spec:
...
template:
...
spec:
...
containers:
- name: {{ .Values.image.name }}
image: {{ include "microservice-base-chart.reponame" . }}/{{ .Values.image.name }}:{{ .Values.image.version }}
But when I do
$ helm install ms-0 ./microservice-chart/ --dry-run --debug
I get
install.go:178: [debug] Original chart version: ""
install.go:195: [debug] CHART PATH: /path/helm/microservice-chart
Error: INSTALLATION FAILED: template: microservice-chart/charts/microservice-0/templates/deployment.yaml:36:20: executing "microservice-chart/charts/microservice-0/templates/deployment.yaml" at <include "microservice-base-chart.reponame" .>: error calling include: template: microservice-chart/charts/microservice-0/templates/_helpers.tpl:70:7: executing "microservice-base-chart.reponame" at <.eq>: can't evaluate field eq in type interface {}
helm.go:84: [debug] template: microservice-chart/charts/microservice-0/templates/deployment.yaml:36:20: executing "microservice-chart/charts/microservice-0/templates/deployment.yaml" at <include "microservice-base-chart.reponame" .>: error calling include: template: microservice-chart/charts/microservice-0/templates/_helpers.tpl:70:7: executing "microservice-base-chart.reponame" at <.eq>: can't evaluate field eq in type interface {}
INSTALLATION FAILED
main.newInstallCmd.func2
helm.sh/helm/v3/cmd/helm/install.go:127
github.com/spf13/cobra.(*Command).execute
github.com/spf13/cobra#v1.4.0/command.go:856
github.com/spf13/cobra.(*Command).ExecuteC
github.com/spf13/cobra#v1.4.0/command.go:974
github.com/spf13/cobra.(*Command).Execute
github.com/spf13/cobra#v1.4.0/command.go:902
main.main
helm.sh/helm/v3/cmd/helm/helm.go:83
runtime.main
runtime/proc.go:250
runtime.goexit
runtime/asm_amd64.s:1594
What am I doing wrong? TIA!

How to write below condition in Helm chart syntax in a job.yaml file?

I have to write this condition in helm chart syntax in job.yaml file so that imagePullSecrets get's executed only when the condition is satisfied.
Condition is
when: (network.docker.username | default('', true) | trim != '') and (network.docker.password | default('', true) | trim != '')
To write above condition below this code:
imagePullSecrets:
- name: "{{ $.Values.image.pullSecret }}"
Ideally, Docker username & password should come from Secrets. Here's the Sample helm code to use if in yaml file:
imagePullSecrets:
{{ if and (ne $.Values.network.docker.password '') (ne $.Values.network.docker.username '') }}
- name: "{{ $.Values.image.pullSecret }}"
{{ end }}
And values.yaml should have:
network:
docker:
username: your-uname
password: your-pwd

Helm lint error but everything looks ok to me

I'm getting this error when linting my helm project
$ helm lint --debug
==> Linting .
[INFO] Chart.yaml: icon is recommended
[ERROR] templates/: render error in "myProject/templates/configmap.yaml": template: myProject/templates/configmap.yaml:26:27: executing "myProject/templates/configmap.yaml" at <.Values.fileServiceH...>: can't evaluate field fileHost in type interface {}
Error: 1 chart(s) linted, 1 chart(s) failed
This is my configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: myProject-configmap
data:
tkn.yaml: |
iss: "{{ .Values.iss }}"
aud: "{{ .Values.aud }}"
db.yaml: |
database: "{{ .Values.database }}"
user: "{{ .Values.user }}"
host: "{{ .Values.host }}"
dialect: "{{ .Values.dialect }}"
pool:
min: "{{ .Values.pool.min }}"
max: "{{ .Values.pool.max }}"
acquire: "{{ .Values.pool.acquire }}"
idle: "{{ .Values.pool.idle }}"
fileservice.yaml: |
fileServiceHost:
fileHost: "{{ .Values.fileServiceHost.fileHost }}"
notificationservice.yaml: |
notificationServiceHost:
notificationHost: "{{ .Values.notificationservice.notificationHost }}"
organizationservice.yaml: |
organizationServiceHost:
organizationHost: "{{ .Values.organizationservice.organizationHost }}"
organizations.yaml: |
organizations: {{ .Values.organizations | toJson | indent 4 }}
epic.yaml: |
redirectUri: "{{ .Values.redirectUri }}"
This is my /vars/dev/fileservice.yaml file
fileServiceHost:
fileHost: 'https://example.com'
What is wrong that i'm getting this lint error?
You want to either use .Files.Get to load the yaml files or take the yaml content that you have in the yaml files and capture it in the values.yaml so that you can insert it directly in your configmap with toYaml.
If the values are just static and you don't need the user to override them then .Files.Get is better for you. If you want to be able to override the content in the yaml files easily at install time then just represent them in the values.yaml file.

How to pass dynamic arguments to a helm chart that runs a job

I'd like to allow our developers to pass dynamic arguments to a helm template (Kubernetes job). Currently my arguments in the helm template are somewhat static (apart from certain values) and look like this
Args:
--arg1
value1
--arg2
value2
--sql-cmd
select * from db
If I were run a task using the docker container without Kubernetes, I would pass parameters like so:
docker run my-image --arg1 value1 --arg2 value2 --sql-cmd "select * from db"
Is there any way to templatize arguments in a helm chart in such way that any number of arguments could be passed to a template.
For example.
cat values.yaml
...
arguments: --arg1 value1 --arg2 value2 --sql-cmd "select * from db"
...
or
cat values.yaml
...
arguments: --arg3 value3
...
I've tried a few approaches but was not successful. Here is one example:
Args:
{{ range .Values.arguments }}
{{ . }}
{{ end }}
Yes. In values.yaml you need to give it an array instead of a space delimited string.
cat values.yaml
...
arguments: ['--arg3', 'value3', '--arg2', 'value2']
...
or
cat values.yaml
...
arguments:
- --arg3
- value3
- --arg2
- value2
...
and then you like you mentioned in the template should do it:
args:
{{ range .Values.arguments }}
- {{ . }}
{{ end }}
If you want to override the arguments on the command line you can pass an array with --set like this:
--set arguments={--arg1, value1, --arg2, value2, --arg3, value3, ....}
In your values file define arguments as:
extraArgs:
argument1: value1
argument2: value2
booleanArg1:
In your template do:
args:
{{- range $key, $value := .Values.extraArgs }}
{{- if $value }}
- --{{ $key }}={{ $value }}
{{- else }}
- --{{ $key }}
{{- end }}
{{- end }}
Rico's answer needed to be improved.
Using the previous example I've received errors like:
templates/deployment.yaml: error converting YAML to JSON: yaml or
failed to get versionedObject: unable to convert unstructured object to apps/v1beta2, Kind=Deployment: cannot restore slice from string
This is my working setup with coma in elements:
( the vertical format for the list is more readable )
cat values.yaml
...
arguments: [
"--arg3,",
"value3,",
"--arg2,",
"value2,",
]
...
in the template should do it:
args: [
{{ range .Values.arguments }}
{{ . }}
{{ end }}
]
because of some limitations, I had to work with split and to use a delimiter, so in my case:
deployment.yaml :
{{- if .Values.deployment.args }}
args:
{{- range (split " " .Values.deployment.args) }}
- {{ . }}
{{- end }}
{{- end }}
when use --set:
helm install --set deployment.args="--inspect server.js" ...
results with:
- args:
- --inspect
- server.js
The arguments format needs to be kept consistent in such cases.
Here is my case and it works fine.
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ .Values.app.name }}
labels:
app: {{ .Values.app.name }}
instance: test
spec:
replicas: {{ .Values.master.replicaCount }}
selector:
matchLabels:
app: {{ .Values.app.name }}
instance: test
template:
metadata:
labels:
app: {{ .Values.app.name }}
instance: test
spec:
imagePullSecrets:
- name: gcr-pull-secret
containers:
- name: {{ .Values.app.name }}
image: {{ .Values.app.image }}
env:
- name: POD_IP
valueFrom:
fieldRef:
fieldPath: status.podIP
args:
[
"--users={{int .Values.cmd.users}}",
"--spawn-rate={{int .Values.cmd.rate}}",
"--host={{.Values.cmd.host}}",
"--logfile={{.Values.cmd.logfile}}",
"--{{.Values.cmd.role}}"]
ports:
- containerPort: {{ .Values.container.port }}
resources:
requests:
memory: {{ .Values.container.requests.memory }}
cpu: {{ .Values.container.requests.cpu }}
limits:
memory: {{ .Values.container.limits.memory }}
cpu: {{ .Values.container.limits.cpu }}
Unfortunately following mixed args format does not work within container construct -
mycommand -ArgA valA --ArgB valB --ArgBool1 -ArgBool2 --ArgC=valC
The correct format of above command expected is -
mycommand --ArgA=valA --ArgB=valB --ArgC=valC --ArgBool1 --ArgBool2
This can be achieved by following constructs -
#Dockerfile last line
ENTRYPOINT [mycommand]
#deployment.yaml
containers:
- name: {{ .Values.app.name }}
image: {{ .Values.app.image }}
args: [
"--ArgA={{ .Values.cmd.ArgA }}",
"--ArgB={{ .Values.cmd.ArgB }}",
"--ArgC={{ .Values.cmd.ArgC }}",
"--{{ .Values.cmd.ArgBool1 }}",
"--{{ .Values.cmd.ArgBool2 }}" ]
#values.yaml
cmd:
ArgA: valA
ArgB: valB
ArgC: valC
ArgBool1: "ArgBool1"
ArgBool2: "ArgBool2"
helm install --name "airflow" stable/airflow --set secrets.database=mydatabase,secrets.password=mypassword
So this is the helm chart in question: https://github.com/helm/charts/tree/master/stable/airflow
Now I want to overwrite the default values in the helm chart
secrets.database and
secrets.password so I use --set argument and then it is key=value pairs separated by commas.
helm install --name "<name for your chart>" <chart> --set key0=value0,key1=value1,key2=value2,key3=value3
Did you try this?
{{ range .Values.arguments }}
{{ . | quote }}
{{ end }}
Acid R's key/value solution was the only thing that worked for me.
I ended up with this:
values.yaml
arguments:
url1: 'http://something1.example.com'
url2: 'http://something2.example.com'
url3: 'http://something3.example.com'
url4: 'http://something3.example.com'
And in my template:
args:
{{- range $key, $value := .Values.arguments }}
- --url={{ $value }}
{{- end }}