How to insert or add a field in a yaml after a specific key in yq
Asked Answered
E

3

6

I have a k8s yaml file with below block

spec:
  replicas: 1
  strategy:
    type: Recreate

and I want to add below block after "spec:"

selector:
  matchLabels:
    app: test-app

The file is huge and has many "spec:" fields, so it should be added at the first match.

Final file content should look like this :

spec:
  selector:
    matchLabels:
      app: test-app
  replicas: 1
  strategy:
    type: Recreate

I came up with this working solution using yq with correct indentation but it appends at the end of the file, Its painful to maintain and reading similar 100's of files.

yq  -i -y '.spec += {selector:{matchLabels:{app:"test-app"}}}' filename.yaml

Any answers with tools like sed or awk are welcome.

Edh answered 8/4, 2020 at 20:31 Comment(0)
P
1

I'm not familiar with yq, but I know it supports limited JSON I/O. Here's a solution to the structural problem with jq:

.spec |= ({selector: {matchLabels: {app: "test-app"}}} + .)

Maybe worth a shot in native yq?

Sample pipeline (untested):

yq r -j k8s.yaml | jq "$script" | yq r --prettyPrint

There are also these jq yamlifiers by the incorrigible Jeff Mercado.

Pursuant answered 8/4, 2020 at 22:28 Comment(0)
S
4

Here you go

$ yq --yaml-output '.spec |= ({selector: {matchLabels: {app: "test-app"}}} + .)' </tmp/your-yaml-file.yaml 

spec:
  selector:
    matchLabels:
      app: test-app
  replicas: 1
  strategy:
    type: Recreate

Since you mentioned you have hundreds of files and each has many spec elements, it's unclear if this will solve your actual problem but hopefully it can be of help. Good luck!

Stomodaeum answered 9/4, 2020 at 3:46 Comment(4)
OP specifically mentioned the order of the key-value pairs as a requirement. This is a long-winded equivalent of the example script.Pursuant
Agreed; his answer was the same using syntax I was unfamiliar with. Updated.Stomodaeum
this leads to "Error: unknown flag: --yaml-output"Boldt
@DanielMethner There are 2 yq's -- the 'Andrey Kislyuk' yq and the 'Mike Farah' yq. The Kisyluk has the --yaml-output flag; it appears the Farah yq does not (never used it but I just grepped the source and didn't see that flag). Perhaps you are using the Farah yq?Stomodaeum
P
1

I'm not familiar with yq, but I know it supports limited JSON I/O. Here's a solution to the structural problem with jq:

.spec |= ({selector: {matchLabels: {app: "test-app"}}} + .)

Maybe worth a shot in native yq?

Sample pipeline (untested):

yq r -j k8s.yaml | jq "$script" | yq r --prettyPrint

There are also these jq yamlifiers by the incorrigible Jeff Mercado.

Pursuant answered 8/4, 2020 at 22:28 Comment(0)
O
-3

You want a pickup-truck solution. I'm suggesting an Earth-mover instead.
(ATTENTION: Following requires Node.JS, Java-8 and command-line Git installed)..

npm install -g [email protected]
npm install -g @asux.org/cli-npm
export NODE_PATH=`npm root -g`
asux

The above does installation.


For what you want.. Create a /tmp/batch-file.txt containing the following lines.
## This is a comment.  No temporary files are created by this.
saveTo !ORIGINALINPUT
yaml read spec
saveTo !SAVED
useAsInput !ORIGINALINPUT
yaml delete 'spec/*'
yaml insert spec @/tmp/HugeSelectorFile.yaml
yaml insert spec !SAVED

Run the command:

asux yaml batch @/tmp/batch-file.txt -i ./YOURORIGINAL.yaml -o ./NEW.yaml

ASSUMPTIONS:
1) Your original YAML file is ./YOURORIGINAL.yaml
2) You want a new file called ./NEW.yaml
3) Your "huge selector" file is called /tmp/HugeSelectorFile.yaml (see 2nd-last lime in batch.txt above)

NOTE: The '@' character prefixing file-names is by-design (as without that '@' character, it means you are passing in JSON/YAML in-line within the command-line).

More can be found at https://github.com/org-asux/org-ASUX.github.io/wiki/Welcome-to-WIKI-for-org.ASUX

Omora answered 10/4, 2020 at 0:3 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.