configMapGenerator doesn't create integer value - kubernetes

Here it is my kustomization.yaml
kind: Kustomization
configMapGenerator:
- name: app-cm
literals:
- foo=bar
- var1=1
after kustomize build . I see var1 value in double quotes:
apiVersion: v1
data:
foo: bar
var1: "1"
kind: ConfigMap
metadata:
name: app-cm-ghtd2cb8m9
How should I compose kustomization.yaml the file to get the value of the variable without the quotes?
I expect var1 value without quotation as:
apiVersion: v1
data:
foo: bar
var1: 1
kind: ConfigMap
metadata:
name: app-cm-ghtd2cb8m9

What you expect can not be done. Kustomize did it right. The schema for a ConfigMap, in kubernetes, expects data do be a dict, whose values should be strings.
If we were to omit those quotes, while this yaml would still be "valid": when converted into json and posted to Kubernetes API, your value would be sent as an integer. This would violate ConfigMaps schema. Adding those quotes makes sure proper type would be used.
Maybe you can cast this value as integer in your application, or whatever you're trying to use this with.

Related

How to reuse variables in a kubernetes yaml?

I have a number of repeated values in my kubernetes yaml file and I wondering if there was a way I could store variables somewhere in the file, ideally at the top, that I can reuse further down
sort of like
variables:
- appName: &appname myapp
- buildNumber: &buildno 1.0.23
that I can reuse further down like
labels:
app: *appname
tags.datadoghq.com/version:*buildno
containers:
- name: *appname
...
image: 123456.com:*buildno
if those are possible
I know anchors are a thing in yaml I just couldn't find anything on setting variables
You can't do this in Kubernetes manifests, because you need a processor to manipulate the YAML files. Though you can share the anchors in the same YAML manifest like this:
---
apiVersion: v1
kind: ConfigMap
metadata:
name: &cmname myconfig
namespace: &namespace default
labels:
name: *cmname
deployedInNamespace: *namespace
data:
config.yaml: |
[myconfig]
example_field=1
This will result in:
apiVersion: v1
data:
config.yaml: |
[myconfig]
example_field=1
kind: ConfigMap
metadata:
creationTimestamp: "2023-01-25T10:06:27Z"
labels:
deployedInNamespace: default
name: myconfig
name: myconfig
namespace: default
resourceVersion: "147712"
uid: 4039cea4-1e64-4d1a-bdff-910d5ff2a485
As you can see the labels name && deployedInNamespace have the values resulted from the anchor evaluation.
Based on your use case description, what you would need is going the Helm chart path and template your manifests. You can then leverage helper functions and easily customize when you want these fields. From my experience, when you have an use case like this, Helm is the way to go, because it will help you customize everything within your manifests when you decide to change something else.
I guess there is a similar question with answer.
Please check below
How to reuse an environment variable in a YAML file?

kubectl apply with stringData in secret does not remove fields

(using kubernetes v1.15.7 in minikube and matching client version and minikube 1.9.0)
If I kubectl apply a secret like this:
apiVersion: v1
data:
MY_KEY: dmFsdWUK
MY_SECRET: c3VwZXJzZWNyZXQK
kind: Secret
metadata:
name: my-secret
type: Opaque
then subsequently kubectl apply a secret removing the MY_SECRET field, like this:
apiVersion: v1
data:
MY_KEY: dmFsdWUK
kind: Secret
metadata:
name: my-secret
type: Opaque
The data field in the result is what I expect when I kubectl get the secret:
data:
MY_KEY: dmFsdWUK
However, if I do the same thing using stringData instead for the first kubectl apply, it does not remove the missing key on the second one:
First kubectl apply:
apiVersion: v1
stringData:
MY_KEY: value
MY_SECRET: supersecret
kind: Secret
metadata:
name: my-secret
type: Opaque
Second kubectl apply (stays the same, except replacing MY_KEY's value with b2hubyEK to show the configuration DID change)
apiVersion: v1
data:
MY_KEY: b2hubyEK
kind: Secret
metadata:
name: my-secret
type: Opaque
kubectl get result after applying the second case:
data:
MY_KEY: b2hubyEK
MY_SECRET: c3VwZXJzZWNyZXQ=
The field also does not get removed if the second case uses stringData instead. So it seems that once stringData is used once, it's impossible to remove a field without deleting the secret. Is this a bug? Or should I be doing something differently when using stringData?
kubectl apply need to merge / patch the changes here. How this works is described in How apply calculates differences and merges changes
I would recommend to use kustomize with kubectl apply -k and use the secretGenerator to create a unique secret name, for every change. Then you are practicing Immutable Infrastructure and does not get this kind of problems.
A brand new tool for config manangement is kpt, and kpt live apply may also be an interesting solution for this.
The problem is that stringData is a write only field. It doesn’t have convergent behavior so it breaks the merge patch generator system. Most high level tools fix this by converting to normal data before dealing with the patch.

Can Openshift templates create objects over multiple projects

If I create project 'A' and want to deploy a template from inside it that creates objects in project 'A' and also in another project 'B' how would I achieve this. I tried simply specifying the namespace of project 'B' in the template but got the error
the namespace of the provided object does not match the namespace sent on the request
According to documentation:
If an object definition’s metadata includes a fixed namespace field value, the field will be stripped out of the definition during template instantiation. If the namespace field contains a parameter reference, normal parameter substitution will be performed and the object will be created in whatever namespace the parameter substitution resolved the value to, assuming the user has permission to create objects in that namespace.
So just specify required namespaces as template's parameters. Usable example:
apiVersion: template.openshift.io/v1
kind: Template
metadata:
name: xxx
parameters:
- name: ns1
value: test1
- name: ns2
value: test2
objects:
- apiVersion: v1
data:
key1: value1
kind: ConfigMap
metadata:
namespace: ${ns1}
name: cm1
- apiVersion: v1
data:
key2: value2
kind: ConfigMap
metadata:
namespace: ${ns2}
name: cm2

how to create a toml array usng helm template?

I have a configmap which contains a toml file
something like
apiVersion: v1
kind: ConfigMap
data:
burrow.toml: |
[zookeeper]
servers=[abc.2181, cde.2181]
timeout=6
root-path="/burrow"
When I am trying to create a helm chart to generate this configmap, I was putting something like:
apiVersion: v1
kind: ConfigMap
data:
burrow.toml: |
[zookeeper]
servers={{ .Values.config.zookeeperServers }}
timeout=6
root-path="/burrow"
and in the values.yaml, I put:
zookeeperServers: [ "abc.2181", "cde.2181"]
However, the rendered value became:
apiVersion: v1
kind: ConfigMap
data:
burrow.toml: |
[zookeeper]
servers=[abc.2181 cde.2181]
timeout=6
root-path="/burrow"
The comma is missing. Is there a good way to template this correctly? Thanks!
Here is one solution, in the values.yaml
put
zookeeperServers: |
[ "abc.2181", "cde.2181"]
solves the problem.
Try this, servers=[{{ .Values.config.zookeeperServers | join "," }}]. Quoting could get weird if you put TOML metachars in those values, but for simple things it should work.

How to use values from a ConfigMap with key/value separated by equal symbol (=)?

Given I have created a ConfigMap with a file like that :
VARIABLE1=foo
VARIABLE2=bar
Is there a way to access those values in Kubernetes or does it have to be in the YAML format?
Let's say you have a file called z with the contents above. You have two options to make that into a ConfigMap.
Option 1 (--from-file)
$ kubectl create cm cm1 --from-file=z
This will result in an object like this:
apiVersion: v1
kind: ConfigMap
metadata:
name: cm1
data:
z: |
VARIABLE1=foo
VARIABLE2=bar
There is no direct way to project a single value from this ConfigMap as it contains just one blob. However you can, from a shell used in command of a container source that blob (if you project it as a file) and then use the resulting environment variables.
Option 2 (--from-env-file)
$ kubectl create cm cm2 --from-env-file=z
This will result in an object like this:
apiVersion: v1
kind: ConfigMap
metadata:
name: cm2
data:
VARIABLE1: foo
VARIABLE2: bar
As you can see the different variables became separate key-value pairs in this case.
There are many more examples in the reference documentation