Generating yaml output using kubectl result in splits line - kubernetes

I am trying to generate yaml output with kubectl --dry-run.
When I run this
$ kubectl create configmap my-config-map -o yaml --dry-run=client | kubectl annotate -f- --dry-run=client -o yaml --local this-is-my-target-directory='{{ template "This.is.long.path.for.some.value" . }}'
I get the following output where annotations are splitting into 2 lines.
apiVersion: v1
kind: ConfigMap
metadata:
annotations:
this-is-my-target-directory: '{{ template "This.is.long.path.for.some.value" .
}}'
creationTimestamp: null
name: my-config-map
my desired output is that annotations should be in one line. like below
apiVersion: v1
kind: ConfigMap
metadata:
annotations:
this-is-my-target-directory: '{{ template "This.is.long.path.for.some.value" . }}'
creationTimestamp: null
name: my-config-map
If I reduce the size of the string then it becomes 1 line. I could not find anywhere in the documentation anything about line length. Can anyone guide me on how to fix this?

I think you can't find anything because this is a totally valid yaml. So I guess you can use it as it's without the need to put the curly brackets at the same line.

Related

Set environment variable in kubernetes secret

When using Kubernetes .yml files, I can do the following:
$ cat configmap.yml
apiVersion: v1
kind: ConfigMap
metadata:
name: my-configmap
data:
foo: ${FOO}
bar: ${BAR}
static: doesNotChange
$ export FOO=myFooVal
$ export BAR=myBarVal
$ cat configmap.yml | envsubst | kubectl apply -f -
This would replace ${FOO} and ${BAR} in the configmap.yml file before actually applying the file to the cluster.
How could I achieve the very same behavior with a Kubernetes secret which has it's data values base64 encoded?
I would need to read all the keys in the data: field, decode the values, apply the environment variables and encode it again.
A tool to decode and encode the data: values inplace would be much appreciated.
It is actually possible, to store the secret.yml with stringData instead of data which allows to keep the files in plain text (SOPS encryption is still possible and encouraged)
$ cat secret.yml
apiVersion: v1
kind: Secret
metadata:
name: test-secret
namespace: default
type: Opaque
stringData:
dotenv: |
DATABASE_URL="postgresql://test:test#localhost:5432/test?schema=public"
API_PORT=${PORT}
FOO=${FOO}
BAR=${BAR}
$ export PORT=80
$ export FOO=myFooValue
$ export BAR=myBarValue
$ cat secret.yml | envsubst | kubectl apply -f -
A plus is for sure, that this not only allows for creation of the secret, but updating is also possible.
Just for documentation, here would be the full call with SOPS:
$ sops --decrypt secret.enc.yml | envsubst | kubectl apply -f -

Kubetcl create configmap with --from-file flag, inconsistent behavior

When I'm executing create config command such as:
kubectl create configmap config-map-example --from-file=conf1.js=./conf-files/conf1.js --from-file=conf2.js=./conf-files/conf2.js --from-file=conf3.js=./conf-files/conf3.js --dry-run -o yaml
The content of each config file is either imported as string, or as block scalar, e.g:
kind: ConfigMap
metadata:
name: config-map-example
apiVersion: v1
data:
conf1.js: |-
// conf1.js content
conf2.js: "// conf2.js content as string with \n line breaks"
conf3.js: |-
// conf3.js content
Why is this happening?

Error: unable to recognize "mongo-configmap.yaml": no matches for kind "ConfigMap" in version "V1"

I am following a MongoDB tutorial on Kubernetes, but when I create the configuration map, it gives me this error:
error: unable to recognize "mongo-configmap.yaml": no matches for kind "ConfigMap" in version "V1"
This is the mongo-configmap.yaml file:
apiVersion: V1
kind: ConfigMap
metadata:
name: mongodb-configmap
data:
database_url: mongodb-service
The version should be lower case.
apiVersion: v1
lang-none
You can run the below command to refer to the attributes.
kubectl explain cm | head
Or
kubectl explain cm --recursive | grep -i <attribute> or head
KIND: ConfigMap
VERSION: v1
DESCRIPTION:
ConfigMap holds configuration data for pods to consume.
FIELDS:
apiVersion <string>
binaryData <map[string]string>
data <map[string]string>

Programatically apply a single resource from a multi resource Kubernetes YAML file

I have a file with three configmaps in it, like the one below.
apiVersion: v1
data:
TEST: "one"
kind: ConfigMap
metadata:
name: test-config-one
---
apiVersion: v1
data:
TEST: "two"
kind: ConfigMap
metadata:
name: test-config-two
---
apiVersion: v1
data:
TEST: "three"
kind: ConfigMap
metadata:
name: test-config-three
I'm trying to apply only test-config-three to the cluster. I know I can break that out into its own file and run kubectl apply -f test-config-three.yaml, but is there a way to do that without having to create a new file?
I was hoping to be able to do something like:
cat file.yml | yq <get only test-config-three> | kubectl apply -f -
But yq doesn't seem to support finding a single resource in a file. I also looked at tools like kubesplit but they tend to output all resources to separate files.
Is there a way to isolate and output a single resource from a yaml file containing multiple resources without creating a new file?
Update
Thanks to #Inian's answer below, I was able to get this full command working.
cat file.yml | yq e 'select(.data.TEST == "three")' - | kubectl apply -f -
There are two versions of yq implemented, one in Python and one in Go as I've highlighted in my answer at How can I parse a YAML file from a Linux shell script?
Using the Python version - kislyuk/yq
yq -y 'select(.data.TEST == "three")' yaml
Go version - mikefarah/yq
yq e 'select(.data.TEST == "three")' yaml
If you have python you can try following
export MYFILE=file.yml
export DOC_NUMBER=2
python3 -c "import yaml; print(yaml.dump(list(yaml.safe_load_all(open('"$MYFILE"')))["$DOC_NUMBER"]))" | kubectl apply -f -
yaml.safe_load_all(open('"$MYFILE"')) loads all the documents in the yaml file into a list. Then you are selecting "$DOC_NUMBER" document with ["$DOC_NUMBER"].
yaml.dump would dump the loaded object back into yaml format which is then printed.

How to edit configmap in kubernetes and override the values from a different yaml file?

I want to edit the configmap and replace the values. But it should be done using a different YAML in I ll specify overriding values as part of that file.
I was trying using kubectl edit cm -f replace.yaml but this didn't work so i want to know the structure in which the new file should be.
apiVersion: v1
kind: ConfigMap
metadata:
name: int-change-change-management-service-configurations
data:
should_retain_native_dn: "False"
NADC_IP: "10.11.12.13"
NADC_USER: "omc"
NADC_PASSWORD: "hello"
NADC_PORT: "991"
plan_compare_wait_time: "1"
plan_prefix: ""
ingress_ip: "http://10.12.13.14"
Now lets us assume NADC_IP should be changed and So I would like to know how should be structure of the YAML file and using which command it can be served?
The override taking place should only be during helm test for example when i run
helm test <release-name>?
kubectl replace -f replace.yaml
If you have a configmap in place like this:
apiVersion: v1
kind: ConfigMap
metadata:
name: my-configmap
data:
should_retain_native_dn: "False"
NADC_IP: "10.11.12.13"
and you want to change the value of NADC_IP create a manifest file like this:
apiVersion: v1
kind: ConfigMap
metadata:
name: my-configmap
data:
should_retain_native_dn: "False"
NADC_IP: "12.34.56.78" # the new IP
and run kubectl replace -f replace.yaml
To update variable in configmap you need to take two steps:
First, update the value of variable:
kubectl create configmap <name_of_configmap> --from-literal=<var_name>=<new_value> -o yaml --dry-run | kubectl replace -f -
So in your case it will looks like this:
kubectl create configmap int-change-change-management-service-configurations --from-literal=NADC_IP=<new_value> -o yaml --dry-run | kubectl replace -f -
Second step, restart the pod:
kubectl delete pod <pod_name>
App will use new value from now. Let me know, if it works for you.
kubectl get cm {configmap name} -o=yaml --export > filename.yaml
You can try this it will give you yaml format
kubectl get configmap
int-change-change-management-service-configurations -o yaml
You can copy the content and replace it inside new yaml file and apply the changes
EDIT : 1
If you want to edit over terminal you can run
kubectl edit configmap {configmap name}
It will use vim editor and you can replace value from terminal using edit command.
EDIT : 2
kubectl get cm {configmap name} -o=yaml --export > filename.yaml