Given the following yaml:
charts:
# repository with Helm charts for creation namespaces
path: ns
pathMonitoringPrometheus: prom
namespaces:
first:
description: "Description of first"
enabled: false
branch: master
bootstrapChart: bootstrap
syncAccessGroups: []
namespace:
role: k8s-role-of-first
istio: disabled
public: view
sources: []
second:
description: "Description of second"
enabled: false
branch: HEAD
bootstrapChart: bootstrap
namespace:
role: k8s-role-of-second
istio: 1-13-2
labels:
label: second
sources:
- http://url.of.second
How could we get a list of namespaces and their istio value if it is different to "disabled".
We are trying to use "yq" tool, but I guess any approach would be ok, although "yq" would be a preferred approach.
second, 1-13-2
Using kislyuk/yq you can base your filter on jq.
to_entries splits up the object into an array of key-value pairs
select selects those items matching your criteria
String interpolation in combination with the -r option puts together your desired output
yq -r '
.namespaces
| to_entries[]
| select(.value.namespace.istio != "disabled")
| "\(.key), \(.value.namespace.istio)"
'
second, 1-13-2
Using mikefarah/yq the filter is quite similar.
to_entries[] has to be split up to_entries | .[]
String interpolation is replaced using join and an array
yq '
.namespaces
| to_entries | .[]
| select(.value.namespace.istio != "disabled")
| [.key, .value.namespace.istio] | join(", ")
'
second, 1-13-2
this will do:
cat /path/tp/your.yaml |yq -r '.namespaces | to_entries[] | "\(.key) \(.value.namespace.istio)"'`
will result:
first disabled
second 1-13-2
Related
I want write a script which is giving me the volumeId,instanceId and tags. But in tags just the "Name" is interest me.
I will elaborate.
today I am running with the next call
aws ec2 describe-volumes --filters Name=status,Values=available | jq -c '.Volumes[] | {State: .State, VolumeId: .VolumeId, Tags: .Tags}'
"State":"available","VolumeId":"vol-094c79bc5e641bd7e","Tags":[{"Key":"Name","Value":"Adi"},{"Key":"Team","Value":"SRE"}]}
2.{"State":"available","VolumeId":"vol-041485dd7394bbdd7","Tags":[{"Key":"Team","Value":"SRE"}]}
I want my response will include the just the tag "Name" and it's value.
If the tag "Name" does not exist , I want in my response just the "State","VolumeId".
For 1.State":"available","VolumeId":"vol-094c79bc5e641bd7e","Tags":[{"Key":"Name","Value":"Adi"}
For 2. {"State":"available","VolumeId":"vol-041485dd7394bbdd7"}
If you can live with "Tags": [] holding an empty array while still being present, a simple map(select(.Key == "Name")) will do:
jq -c '.Volumes[] | {State, VolumeId, Tags: (.Tags | map(select(.Key == "Name")))}'
{"State":"available","VolumeId":"vol-094c79bc5e641bd7e","Tags":[{"Key":"Name","Value":"Adi"}]}
{"State":"available","VolumeId":"vol-041485dd7394bbdd7","Tags":[]}
Demo
Otherwise you need to distinguish separately whether the field should be added or not. This can be achieved using an if statement:
jq -c '.Volumes[] | {State, VolumeId} + (
{Tags: (.Tags | map(select(.Key == "Name")))} | if .Tags == [] then {} else . end
)'
{"State":"available","VolumeId":"vol-094c79bc5e641bd7e","Tags":[{"Key":"Name","Value":"Adi"}]}
{"State":"available","VolumeId":"vol-041485dd7394bbdd7"}
Demo
I have a yaml file called teams.yml that looks like this:
test:
bonjour: hello
loop:
bonjour: allo
I want to loop over an array and get itsvalues matching a key in the yaml. I have tried yq e 'keys | .[] | select(. == "test")' .github/teams.yml and it returns test whereas yq e 'keys | .[] | select(. == "abc")' .github/teams.yml returns nothing which is enough to get the information I am interested in.
The issue is that, when using the same logic in a for loop, yq returns nothing:
#!/bin/bash
yq e 'keys | .[] | select(. == "abc")' .github/teams.yml # Prints nothing
yq e 'keys | .[] | select(. == "test")' .github/teams.yml # Prints 'test'
ar=( "abc" "test" "xyz" )
for i in "${ar[#]}" # Prints nothing
do
yq e 'keys | .[] | select(. == "$i")' .github/teams.yml
done
What explains the lack of output in the for loop?
Call yq with the loop variable set in the environment, and use env within yq to read environment variables. See also the section Env Variable Operators in the manual.
ar=( "abc" "test" "xyz" )
for i in "${ar[#]}" # Prints nothing
do
i="$i" yq e 'keys | .[] | select(. == env(i))' .github/teams.yml
done
Another way could be to import the (preformatted) array from the environment and just make the array subtractions within yq (saving you the looping and calling yq multiple times):
ar='["abc","test","xyz"]' yq e 'env(ar) - (env(ar) - keys) | .[]' .github/teams.yml
I have this structure:
foo:
image: 123
bar:
image: 456
baz:
config: "my config"
and I'd like to print the root keys (i.e. foo, bar, baz) based on the existence of the child "image"
In yq version 3 I could do this:
$ yq read test.yaml --printMode p "*.image" | awk -F'.' '{print $1}'
foo
bar
But I can't find the equivalent in v4. The yq + jq solution would be:
$ yq -j e test.yaml | jq -r 'to_entries[] | select(.value | has("image")) | [.key][]'
foo
bar
Any idea how to do this with yq v4?
You can use the path operator to get the path of the matching object containing the tag image
yq e '.[] | select(has("image")) | path | .[]' yaml
I use Jq to perform some filtering on a large json file using :
paths=$(jq '.paths | to_entries | map(select(.value[].tags | index("Filter"))) | from_entries' input.json)
and write the result to a new file using :
jq --argjson prefix "$paths" '.paths=$prefix' input.json > output.json
But this ^ fails as $paths has a very high line count (order of 100,000).
Error :
jq: Argument list too long
I also went through : /usr/bin/jq: Argument list too long error bash , understood the same problem there, but did not get the solution.
In general, assuming your jq allows it, you could use —argfile or —slurpfile but in your case you can simply avoid the issue by invoking jq just once instead of twice. For example, to keep things clear:
( .paths | to_entries | map(select(.value[].tags | index("Filter"))) | from_entries ) as $prefix
| .paths=$prefix
Even better, simply use |=:
.paths |= ( to_entries | map(select(.value[].tags | index("Filter"))) | from_entries)
or better yet, use with_entries.
I am trying to display the output of the command using "until",
- name: Waiting for stack to Deploy...
shell: '{{ creds }} heat event-list {{stack_name}}'
register: waiting_for_stack
until: waiting_for_stack.stdout.find("Stack CREATE completed successfully") or waiting_for_stack.stdout.find("CREATE_FAILED")!= -1
retries: 10
delay: 3
- debug: var=waiting_for_stack.stdout_lines
I am looping the shell command to get the entire event list of stack. But looping does not work. It is exiting from the first iteration without matching the string provided in conditions. Event list out-out looks like this.
ok: [10.206.41.150] => {
"waiting_for_stack.stdout_lines": [
"+---------------+--------------------------------------+------------------------+--------------------+----------------------+",
"| resource_name | id | resource_status_reason | resource_status | event_time |",
"+---------------+--------------------------------------+------------------------+--------------------+----------------------+",
"| stack01 | 924498f6-6498-4560-947c-fec5149b9775 | Stack CREATE started | CREATE_IN_PROGRESS | 2016-05-12T02:55:18Z |",
"| MCM2 | 1e6fe65d-971b-49c6-9441-dd77edd47d29 | state changed | CREATE_IN_PROGRESS | 2016-05-12T02:55:18Z |",
"+---------------+--------------------------------------+------------------------+--------------------+----------------------+"
]
}
Am I doing something wrong, or is there a better way to execute this? I am using ansible version 1.7 .
until: ("Stack CREATE completed successfully" in waiting_for_stack.stdout) or ("CREATE_FAILED" in waiting_for_stack.stdout)
Did the job for me.