I am trying to craft a gcloud command that does a bulk metadata update on compute engine instances.
Normally I could just pipe gcloud compute instances list
to xargs gcloud compute instances add-metadata
. However, this is thwarted because for some inexplicable reason, add-metadata
needs both an instance name, and a zone, even though compute instance names appear to be globally unique. So now I'm forced to try to shuttle both pieces of data (both name and zone) to the add-metadata command. If I don't provide both, I get:
ERROR: (gcloud.compute.instances.add-metadata) Underspecified resource [worker-1]. Specify the [--zone] flag.
I'm about ready to give up on the bash/xargs incantation and switch to python but I thought I'd check here first.
I have this command:
gcloud compute instances list \
--filter="name~'worker' AND zone~'us-central1'" \
--format 'value(name,zone)'
which returns something like:
worker-1 us-central1-c
worker-2 us-central1-c
worker-3 us-central1-c
worker-4 us-central1-c
I then need to pipe these into a command like:
gcloud compute instances add-metadata --zone=[zone goes here] --metadata myvalue=true [instance name goes here]
But this is proving tricky/annoying using xargs alone. Is there a better or simpler way to accomplish what I'm attempting?
CodePudding user response:
Pipe it to while read sequence:
gcloud compute instances list \
--filter="name~'worker' AND zone~'us-central1'" \
--format 'value(name,zone)' | \
while read instance zone; do
gcloud compute instances add-metadata \
--zone=$zone --metadata myvalue=true $instance
done
CodePudding user response:
You can wrap a sh
"in the middle" to help with positional arguments.
In your case you can run below CLI, noting that it'll echo
the gcloud
commands that it would run, then once comfortable with the resulting set of commands, either remove the echo
there, or run the whole command |sh -x
:
gcloud compute instances list \
--filter="name~'worker' AND zone~'us-central1'" \
--format 'value(name,zone)' |\
xargs -n2 sh -c \
'echo gcloud compute instances add-metadata --zone="$2" --metadata myvalue=true "$1"' --
The trick here is this CLI arrangement: xargs -n2 sh -c '... $1 ... $2' --
-n2
to letxargs
pass in args in groups of twosh -c '... $1 ... $2' --
as a mini scriptlet