Last active
January 13, 2023 09:11
-
-
Save chenweienn/f143c34cad6eff691e639571fb5b8b9a to your computer and use it in GitHub Desktop.
A script to list service instances on TAS foundation.
This file contains hidden or 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 | |
| SCRIPT_NAME=$(basename $0) | |
| usage() { | |
| echo "Usage:" | |
| echo " $SCRIPT_NAME --per-svc|--per-org" | |
| echo "" | |
| echo "Flags:" | |
| echo " --per-svc Print triple (org_name, space_name, service_instance_name) for every service offering." | |
| echo " User-provided service instances are printed as the end." | |
| echo " The triples are ordered alphabetically by org_name and space_name." | |
| echo "" | |
| echo " --per-org Print triple (service_offering_name, service_plan_name, service_instance_name) for every space in every org." | |
| echo " User-provided service instances are printed as the end." | |
| echo " The triples are ordered alphabetically by service_offering_name and service_plan_name." | |
| echo "" | |
| echo "Prereuisites:" | |
| echo " 1. jq" | |
| echo " 2. cf login using admin user" | |
| echo "" | |
| echo "Tips:" | |
| echo " This script polls a few cf APIs to retrieve resources: orgs, spaces, service_offerings, service_plans, service_instances." | |
| echo " They are saved into files ./<resource>.json locally." | |
| echo " You can \"export SKIP_POLL_CF_API=true\" to reuse polled resources from prior script execution." | |
| echo "" | |
| } | |
| # print org-space-service mappings for a service instance | |
| map_org_space_svc() { | |
| SVC_INSTANCE="$1" | |
| SVC_INSTANCE_NAME=$(echo $SVC_INSTANCE | jq '.name' -r) | |
| SVC_INSTANCE_SPACE_GUID=$(echo $SVC_INSTANCE | jq '.relationships.space.data.guid' -r) | |
| SVC_INSTANCE_SPACE=$(cat ./spaces.json | jq --arg GUID $SVC_INSTANCE_SPACE_GUID 'select(.guid==$GUID)' -c) | |
| SVC_INSTANCE_SPACE_NAME=$(echo $SVC_INSTANCE_SPACE | jq '.name' -r) | |
| SVC_INSTANCE_ORG_GUID=$(echo $SVC_INSTANCE_SPACE | jq '.relationships.organization.data.guid' -r) | |
| SVC_INSTANCE_ORG=$(cat ./organizations.json | jq --arg GUID $SVC_INSTANCE_ORG_GUID 'select(.guid==$GUID)' -c) | |
| SVC_INSTANCE_ORG_NAME=$(echo $SVC_INSTANCE_ORG | jq '.name' -r) | |
| echo -e " Org: $SVC_INSTANCE_ORG_NAME \tSpace: $SVC_INSTANCE_SPACE_NAME \tInstance: $SVC_INSTANCE_NAME" | |
| } | |
| map_offering_plan_svc() { | |
| SVC_INSTANCE="$1" | |
| SVC_INSTANCE_NAME=$(echo $SVC_INSTANCE | jq '.name' -r) | |
| SVC_PLAN_GUID=$(echo $SVC_INSTANCE | jq '.relationships.service_plan.data.guid' -r) | |
| SVC_PLAN_NAME=$(cat ./service_plans.json | jq --arg GUID $SVC_PLAN_GUID 'select(.guid==$GUID) | .name' -r) | |
| SVC_OFFERING_GUID=$(cat ./service_plans.json | jq --arg GUID $SVC_PLAN_GUID 'select(.guid==$GUID) | .relationships.service_offering.data.guid' -r) | |
| SVC_OFFERING_NAME=$(cat ./service_offerings.json | jq --arg GUID $SVC_OFFERING_GUID 'select(.guid==$GUID) | .name' -r) | |
| echo -e " Offering: $SVC_OFFERING_NAME \tPlan: $SVC_PLAN_NAME \tInstance: $SVC_INSTANCE_NAME" | |
| } | |
| # print service instances for each service_offerings/service_plans and for user-provided services as well | |
| per_svc() { | |
| # part-1: managed services | |
| cat ./service_offerings.json | \ | |
| while read -r SVC_OFF; do | |
| SVC_OFF_NAME=$(echo "$SVC_OFF" | jq -r '.name') | |
| SVC_OFF_GUID=$(echo "$SVC_OFF" | jq -r '.guid') | |
| echo -e "=============== Service Offering: $SVC_OFF_NAME ================\n" | |
| cat ./service_plans.json | jq --arg GUID $SVC_OFF_GUID 'select(.relationships.service_offering.data.guid==$GUID)' -c | \ | |
| while read -r SVC_PLAN; do | |
| SVC_PLAN_NAME=$(echo "$SVC_PLAN" | jq -r '.name') | |
| SVC_PLAN_GUID=$(echo "$SVC_PLAN" | jq -r '.guid') | |
| INSTANCE_COUNT=$(cat ./service_instances.json | jq --arg GUID $SVC_PLAN_GUID -s '[ .[] | select(.relationships.service_plan?.data.guid==$GUID) ] | length') | |
| # echo "debug instance count: $INSTANCE_COUNT" | |
| echo -e " -------- Service Plan: $SVC_PLAN_NAME ( #instances: $INSTANCE_COUNT )" | |
| if [ $INSTANCE_COUNT -gt 0 ]; then | |
| echo "" | |
| cat ./service_instances.json | jq --arg GUID $SVC_PLAN_GUID 'select(.relationships.service_plan?.data.guid==$GUID)' -c | \ | |
| while read -r SVC_INSTANCE; do | |
| map_org_space_svc "$SVC_INSTANCE" | |
| done | sort -k 2,4 --ignore-case | column -t -s "$(printf '\t')" | |
| echo "" | |
| fi | |
| done | |
| echo "" | |
| done | |
| # part-2: user-provided services | |
| USER_PROVIDED_INSTANCE_COUNT=$(cat ./service_instances.json | jq -s '[ .[] | select(.type=="user-provided") ] | length') | |
| echo -e "=============== User-provided services ( #instances: $USER_PROVIDED_INSTANCE_COUNT ) ============\n" | |
| if [ $USER_PROVIDED_INSTANCE_COUNT -gt 0 ]; then | |
| cat ./service_instances.json | jq 'select(.type=="user-provided")' -c | \ | |
| while read -r SVC_INSTANCE; do | |
| map_org_space_svc "$SVC_INSTANCE" | |
| done | sort -k 2,4 --ignore-case | column -t -s "$(printf '\t')" | |
| fi | |
| } | |
| ## generating service usage details per organizations/spaces | |
| per_org() { | |
| cat ./organizations.json | jq -c '.' | \ | |
| while read -r ORG; do | |
| ORG_NAME=$(echo "$ORG" | jq -r '.name') | |
| ORG_GUID=$(echo "$ORG" | jq -r '.guid') | |
| echo -e "=============== Org: $ORG_NAME ================\n" | |
| cat ./spaces.json | jq --arg GUID $ORG_GUID 'select(.relationships.organization.data.guid==$GUID)' -c | \ | |
| while read -r SPACE; do | |
| SPACE_NAME=$(echo "$SPACE" | jq -r '.name') | |
| SPACE_GUID=$(echo "$SPACE" | jq -r '.guid') | |
| SPACE_INSTANCE_COUNT=$(cat ./service_instances.json | jq --arg GUID $SPACE_GUID -s '[ .[] | select(.relationships.space.data.guid==$GUID) ] | length') | |
| echo -e " ------- Space: $SPACE_NAME ( #instances: $SPACE_INSTANCE_COUNT )" | |
| if [ $SPACE_INSTANCE_COUNT -gt 0 ]; then | |
| echo "" | |
| # part-1: managed services | |
| cat ./service_instances.json | jq --arg GUID $SPACE_GUID 'select(.relationships.space.data.guid==$GUID and .type=="managed")' -c | \ | |
| while read -r SVC_INSTANCE; do | |
| map_offering_plan_svc "$SVC_INSTANCE" | |
| done | sort -k 2,4 --ignore-case | column -t -s "$(printf '\t')" | |
| echo "" | |
| # part-2: user-provided services | |
| USER_PROVIDED_INSTANCE_COUNT=$(cat ./service_instances.json | jq --arg GUID $SPACE_GUID -s '[ .[] | select(.relationships.space.data.guid==$GUID and .type=="user-provided") ] | length') | |
| if [ $USER_PROVIDED_INSTANCE_COUNT -gt 0 ]; then | |
| echo -e " User provided services:\n" | |
| cat ./service_instances.json | jq --arg GUID $SPACE_GUID 'select(.relationships.space.data.guid==$GUID and .type=="user-provided")' -c | \ | |
| while read -r SVC_INSTANCE; do | |
| # user-provided service instances are not associated with any service offering or plan. Just print their names. | |
| SVC_INSTANCE_NAME=$(echo $SVC_INSTANCE | jq '.name' -r) | |
| echo " Instance: $SVC_INSTANCE_NAME" | |
| done | sort -k 2 --ignore-case | |
| echo "" | |
| fi | |
| fi | |
| done | |
| echo "" | |
| done | |
| } | |
| # v2 API allows results-per-page <=100 | |
| # https://bosh.io/jobs/cloud_controller_ng?source=github.com/cloudfoundry/capi-release&version=1.143.0#p%3dcc.renderer.max_results_per_page | |
| # v3 API allows per_page <=5000 | |
| # https://github.com/cloudfoundry/cloud_controller_ng/blob/main/lib/cloud_controller/paging/pagination_options.rb#L10 | |
| poll_cf_resources() { | |
| API_RESOURCES=("organizations" "spaces" "service_offerings" "service_plans" "service_instances") | |
| PER_PAGE_MAX=5000 | |
| for RESOURCE in "${API_RESOURCES[@]}"; do | |
| echo "Saving $RESOURCE into ./$RESOURCE.json ..." | |
| # clean old API resources cache files | |
| echo -n "" > ./$RESOURCE.json | |
| TOTAL_PAGES=$(cf curl "/v3/$RESOURCE?per_page=$PER_PAGE_MAX" | jq '.pagination.total_pages' -r) | |
| PAGE=1 | |
| while [ $PAGE -le $TOTAL_PAGES ]; do | |
| cf curl "/v3/$RESOURCE?per_page=$PER_PAGE_MAX&page=$PAGE" | jq '.resources[]' -c >> ./$RESOURCE.json | |
| ((PAGE++)) | |
| done | |
| done | |
| } | |
| main() { | |
| # Check pre-requisites: jq, cf login | |
| if ! (jq --version > /dev/null 2>&1); then | |
| usage | |
| exit | |
| fi | |
| if ! (cf orgs > /dev/null 2>&1); then | |
| usage | |
| exit | |
| fi | |
| # STEP-1: retrieve cf API RESOURCEs = (organizations, spaces, service_offerings, service_plans, service_instances) to ./$RESOURCE.json | |
| # export SKIP_POLL_CF_API=true to reuse polled resources json file from prior execution | |
| if [ "${SKIP_POLL_CF_API:-}" != "true" ]; then | |
| poll_cf_resources | |
| fi | |
| # STEP-2: print service instances details | |
| case $1 in | |
| # grouping output per service offering | |
| --per-svc ) | |
| per_svc | |
| ;; | |
| # grouping output per org | |
| --per-org ) | |
| per_org | |
| ;; | |
| * ) | |
| usage | |
| ;; | |
| esac | |
| echo "Finished" | |
| } | |
| main $@ |
Author
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Example output 1:
Example output 2: