bash loops with multi-statement conditions
I wanted to pause a script until the status of 2 Cloud Run services became ready. In this case, I wanted to check for the status condition RoutesReady to be True.
My initial attempt is ghastly:
while [[ "True"!=$(gcloud run services describe ...) && "True"!=$(gcloud run service describe ...)]]
do
...
loop
NOTE In actuality, is was worse than that because I had
--projectand--regionflags and pumped the result throughjq
I found an interesting comment by jonathan-leffler on this Stack overflow answer suggesting that the condition in bash loops could actually be an (arbitrarily?) complex sequence of commands as long as the final statement returns true. Thanks Jonathan!
As a result, I was able to rewrite the above in a better way:
FILTER=".status.conditions[]|select(.type==\"RoutesReady\").status"
until
STATUS_ONE=$(\
gcloud run services describe ${NAME_ONE} \
--project=${PROJECT} \
--region=${REGION} \
--format=json \
| jq -r "${FILTER}")
STATUS_TWO=$(\
gcloud run services describe ${NAME_TWO} \
--project=${PROJECT} \
--region=${REGION} \
--format=json \
| jq -r "${FILTER}")
[[ ${STATUS_ONE}=="True" && ${STATUS_TWO}=="True" ]]
do
sleep 5s
done
NOTE Notice in the above that the
untilcondition is actually 3 statements (STATUS_ONE=...; STATUS_TWO=...; [[ ...]]). The first 2 statements allow me assign the filteredgcloud run describecommands output to variables that can then be queried in the condition. An advantage to this approach is that these 2 variables are only needed for the condition and don’t need to be smeared into the loop body.
Another improvement could be to turn the status acquisition into a function.
Aside
I wanted to be able to perform the query without resorting to jq but am unsuccessful.
I tried:
gcloud run services describe ${NAME} \
--project=${PROJECT} \
--region=${REGION} \
--format="value(status.conditions.filter(type=\"RoutesReady\").)"
This yields the correctly filtered condition but I’m unable to work out how to then grab the status from that result.