Last active
April 13, 2018 15:53
-
-
Save brightzheng100/e5e0fc9978fcf49e6f934247023cfdd3 to your computer and use it in GitHub Desktop.
List all granted orgs' service instances
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
# Dependencies: cf, jq >= 1.5 | |
set -euo pipefail | |
umask 0077 | |
PROPERTIES_TO_SHOW_H=("#" guid name last_operation last_operation_at service_name organization space) | |
PROPERTIES_TO_SHOW=(.metadata.guid .entity.name .entity.last_operation.state .entity.last_operation.updated_at .extra.service_name .extra.organization .extra.space) | |
show_usage () { | |
cat << EOF | |
Usage: $(basename "$0") [OPTION]... | |
-s <sort field> sort by specified field index or its name | |
-S <sort field> sort by specified field index or its name (numeric) | |
-f <field1,field2,...> show only fields specified by indexes or field names | |
-c <minutes> filter objects created within last <minutes> | |
-u <minutes> filter objects updated within last <minutes> | |
-C <minutes> filter objects created more than <minutes> ago | |
-U <minutes> filter objects updated more than <minutes> ago | |
-k <minutes> update cache if older than <minutes> (default: 10) | |
-n ignore cache | |
-N do not format output and keep it tab-separated (useful for further processing) | |
-j print json (filter and sort options are not applied when -j is in use) | |
-v verbose | |
-h display this help and exit | |
EOF | |
} | |
P_TO_SHOW_H=$(echo "${PROPERTIES_TO_SHOW_H[*]}") | |
P_TO_SHOW=$(IFS=','; echo "${PROPERTIES_TO_SHOW[*]}") | |
p_index() { | |
for i in "${!PROPERTIES_TO_SHOW_H[@]}"; do | |
if [[ "${PROPERTIES_TO_SHOW_H[$i]}" == "$1" ]]; then | |
echo $(($i+1)) | |
fi | |
done | |
} | |
p_names_to_indexes() { | |
IFS=',' | |
fields=() | |
for f in $1; do | |
if [[ $f =~ ^[0-9]+$ ]]; then | |
fields+=($f) | |
else | |
fields+=($(p_index "$f")) | |
fi | |
done | |
echo "${fields[*]}" | |
} | |
# Process command line options | |
opt_sort_options="" | |
opt_sort_field="" | |
opt_created_minutes="" | |
opt_updated_minutes="" | |
opt_created_minutes_older_than="" | |
opt_updated_minutes_older_than="" | |
opt_cut_fields="" | |
opt_format_output="" | |
opt_update_cache_minutes="" | |
opt_print_json="" | |
opt_verbose="" | |
while getopts "s:S:c:u:C:U:f:k:nNjvh" opt; do | |
case $opt in | |
s) opt_sort_options="-k" | |
opt_sort_field=$OPTARG | |
;; | |
S) opt_sort_options="-nk" | |
opt_sort_field=$OPTARG | |
;; | |
c) opt_created_minutes=$OPTARG | |
;; | |
u) opt_updated_minutes=$OPTARG | |
;; | |
C) opt_created_minutes_older_than=$OPTARG | |
;; | |
U) opt_updated_minutes_older_than=$OPTARG | |
;; | |
f) opt_cut_fields=$OPTARG | |
;; | |
k) opt_update_cache_minutes=$OPTARG | |
;; | |
N) opt_format_output="false" | |
;; | |
n) opt_update_cache_minutes="no_cache" | |
;; | |
j) opt_print_json="true" | |
;; | |
v) opt_verbose="true" | |
;; | |
h) | |
show_usage | |
exit 0 | |
;; | |
?) | |
show_usage >&2 | |
exit 1 | |
;; | |
esac | |
done | |
# Set verbosity | |
VERBOSE=${opt_verbose:-false} | |
# Set printing json option (default: false) | |
PRINT_JSON=${opt_print_json:-false} | |
# Set sorting options, default is '-k1' (See 'man sort') | |
if [[ -n $opt_sort_field ]]; then | |
opt_sort_field=$(( $(p_names_to_indexes "$opt_sort_field") - 1 )) | |
fi | |
SORT_OPTIONS="${opt_sort_options:--k} ${opt_sort_field:-1},${opt_sort_field:-1}" | |
# Set cache update option (default: 10) | |
UPDATE_CACHE_MINUTES=${opt_update_cache_minutes:-10} | |
# Define command to cut specific fields | |
if [[ -z $opt_cut_fields ]]; then | |
CUT_FIELDS="cat" | |
else | |
opt_cut_fields=$(p_names_to_indexes "$opt_cut_fields") | |
cut_fields_awk=$(echo "$opt_cut_fields" | sed 's/\([0-9][0-9]*\)/$\1/g; s/,/"\\t"/g') | |
CUT_FIELDS='awk -F"\t" "{print $cut_fields_awk}"' | |
fi | |
# Define format output command | |
if [[ $opt_format_output == "false" ]]; then | |
FORMAT_OUTPUT="cat" | |
else | |
FORMAT_OUTPUT="column -ts $'\t'" | |
fi | |
# Post filter | |
POST_FILTER="" | |
if [[ -n $opt_created_minutes ]]; then | |
POST_FILTER="$POST_FILTER . | | |
(.metadata.created_at | (now - fromdate) / 60) as \$created_min_ago | | |
select (\$created_min_ago < $opt_created_minutes) |" | |
fi | |
if [[ -n $opt_updated_minutes ]]; then | |
POST_FILTER="$POST_FILTER . | | |
(.metadata.updated_at as \$updated_at | if \$updated_at != null then \$updated_at | (now - fromdate) / 60 else null end ) as \$updated_min_ago | | |
select (\$updated_min_ago != null) | select (\$updated_min_ago < $opt_updated_minutes) |" | |
fi | |
if [[ -n $opt_created_minutes_older_than ]]; then | |
POST_FILTER="$POST_FILTER . | | |
(.metadata.created_at | (now - fromdate) / 60) as \$created_min_ago | | |
select (\$created_min_ago > $opt_created_minutes_older_than) |" | |
fi | |
if [[ -n $opt_updated_minutes_older_than ]]; then | |
POST_FILTER="$POST_FILTER . | | |
(.metadata.updated_at as \$updated_at | if \$updated_at != null then \$updated_at | (now - fromdate) / 60 else null end ) as \$updated_min_ago | | |
select (\$updated_min_ago != null) | select (\$updated_min_ago > $opt_updated_minutes_older_than) |" | |
fi | |
# The following variables are used to generate cache file path | |
script_name=$(basename "$0") | |
user_id=$(id -u) | |
cf_target=$(cf target) | |
get_json () { | |
next_url="$1" | |
is_api_v2=false | |
is_api_v3=false | |
[[ ${next_url#/v2} != $next_url ]] && is_api_v2=true | |
[[ ${next_url#/v3} != $next_url ]] && is_api_v3=true | |
next_url_hash=$(echo "$next_url" "$cf_target" | $(which md5sum || which md5) | cut -d' ' -f1) | |
cache_filename="/tmp/.$script_name.$user_id.$next_url_hash" | |
if [[ $UPDATE_CACHE_MINUTES != "no_cache" ]]; then | |
# Remove expired cache file | |
find "$cache_filename" -maxdepth 0 -mmin +$UPDATE_CACHE_MINUTES -exec rm '{}' \; 2>/dev/null || true | |
# Read from cache if exists | |
if [[ -f "$cache_filename" ]]; then | |
cat "$cache_filename" | |
return | |
fi | |
fi | |
output_all=() | |
json_output="" | |
current_page=0 | |
total_pages=0 | |
while [[ $next_url != null ]]; do | |
# Get data | |
json_data=$(cf curl "$next_url") | |
# Show progress | |
current_page=$((current_page + 1)) | |
if [[ $total_pages -eq 0 ]]; then | |
if $is_api_v2; then | |
total_pages=$(cf curl "$next_url" | jq '.total_pages') | |
elif $is_api_v3; then | |
total_pages=$(cf curl "$next_url" | jq '.pagination.total_pages') | |
fi | |
fi | |
if $VERBOSE; then | |
[[ $current_page -gt 1 ]] && echo -ne "\033[1A" >&2 | |
echo -e "Fetched page $current_page from $total_pages ( $next_url )\033[0K\r" >&2 | |
fi | |
# Generate output | |
if $is_api_v2; then | |
output_current=$(echo "$json_data" | jq '[ .resources[] | {key: .metadata.guid, value: .} ] | from_entries') | |
elif $is_api_v3; then | |
output_current=$(echo "$json_data" | jq '[ .resources[] | {key: .guid, value: .} ] | from_entries') | |
fi | |
# Append current output to the result | |
output_all+=("$output_current") | |
# Get URL for next page of results | |
if $is_api_v2; then | |
next_url=$(echo "$json_data" | jq .next_url -r) | |
elif $is_api_v3; then | |
next_url=$(echo "$json_data" | jq .pagination.next.href -r | sed 's#^http\(s\?\)://[^/]\+/v3#/v3#') | |
fi | |
done | |
json_output=$( (IFS=$'\n'; echo "${output_all[*]}") | jq -s 'add' ) | |
# Update cache file | |
if [[ $UPDATE_CACHE_MINUTES != "no_cache" ]]; then | |
echo "$json_output" > "$cache_filename" | |
fi | |
echo "$json_output" | |
} | |
# Get organizations | |
next_url="/v2/organizations?results-per-page=100" | |
json_organizations=$(get_json "$next_url" | jq "{organizations:.}") | |
# Get spaces | |
next_url="/v2/spaces?results-per-page=100" | |
json_spaces=$(get_json "$next_url" | jq "{spaces:.}") | |
# Get stacks | |
next_url="/v2/stacks?results-per-page=100" | |
json_stacks=$(get_json "$next_url" | jq "{stacks:.}") | |
# Get isolation_segments | |
next_url="/v3/isolation_segments?per_page=100" | |
json_isolation_segments=$(get_json "$next_url" | jq "{isolation_segments:.}") | |
# Get services | |
next_url="/v2/services?results-per-page=100" | |
json_services=$(get_json "$next_url" | jq "{services:.}") | |
# Get service_instances | |
next_url="/v2/service_instances?results-per-page=100" | |
json_service_instances=$(get_json "$next_url" | jq "{service_instances:.}") | |
# Add extra data to json_organizations | |
json_organizations=$(echo "$json_organizations"$'\n'"$json_isolation_segments" | \ | |
jq -s 'add' | \ | |
jq '.isolation_segments as $isolation_segments | | |
.organizations[] |= (.extra.isolation_segment = ( $isolation_segments[.entity.default_isolation_segment_guid // empty].name // null ) | |
) | | |
.organizations | {organizations:.}') | |
# Add extra data to json_spaces | |
json_spaces=$(echo "$json_organizations"$'\n'"$json_spaces"$'\n'"$json_isolation_segments" | \ | |
jq -s 'add' | \ | |
jq '.organizations as $organizations | | |
.isolation_segments as $isolation_segments | | |
.spaces[] |= (.extra.organization = $organizations[.entity.organization_guid].entity.name | | |
.extra.isolation_segment = ( $isolation_segments[.entity.isolation_segment_guid // empty].name // null ) | |
) | | |
.spaces | {spaces:.}') | |
# Add extra data to json_service_instances | |
json_service_instances=$(echo "$json_stacks"$'\n'"$json_spaces"$'\n'"$json_isolation_segments"$'\n'"$json_organizations"$'\n'"$json_services"$'\n'"$json_service_instances" | \ | |
jq -s 'add' | \ | |
jq '.stacks as $stacks | | |
.spaces as $spaces | | |
.isolation_segments as $isolation_segments | | |
.organizations as $organizations | | |
.services as $services | | |
.service_instances[] |= (.extra.organization = $spaces[.entity.space_guid].extra.organization | | |
.extra.space = $spaces[.entity.space_guid].entity.name | | |
.extra.organization_isolation_segment = $organizations[$spaces[.entity.space_guid].entity.organization_guid].extra.isolation_segment | | |
.extra.space_isolation_segment = $spaces[.entity.space_guid].extra.isolation_segment | | |
.extra.isolation_segment = (.extra.space_isolation_segment // .extra.organization_isolation_segment) | | |
.extra.service_name = $services[.entity.service_guid].entity.label | |
) | | |
.service_instances | {service_instances:.}') | |
if $PRINT_JSON; then | |
echo "$json_service_instances" | |
else | |
# Generate service instances list (tab-delimited) | |
service_instance_list=$(echo "$json_service_instances" |\ | |
jq -r ".service_instances[] | | |
$POST_FILTER | |
[ $P_TO_SHOW | select (. == null) = \"<null>\" | select (. == \"\") = \"<empty>\" ] | | |
@tsv") | |
# Print headers and app_list | |
(echo $P_TO_SHOW_H | tr ' ' '\t'; echo -n "$service_instance_list" | sort -t $'\t' $SORT_OPTIONS | nl -w4) | \ | |
# Cut fields | |
eval $CUT_FIELDS | \ | |
# Format columns for nice output | |
eval $FORMAT_OUTPUT | less --quit-if-one-screen --no-init --chop-long-lines | |
fi |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment