#!/bin/bash # # Author: Georg Voell - georg.voell@standby.cloud # Version: @(#)oci-object 3.2.0 12.08.2024 (c)2024 Standby.cloud # Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl/ # # This script can be used free of charge. Use it as is or customize as needed. It is not guaranteed to be # error free and you will not be reimbursed for any damage it may cause. # #@ Do some jobs with oci objects #@ #@Usage: oci-object [options] [action] #@ Options: -h, --help : Displays helptext. #@ -v, --version : Displays the version of the script. #@ -f, --force : Force refreshing all lists (no cashing). #@ -m, --monochrome : Don't display colors or progress. #@ -o, --output : Output format: can be "table" (default), "json", "tsv" or "line". #@ -d, --domains : Search IDCS domains (more detailed infos for users and groups but slower). #@ -c, --compartment-id : Compartment OCID. #@ -r, --region : Region (e.g. eu-frankfurt-1). #@ -t, --type : Instance type (e.g. instance or "instance,dbsystem"). #@ Action: #@ list: List all supported resource types. #@ check: List all available resource types in the Home Region and check if they are currently supported. #@ search: (Default) Search for objects. #@ analyze: Not yet implemented (Search for Compartments that are not accessible and for Instances that are not in .ssh/config. #@ TypeStr (one type or list of types in a comma separated string e.g.): #@ instance: List only IaaS Instances. #@ dbsystem: List only DB Systems #@ #@Examples: #@ oci-object #@ List compartments and all objects in these compartments. #@ oci-object search --compartment-id ocid1.tenancy.oc1..xxxxxxxxx #@ List all objects in root compartment. # # Exit codes: # 01: Unknown or wrong parameter. # 02: Unknown action or action not allowed. # 03: No **instance-id** specified with start or stop. # 04: Instance was already running or stopped. *** # 05: Instance was already opened / closed or VIP was already added / deleted. *** # 06: Could not attach / detach public ip (or unexpected error) # 95: External variable $HOME_REGION is not really the home region. *** # 96: Specified region not subscribed. *** # 97: Tools not configured. *** # 98: Unknown function call. *** # 99: User interrupt. # # See also: # **install-scripts**(1) # # ToDo: # # - Not all objects have JSON detail information yet. # # Update history: # # V 1.0.0 11.06.2020 Using library # V 1.0.1 01.09.2020 Changed parameter v to n for vnic-id # V 1.0.2 25.03.2021 Using raw output from oci cli # V 1.0.3 30.03.2021 Using oci api # V 1.0.4 31.03.2021 Check also status of service(s) on target VM # V 1.0.5 02.04.2021 Check more types (not only instance) # V 1.0.6 22.04.2021 Backup for instance # V 1.0.7 27.04.2021 Renamed oci-instance to oci-object # V 3.0.0 15.05.2021 Separated Search Objects and actions on instance # V 3.1.0 05.06.2023 New copyright # V 3.1.1 11.07.2024 Bugfix: Use printf different # V 3.1.2 26.07.2024 Additional actions: list and check # V 3.1.3 08.03.2024 Additional output formats # V 3.2.0 12.08.2024 New minor version # # Find executable bash library and source it lib=`which lib.bash 2>/dev/null | sed 's|^no 'lib.bash' in .*||'` if [ "$lib" != "" ]; then source "$lib" else progdir=`dirname "$0"` if [ -r "${progdir}/lib.bash" ]; then source "${progdir}/lib.bash" else echo "Unexpected error: Unable to locate bash library 'lib.bash'." exit 1 fi fi # Don't let oci-api envelope JSON export ENVELOPE_API=false # Repository to download from readonly downloadurl="https://standby.cloud/download" readonly configdir="${HOME}/.config" readonly toolsdir="admintools" readonly listsdir="lists" readonly resfile="resources.txt" # All searchable Resources (list on web) readonly apifile="api.txt" # All OCI APIs (list on web) readonly regfile="regions.txt" # All OCI Regions (list on web) readonly compfile="compartments.txt" # All Compartments (name) readonly adfile="ads.txt" # All Availability domains readonly domainfile="domains.txt" # All Identity Domains readonly iambase="20160918" readonly querybase="20180409" # Source environment variables if [ -r "${HOME}/.$toolsdir" ]; then source "${HOME}/.$toolsdir" else if [ -r "/usr/local/share/info/.$toolsdir" ]; then source "/usr/local/share/info/.$toolsdir" fi fi # Do extra cleanup function ExtraCleanup() { filecheck -rm ${scratchfile}.regn # All subscribed regions filecheck -rm ${scratchfile}.avd # All availability domains in all subscribed regions filecheck -rm ${scratchfile}.comp # All compartments (id) filecheck -rm ${scratchfile}.name # All compartments (name) filecheck -rm ${scratchfile}.domain # All domains filecheck -rm ${scratchfile}.inst # Instance infos filecheck -rm ${scratchfile}.json # Detailes JSON infos filecheck -rm ${scratchfile}.body filecheck -rm ${scratchfile}.test } # Download all needed files from repo function Initialize() { local result="" # Create config dir if it does not exist if [ ! -d "${configdir}/${toolsdir}/$listsdir" ]; then mkdir -p "${configdir}/${toolsdir}/$listsdir" fi # Download API info files for file in $resfile $apifile $regfile; do if [ "$force" = false ]; then result=`filecheck -fy "${configdir}/${toolsdir}/${listsdir}/$file"` else result="" fi if [ "$result" = "" ]; then # echo "Downloading file '${configdir}/${toolsdir}/${listsdir}/$file'." >> /tmp/test.txt transfer --quiet "${downloadurl}/${listsdir}/$file" | stripcomment | grep . > $scratchfile result=`head -n 1 "$scratchfile" | cut -d$'\t' -f1` if [ "$result" = "name" ]; then mv -f $scratchfile "${configdir}/${toolsdir}/${listsdir}/$file" fi fi done } function CheckResType() { local rtype=${1} local stat=0 local result="" if [ "$instance_type" != "" -a "$rtype" != "" ]; then result=`echo "$instance_type" | grep "\<${rtype}\>"` if [ "$result" != "" -o "$instance_type" = "all" ]; then # found rtype in instance_type stat=1 fi fi return $stat } function DeleteResType() { local rtype=${1} local stat=0 local result="" if [ "$instance_type" != "" -a "$rtype" != "" ]; then result=`echo "$instance_type" | grep "\<${rtype}\>"` if [ "$result" != "" -a "$instance_type" != "all" ]; then if [ "$OS" = "Darwin" ]; then instance_type=`echo "$instance_type" | sed 's|[[:<:]]'$rtype'[[:>:]]||'` else instance_type=`echo "$instance_type" | sed 's|\<'$rtype'\>||'` fi fi fi } function PrintSearchString() { local str=${1} local slen=0 if [ "$str" = "" ]; then printf "\n-" slen=1 else printf "\n%s -" "$str" slen=`printf "%s" "$str" | wc -m` slen=$(($slen + 2)) fi return $slen } function PrintUpdateString() { local cyclestr=${1} local cycle=0 case "$cyclestr" in 0) printf "\b%s" "\\" cycle=1 ;; 1) printf "\b%s" "|" cycle=2 ;; 2) printf "\b%s" "/" cycle=3 ;; *) printf "\b%s" "-" cycle=0 esac return $cycle } function PrintEndString() { local str=${1} local slen=${2} if [ "$monochrome" = false -a $slen -gt 0 ]; then local form1="%${slen}s" # Left pad string with blanks local form2="%-${slen}s\n" # Right pad string with blanks if [ $slen -gt 0 ]; then printf "$form1" " " | tr ' ' '\b' # Clear previously printed string with backspace len=0 # Set global variable to 0 fi if [ "$str" != "" ]; then printf "$form2" "$str" # Print new string fi else printf "\n%s\n" "$str" fi } function PrintResult() { local filename=${1} local rType=${2} local option=${3} local name="" local isRegional="" local states="" local service="" local api="" local call="" local region="" local domain="" local result="" local up="" local down="" local deleted="" local error="" local other="" local stat=0 local titems=0 if [ -r "$filename" ]; then if [ "$formatstr" = "table" ]; then if [ "$rType" != "" ]; then if [ -r "${configdir}/${toolsdir}/${listsdir}/$resfile" ]; then result=`grep -i "^$rType " "${configdir}/${toolsdir}/${listsdir}/$resfile"` if [ "$result" != "" ]; then name=`echo "$result" | cut -d$'\t' -f1` # isRegional=`echo "$result" | cut -d$'\t' -f2` states=`echo "$result" | cut -d$'\t' -f3` service=`echo "$result" | cut -d$'\t' -f4` # api=`echo "$result" | cut -d$'\t' -f5` # call=`echo "$result" | cut -d$'\t' -f6` PrintEndString "Resources for type '$name' (Service: ${service}) found:" "$len" else PrintEndString "Resources for type '$rType' found:" "$len" fi fi else PrintEndString "Resources found:" "$len" fi printf "\n" fi if [ "$monochrome" = false -a "$states" != "" ]; then up=`echo "$states" | cut -d';' -f1` down=`echo "$states" | cut -d';' -f2` deleted=`echo "$states" | cut -d';' -f3` error=`echo "$states" | cut -d';' -f4` other=`echo "$states" | cut -d';' -f5` if [ "$up" != "" ]; then up="--green $up" fi if [ "$down" != "" ]; then down="--yellow $down" fi if [ "$deleted" != "" ]; then deleted="--darkgray $deleted" fi if [ "$error" != "" ]; then error="--red $error" fi if [ "$other" != "" ]; then other="--bold $other" fi if [ "$formatstr" = "table" ]; then print-table --import "$filename" $tableformat $option $up $down $deleted $error $other fi else if [ "$formatstr" = "table" ]; then print-table --import "$filename" $tableformat $option else if [ "$formatstr" = "tsv" ]; then if [ $hadheader -eq 0 ]; then cat "$filename" else cat "$filename" | tailfromline2 fi hadheader=1 else result=`filecheck -sl ${scratchfile}.json` if [ "$result" != "" ]; then result=`head -n 1 ${scratchfile}.json` if [ "$result" != "[" -a "$result" != "{" ]; then result="" fi fi if [ "$result" != "" ]; then # We have a detaild JSON file - use that cat ${scratchfile}.json | norm-json --quiet --raw > $scratchfile stat=$? if [ $stat -eq 0 ]; then titems=`cat $scratchfile | $jq -r '. | length'` region=`browse-json --select 1 --quiet --raw --import $scratchfile region` domain=`browse-json --select 1 --quiet --raw --import $scratchfile domainOcid` if [ "$region" = "" ]; then region="NONE" fi if [ "$domain" != "" ]; then domain=true else domain=false fi printf '{\n "elements": ' > ${scratchfile}.json cat $scratchfile >> ${scratchfile}.json printf ',\n"totalElements": %s,\n"createdBy": "%s",\n"region": "%s",\n"type": "%s",\n"identityDomains": %s}\n' "$titems" "$progstr" "$region" \ "$instance_type" "$domain" >> ${scratchfile}.json cat ${scratchfile}.json | $jq -M else cat ${scratchfile}.json fi filecheck -rm $scratchfile filecheck -rm ${scratchfile}.json else region=`tail -n 1 "$filename" | cut -d'.' -f4` if [ "$region" = "" ]; then region="NONE" fi if [ "$rType" = "Domain" ]; then domain=true else domain=false fi print-table --import "$filename" $tableformat $option | \ sed 's|\("contentItems":.*\)|\1,\n "creator": "'$progstr'",\n "region": "'$region'",\n "type": "'$instance_type'",\n "identityDomains": '$domain'|' fi fi fi fi fi } function GetDomainApiVersion { local api="identityDomains" local apiVersion="/admin/v1" local result="" # Check if we have the api file result=`grep "^$api " "${configdir}/${toolsdir}/${listsdir}/$apifile" 2>/dev/null` if [ "$result" != "" ]; then apiVersion=`echo "$result" | cut -d$'\t' -f2` fi # Return a string echo "$apiVersion" } function GetDomainApiEndpoint { local murl=${1} # IDCS URL local apiEndpoint="" if [ "$murl" != "" ]; then apiEndpoint=`echo "$murl" | sed 's|https://||' | sed 's|:443||'` fi # Return a string echo "$apiEndpoint" } # Get total numbers of users and groups for one identity domain function GetIdentityDomainTotalObjects() { local iname=${1} # Resource Type local murl=${2} # IDCS URL local result="" local apiEndpoint="" local apiVersion="" if [ "$iname" != "" -a "$murl" != "" ]; then # Get the api version and endpoint apiVersion=`GetDomainApiVersion` apiEndpoint=`GetDomainApiEndpoint "$murl"` result=`$ociapi "$apiEndpoint" "head" "${apiVersion}/$iname" | browse-json --select 1 --raw --quiet opcTotalItems` fi # Return a string echo "$result" } # Call REST-API to get a resource from Idenity Domain function SearchIdentityDomainResources() { local iname=${1} # Resource Type local id=${2} # OCID (optional) local stat=200 # Expect failure local result="" local apiEndpoint="" local apiVersion="" local mid="" local mls="" local midcs="" local mname="" local mtype="" local mltype="" local mcdate="" local murl="" local tusers="" local tgroups="" # Get the api version apiVersion=`GetDomainApiVersion` # Check if we have a file with all domains result=`filecheck -sl "${configdir}/${toolsdir}/${listsdir}/$domainfile"` if [ "$result" != "" ]; then # There could be more then just the default domain while IFS=$'\t' read -r mid mls midcs mname tusers tgroups mtype mltype comp mcdate murl; do if [ "$mls" = "ACTIVE" ]; then # Get the api endpoint apiEndpoint=`GetDomainApiEndpoint "$murl"` ### Test # apiEndpoint="idcs-883ccf987692485cb5820d1f79024820.identity.oraclecloud.com" # echo "name: '$name' - apiEndpoint: '$apiEndpoint' - ${apiVersion}/${iname}/$id" >> /tmp/test.txt if [ "$id" = "" ]; then $ociapi "$apiEndpoint" "get" "${apiVersion}/${iname}" > ${outfile}.test 2>/dev/null stat=$? else $ociapi "$apiEndpoint" "get" "${apiVersion}/${iname}/$id" > ${outfile}.test 2>/dev/null stat=$? fi result=`filecheck -sl ${outfile}.test` if [ $stat -eq 0 -a "$result" != "" ]; then cat ${outfile}.test fi filecheck -rm ${outfile}.test fi done < <(cat "${configdir}/${toolsdir}/${listsdir}/$domainfile" | tailfromline2) fi return $stat } # Call REST-API to get a resource from Idenity Domain function DisplayIdentityDomainResource() { local iname=${1} # Resource Type local stat=200 # Expect failure local result="" local name="" local attrstr="" local mocid="" local mactive="" local mid="" local mname="" local mdomain="" local mcomp="" local meta="" local muser="" if [ "$iname" != "" ]; then # Append an s to the string name=`echo "${iname}s"` result=`echo "$name" | tolower` if [ "$monochrome" = false ]; then PrintSearchString "Searching for ${result}..." len=$? cycle=0 fi # SearchIdentityDomainResources "$name" 2>/dev/null | norm-json --quiet > ${scratchfile}.json SearchIdentityDomainResources "$name" > ${scratchfile}.json # norm-json should be already done in oci-api stat=$? if [ "$monochrome" = false ]; then PrintUpdateString "$cycle" cycle=$? fi result=`filecheck -sl ${scratchfile}.json` if [ $stat -eq 0 -a "$result" != "" ]; then # Create a textfile with values separated by tab cat ${scratchfile}.json | $jq -r '(.[] | [.ocid, if has("active") then if .active then "ACTIVE" else "INACTIVE" end else "NONE" end, .id, if has("displayName") then .displayName else "NONE" end, .domainOcid, .compartmentOcid, .meta.created, .userName]) | @tsv' > $scratchfile if [ "$monochrome" = false ]; then PrintUpdateString "$cycle" cycle=$? fi # Create Header in result file if [ "$name" = "Users" ]; then printf "id\tlifecycleState\tuniqueId\tdisplayName\tuserName\tdomain\tcompartment\tcreated\n" > ${scratchfile}.test else printf "id\tlifecycleState\tuniqueId\tdisplayName\tdomain\tcompartment\tcreated\n" > ${scratchfile}.test fi while IFS=$'\t' read -r mocid mactive mid mname mdomain mcomp meta muser; do result=`grep "^${mdomain} ACTIVE" "${configdir}/${toolsdir}/${listsdir}/$domainfile"` if [ "$result" != "" ]; then mdomain=`echo "$result" | cut -d$'\t' -f4` fi result=`grep "^${mcomp} ACTIVE" "${configdir}/${toolsdir}/${listsdir}/$compfile"` if [ "$result" != "" ]; then mcomp=`echo "$result" | cut -d$'\t' -f3` fi # Creation date and limit displayname to 40 chars meta=`echo "$meta" | cut -d'T' -f1` mname=`ShrinkString "$mname" 40` if [ "$name" = "Users" ]; then printf "%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\n" "$mocid" "$mactive" "$mid" "$mname" "$muser" "$mdomain" "$mcomp" "$meta" >> ${scratchfile}.test else printf "%s\t%s\t%s\t%s\t%s\t%s\t%s\n" "$mocid" "$mactive" "$mid" "$mname" "$mdomain" "$mcomp" "$meta" >> ${scratchfile}.test fi done < $scratchfile # Display result PrintResult ${scratchfile}.test "$iname" # Cleanup filecheck -rm ${scratchfile}.test filecheck -rm ${scratchfile}.json else PrintEndString "No resources for type '$iname' found." "$len" fi fi } # Call REST-API and get details of specified id or list all resources if id not given function GetResource() { local iname=${1} # Resource Type local iregion=${2} # Region to use local id=${3} # OCID local stat=200 # Expect failure local result="" local rType="" local region="" local name="" local isRegional="" local states="" local service="" local api="" local call="" local apiVersion="" local apiEndpoint="" local mid="" local mls="" local murl="" local mname="" local mtype="" local mltype="" local mcdate="" if [ "$id" != "" ]; then result=`ConvertOCID "$id" | tail -n 1` if [ "$result" != "" ]; then rType=`echo "$result" | cut -d$'\t' -f2` region=`echo "$result" | cut -d$'\t' -f4` if [ "$region" = "" ]; then region="$iregion" fi else return $stat fi else rType="$iname" region="$iregion" fi # echo "rType: '$rType' - region: '$region' - id: '$id'" >> /tmp/test.txt if [ "$rType" != "" ]; then if [ -r "${configdir}/${toolsdir}/${listsdir}/$resfile" ]; then result=`grep -i "^$rType " "${configdir}/${toolsdir}/${listsdir}/$resfile"` if [ "$result" != "" ]; then name=`echo "$result" | cut -d$'\t' -f1` # isRegional=`echo "$result" | cut -d$'\t' -f2` # states=`echo "$result" | cut -d$'\t' -f3` # service=`echo "$result" | cut -d$'\t' -f4` api=`echo "$result" | cut -d$'\t' -f5` call=`echo "$result" | cut -d$'\t' -f6` # echo "name: '$name' - api: '$api' - call: '$call'" >> /tmp/test.txt if [ "$api" != "" -a "$call" != "" ]; then if [ -r "${configdir}/${toolsdir}/${listsdir}/$apifile" ]; then result=`grep "^$api " "${configdir}/${toolsdir}/${listsdir}/$apifile"` if [ "$result" != "" ]; then apiVersion=`echo "$result" | cut -d$'\t' -f2` apiEndpoint=`echo "$result" | cut -d$'\t' -f3 | sed 's|https://||' | sed 's||'"$region"'|'` if [ "$apiVersion" != "" -a "$apiEndpoint" != "" ]; then if [ "$apiVersion" = "/" ]; then apiVersion="" fi # if [ "$id" = "" ]; then # echo "name: '$name' - apiEndpoint: '$apiEndpoint' - ${apiVersion}/${call}" >> /tmp/test.txt # else # echo "name: '$name' - apiEndpoint: '$apiEndpoint' - ${apiVersion}/${call}/$id" >> /tmp/test.txt # fi case "$name" in App) # Don't search for appdomains -> only available with identity domains # SearchIdentityDomainResources "$call" "$id" # stat=$? ;; Bucket) call=`echo "$call" | sed 's|{namespaceName}|'"$namespace"'|' | sed 's|{bucketName}|'"$iname"'|'` $ociapi "$apiEndpoint" "get" "${apiVersion}/${call}" 2>/dev/null stat=$? ;; # dynamicresourcegroup) # $ociapi "$apiEndpoint" "get" "${apiVersion}/${call}/$id" 2>/dev/null # stat=$? # ;; *) if [ "$id" = "" ]; then # No id was specified: Look for all objects in root compartment $ociapi "$apiEndpoint" "get" "${apiVersion}/${call}?compartmentId=$TENANCY_ID" 2>/dev/null stat=$? else $ociapi "$apiEndpoint" "get" "${apiVersion}/${call}/$id" 2>/dev/null stat=$? fi esac fi fi fi fi fi fi fi return $stat } # Sarch for a resource with query REST API function SearchResources() { local region=${1} # e.g. eu-frankfurt-1 local rtype=${2} # e.g. compartment local where=${3} # e.g. compartmentId or identifier or availabilityDomain local is=${4} # The string we are searching for (exact match) local item=${5} # If specified, select the item (record) beginning with 0 # Create body file if [ "$rtype" = "" ]; then rtype="all" fi if [ "$where" != "" -a "$is" != "" ]; then printf '{\n "type": "Structured",\n "query": "query %s resources where %s = '"'%s'"'"\n}\n' "$rtype" "$where" "$is" > ${scratchfile}.body else printf '{\n "type": "Structured",\n "query": "query %s resources"\n}\n' "$rtype" > ${scratchfile}.body fi $ociapi "query.${region}.oraclecloud.com" "post" ${scratchfile}.body "/${querybase}/resources" > ${scratchfile}.test 2>/dev/null stat=$? result=`filecheck -sl ${scratchfile}.test` if [ $stat -eq 0 -a "$result" != "" ]; then # convert-json "identifier,lifecycleState,displayName,availabilityDomain,compartmentId,timeCreated" --import ${scratchfile}.test --quiet --noheader --output tsv > $scratchfile cat ${scratchfile}.test | $jq -r '(.['$item'] | [.identifier, if .lifecycleState == null then "NONE" else .lifecycleState end, if .displayName == null or .displayName == "" then "NONE" else .displayName end, if .availabilityDomain == null or .availabilityDomain == "" then "NONE" else .availabilityDomain end, .compartmentId, if .timeCreated == null then "NONE" else .timeCreated end]) | @tsv' stat=$? else printf "" fi # Cleanup filecheck -rm ${scratchfile}.body filecheck -rm ${scratchfile}.test # Return status return $stat } # Call OCI API and check result # API Reference: https://docs.cloud.oracle.com/en-us/iaas/api/ function UseAPI() { local proc=${1} local region=${2} local comp=${3} local outfile=${4} local optional=${5} local stat=0 local code="" # Make sure that outfile does not exists # filecheck -rm $outfile case "$proc" in GetNamespace) $ociapi "objectstorage.${region}.oraclecloud.com" "get" "/n/" > ${outfile}.test 2>/dev/null stat=$? if [ $stat -eq 0 ]; then # code=`browse-json "data" --import ${outfile}.test --select 1 --raw --quiet` code=`cat ${outfile}.test | jq -r '.[]' 2>/dev/null | head -n 1` stat=$? if [ $stat -eq 0 ]; then echo "$code" > $outfile fi fi ;; ListObjects) $ociapi "objectstorage.${region}.oraclecloud.com" "get" "/n/$namespace/b/${optional}/o" > ${outfile}.test 2>/dev/null stat=$? result=`filecheck -sl ${outfile}.test` if [ $stat -eq 0 -a "$result" != "" ]; then convert-json "name" --import ${outfile}.test --quiet --noheader --output tsv > $outfile stat=$? fi ;; ListResourceTypes) # Documentation: https://docs.oracle.com/en-us/iaas/Content/Search/Concepts/queryoverview.htm#Overview_of_Search # Permissions needed: https://docs.oracle.com/en-us/iaas/Content/Identity/Reference/searchpolicyreference.htm#Details_for_Search $ociapi "query.${region}.oraclecloud.com" "get" "/${querybase}/resourceTypes" > ${outfile}.test 2>/dev/null stat=$? result=`filecheck -sl ${outfile}.test` if [ $stat -eq 0 -a "$result" != "" ]; then convert-json "name" --import ${outfile}.test --quiet --noheader --output tsv > $outfile stat=$? fi ;; # SearchAvailabilityDomains) # printf '{\n "type": "Structured",\n "query": "query %s resources where availabilityDomain = '"'%s'"'"\n}\n' "$optional" "$comp" > ${outfile}.body # # $ociapi "query.${region}.oraclecloud.com" "post" ${outfile}.body "/${querybase}/resources" > ${outfile}.test 2>/dev/null # stat=$? # # result=`filecheck -sl ${outfile}.test` # if [ $stat -eq 0 -a "$result" != "" ]; then # cat ${outfile}.test | $jq -r '(.[0] | [.identifier, if .lifecycleState == null then "NONE" else .lifecycleState end, .displayName, if .availabilityDomain == null or .availabilityDomain == "" then "NONE" else .availabilityDomain end, .compartmentId, .timeCreated]) | @tsv' > $outfile # stat=$? # else # printf "" > $outfile # fi # # filecheck -rm ${outfile}.body # ;; # SearchResources) # # Create body file # if [ "$optional" = "" ]; then # optional="all" # fi # # if [ "$comp" != "" ]; then # code=`echo "$comp" | grep '^ocid1\.compartment\.oc1\.'` # if [ "$code" != "" ]; then # printf '{\n "type": "Structured",\n "query": "query %s resources where compartmentId = '"'%s'"'"\n}\n' "$optional" "$comp" > ${outfile}.body # else # printf '{\n "type": "Structured",\n "query": "query %s resources where identifier = '"'%s'"'"\n}\n' "$optional" "$comp" > ${outfile}.body # fi # else # printf '{\n "type": "Structured",\n "query": "query %s resources"\n}\n' "$optional" > ${outfile}.body # fi # # $ociapi "query.${region}.oraclecloud.com" "post" ${outfile}.body "/${querybase}/resources" > ${outfile}.test 2>/dev/null # stat=$? # # result=`filecheck -sl ${outfile}.test` # if [ $stat -eq 0 -a "$result" != "" ]; then # # convert-json "identifier,lifecycleState,displayName,availabilityDomain,compartmentId,timeCreated" --import ${outfile}.test --quiet --noheader --output tsv > $outfile # cat ${outfile}.test | $jq -r '(.[] | [.identifier, if .lifecycleState == null then "NONE" else .lifecycleState end, if .displayName == "" then "NONE" else .displayName end, if .availabilityDomain == null or .availabilityDomain == "" then "NONE" else .availabilityDomain end, .compartmentId, if .timeCreated == null then "NONE" else .timeCreated end]) | @tsv' > $outfile # stat=$? # else # printf "" > $outfile # fi # # filecheck -rm ${outfile}.body # ;; ListRegionSubscriptions) $ociapi "identity.${region}.oraclecloud.com" "get" "/${iambase}/tenancies/${comp}/regionSubscriptions" > ${outfile}.test 2>/dev/null stat=$? result=`filecheck -sl ${outfile}.test` if [ $stat -eq 0 -a "$result" != "" ]; then convert-json "isHomeRegion,regionKey,regionName,status" --import ${outfile}.test --quiet --noheader --output tsv > $outfile stat=$? fi ;; ListAvailabilityDomains) $ociapi "identity.${region}.oraclecloud.com" "get" "/${iambase}/availabilityDomains/?compartmentId=$comp" > ${outfile}.test 2>/dev/null stat=$? result=`filecheck -sl ${outfile}.test` if [ $stat -eq 0 -a "$result" != "" ]; then convert-json "id,name" --import ${outfile}.test --quiet --noheader --output tsv > $outfile stat=$? fi ;; ListDomains) $ociapi "identity.${region}.oraclecloud.com" "get" "/${iambase}/domains/?compartmentId=$comp" > ${outfile}.test 2>/dev/null stat=$? result=`filecheck -sl ${outfile}.test` if [ $stat -eq 0 -a "$result" != "" ]; then convert-json "id,lifecycleState,homeRegionUrl,displayName,type,licenseType,timeCreated" --import ${outfile}.test --quiet --noheader --output tsv > $outfile stat=$? else printf "" > $outfile fi ;; ListCompartments | GetCompartment) if [ "$proc" = "ListCompartments" ]; then $ociapi "identity.${region}.oraclecloud.com" "get" "/${iambase}/compartments/?compartmentId=$comp" > ${outfile}.test 2>/dev/null stat=$? else $ociapi "identity.${region}.oraclecloud.com" "get" "/${iambase}/compartments/${comp}?compartmentId=$comp" > ${outfile}.test 2>/dev/null stat=$? fi result=`filecheck -sl ${outfile}.test` if [ $stat -eq 0 -a "$result" != "" ]; then convert-json "id,lifecycleState,name,availabilityDomain,compartmentId,timeCreated,description,isAccessible" \ --import ${outfile}.test --quiet --noheader --output tsv > $outfile fi ;; *) stat=98 errormsg $stat "($progstr) Unknown function call." esac # Cleanup filecheck -rm ${outfile}.test # Return status return $stat } # List all supported resource types function ListAllResourceTypes() { local stat=0 local name="" local regional="" local states="" local api="" local call="" if [ -r "${configdir}/${toolsdir}/${listsdir}/$resfile" ]; then printf "name\tisRegional\tservice\n" > $scratchfile while IFS=$'\t' read -r name regional states service api call; do printf "%s\t%s\t%s\n" "$name" "$regional" "$service" >> $scratchfile done < <(cat "${configdir}/${toolsdir}/${listsdir}/$resfile" | stripcomment | tailfromline2) if [ "$formatstr" = "table" ]; then printf "\nAll supported resource types:\n\n" print-table --import $scratchfile $tableformat else if [ "$formatstr" = "tsv" ]; then cat $scratchfile else print-table --import $scratchfile $tableformat fi fi fi } # List all available resource types in the Home Region and check if they are currently supported function CheckAllResourceTypes() { local stat=0 local name="" local result="" if [ "$monochrome" = false ]; then PrintSearchString "Searching for all searchable resources in Home Region..." len=$? cycle=0 fi UseAPI "ListResourceTypes" "$HOME_REGION" "$TENANCY_ID" "$scratchfile" stat=$? result=`filecheck -s $scratchfile` if [ $stat -eq 0 -a "$result" != "" ]; then if [ "$monochrome" = false ]; then PrintUpdateString "$cycle" cycle=$? fi printf "name\tknown\n" > ${scratchfile}.test while IFS=$'\t' read -r name; do result=`grep -i "^$name " "${configdir}/${toolsdir}/${listsdir}/$resfile"` if [ "$result" != "" ]; then printf "%s\t%s\n" "$name" "Yes" >> ${scratchfile}.test else printf "%s\t%s\n" "$name" "No" >> ${scratchfile}.test fi if [ "$monochrome" = false ]; then PrintUpdateString "$cycle" cycle=$? fi done < $scratchfile if [ "$formatstr" = "table" ]; then if [ "$monochrome" = false ]; then PrintEndString "All available resource types:" "$len" printf "\n" else printf "\nAll available resource types:\n\n" fi if [ "$monochrome" = false ]; then print-table --import ${scratchfile}.test $tableformat --green "Yes" --red "No" else print-table --import ${scratchfile}.test $tableformat fi else if [ "$formatstr" = "tsv" ]; then cat ${scratchfile}.test else print-table --import ${scratchfile}.test $tableformat fi fi # Cleanup filecheck -rm ${scratchfile}.test else if [ "$monochrome" = false ]; then PrintEndString "No searchable resources found in Home Region." "$len" else echo "No searchable resources found in Home Region." fi fi } function GetRegionSubscriptions() { local isHomeRegion="" local regionKey="" local regionName="" local status="" local realmKey="" local avds="" local description="" local result="" # Create a list with all sbscribed regions UseAPI "ListRegionSubscriptions" "$HOME_REGION" "$TENANCY_ID" "$scratchfile" stat=$? result=`filecheck -s $scratchfile` if [ $stat -eq 0 -a "$result" != "" ]; then printf "regionName\tstatus\tisHomeRegion\tregionKey\trealmKey\tavds\tdescription\n" > ${scratchfile}.regn while IFS=$'\t' read -r isHomeRegion regionKey regionName status; do if [ -r "${configdir}/${toolsdir}/${listsdir}/$regfile" ]; then result=`grep -i "^$regionKey " "${configdir}/${toolsdir}/${listsdir}/$regfile"` if [ "$result" != "" ]; then realmKey=`echo "$result" | cut -d$'\t' -f2` avds=`echo "$result" | cut -d$'\t' -f4` description=`echo "$result" | cut -d$'\t' -f5` fi fi printf "%s\t%s\t%s\t%s\t%s\t%s\t%s\n" "$regionName" "$status" "$isHomeRegion" "$regionKey" "$realmKey" "$avds" "$description" >> ${scratchfile}.regn done < <(cat $scratchfile | sort -t$'\t' -k3) fi } function GetDataCenterFromAVD() { local avd=${1} local avdkey="" local avdname="" local region="" local rtype="" local uid="" local result="" local stat=0 avd=`echo "$avd" | grep '\:'` # Check if avd contains colon if [ "$avd" != "" ]; then avdkey=`echo "$avd" | cut -d':' -f1` region=`echo "$avd" | cut -d':' -f2 | tolower` region=`echo "$region" | grep '\-'` # Check if avdname contains hyphen if [ "$region" != "" ]; then avdname=`echo "$region" | tail -c 5` # Last 4 chars + newline region=`echo "$region" | sed 's|-'$avdname'$||'` # Delete the avdname from the region if [ "$region" != "" ]; then region=`AdjustRegion "$region"` result=`filecheck -x base32` if [ "$result" != "" ]; then # Decrypt real DC with base32 for rtype in vnic volume privateip database; do # UseAPI "SearchAvailabilityDomains" "$region" "$avd" "${scratchfile}.json" "$rtype" # stat=$? SearchResources "$region" "$rtype" "availabilityDomain" "$avd" "0" > ${scratchfile}.json stat=$? result=`filecheck -s ${scratchfile}.json` if [ $stat -eq 0 -a "$result" != "" ]; then uid=`cat ${scratchfile}.json | cut -d$'\t' -f1` dc=`ConvertOCID "$uid" | tail -n 1 | cut -d$'\t' -f6` printf "%s:%s\n" "$avdname" "$dc" filecheck -rm ${scratchfile}.json return fi filecheck -rm ${scratchfile}.json done fi fi # Return at least anything printf "%s:\n" "$avdname" fi fi } function GetAvailabilityDomains() { local regname="" local regstat="" local id="" local name="" local dummy="" local code="" if [ "$force" = false -a "$instance_type" != "availabilitydomain" ]; then result=`filecheck -fy "${configdir}/${toolsdir}/${listsdir}/$adfile"` else result="" fi if [ "$result" != "" ]; then PrintResult "$result" "AvailabilityDomain" else # We only search for availability domains in subscribed regions if [ -r "${scratchfile}.regn" ]; then if [ "$monochrome" = false ]; then PrintSearchString "Searching for availability domains..." len=$? cycle=0 fi printf "id\tregionName\tname\tcode\n" > ${scratchfile}.avd while IFS=$'\t' read -r regname regstat dummy dummy dummy dummy dummy; do if [ "$regname" != "" -a "$regstat" = "READY" ]; then # $oci iam availability-domain list | norm-json # Get a list with all ad for the specifies region UseAPI "ListAvailabilityDomains" "$regname" "$TENANCY_ID" "$scratchfile" stat=$? if [ "$monochrome" = false ]; then PrintUpdateString "$cycle" cycle=$? fi result=`filecheck -s $scratchfile` if [ $stat -eq 0 -a "$result" != "" ]; then while IFS=$'\t' read -r id name; do code=`GetDataCenterFromAVD $name` printf "%s\t%s\t%s\t%s\n" "$id" "$regname" "$name" "$code" >> ${scratchfile}.avd done < <(cat $scratchfile | sort -t$'\t' -k2) fi fi done < <(cat ${scratchfile}.regn | tailfromline2) # Delete avd file if we couln't find items regstat=`filecheck -sl ${scratchfile}.avd` if [ "$regstat" = "" ]; then filecheck -rm ${scratchfile}.avd PrintEndString "No resources for type 'AvailabilityDomain' found." "$len" else mv -f ${scratchfile}.avd "${configdir}/${toolsdir}/${listsdir}/$adfile" PrintResult "${configdir}/${toolsdir}/${listsdir}/$adfile" "AvailabilityDomain" fi fi fi } # Scan all compartmentIDs and build directory list (recursive) function BuildCompartments() { local comp=${1} local root=${2} local ts="$RANDOM" local id="" local name="" local avd="" local cid="" local cdate="" local desc="" local access="" # Just in case we call the function without any parameter if [ "$comp" = "" ]; then # First call of function with empty compartment - get the root compartment grep "^$TENANCY_ID " ${scratchfile}.comp > ${scratchfile}.$ts else grep " $comp " ${scratchfile}.comp | sort -t$'\t' -k3 > ${scratchfile}.$ts fi if [ "$monochrome" = false ]; then PrintUpdateString "$cycle" cycle=$? fi result=`filecheck -s ${scratchfile}.$ts` if [ "$result" != "" ]; then # "id\tlifecycleState\tname\tavailabilityDomain\tcompartmentId\ttimeCreated\tdescription\tisAccessible\n" while IFS=$'\t' read -r id ls name avd cid cdate desc access; do cdate=`echo "$cdate" | cut -d'T' -f1` # if [ "$desc" = "" -o "$access" = "" ]; then # # Get compartment details # UseAPI "GetCompartment" "$HOME_REGION" "$id" "$scratchfile" # stat=$? # # if [ $stat -eq 0 ]; then # desc=`cat $scratchfile | cut -d$'\t' -f7` # access=`cat $scratchfile | cut -d$'\t' -f8` # fi # fi if [ "$root" = "" ]; then printf "%s\t%s\t%s\t%s\n" "$id" "$ls" "$name" "$cdate" >> ${scratchfile}.name BuildCompartments "$id" "$name" else printf "%s\t%s\t%s\t%s\n" "$id" "$ls" "${root}/$name" "$cdate" >> ${scratchfile}.name BuildCompartments "$id" "${root}/$name" fi done < ${scratchfile}.$ts fi # Remove scratchfile filecheck -rm ${scratchfile}.$ts } function GetCompartment() { local comp=${1} local code="" local access="?" # Just in case we call the function without any parameter if [ "$comp" = "" ]; then comp="$TENANCY_ID" fi # To list all compartments, add: --compartment-id-in-subtree true # comp=`$oci iam compartment list --all | browse-json compartmentId --select 1 --quiet` # root=`$oci iam compartment get --compartment-id $comp | browse-json name --select 1 --quiet` # Get compartment details UseAPI "GetCompartment" "$HOME_REGION" "$comp" "$scratchfile" stat=$? result=`filecheck -s $scratchfile` if [ $stat -eq 0 -a "$result" != "" ]; then cat $scratchfile | sed 's|\tnull\tnull\t|\tNone\tNone\t|' >> ${scratchfile}.comp fi } # List root compartment and all the childs function ListAllCompartments() { local stat=0 local result="" if [ "$force" = false -a "$instance_type" != "compartment" ]; then result=`filecheck -fc "${configdir}/${toolsdir}/${listsdir}/$compfile"` else result="" fi if [ "$result" != "" ]; then if [ "$formatstr" = "table" ]; then PrintResult "$result" "Compartment" else if [ "$formatstr" = "tsv" -a "$instance_type" = "compartment" ]; then cat "$result" fi fi else if [ "$monochrome" = false ]; then PrintSearchString "Searching for compartments..." len=$? cycle=0 fi # Create header printf "id\tlifecycleState\tname\tavailabilityDomain\tcompartmentId\ttimeCreated\tdescription\tisAccessible\n" > ${scratchfile}.comp # Get tenancy ocid and name GetCompartment "$TENANCY_ID" if [ "$monochrome" = false ]; then PrintUpdateString "$cycle" cycle=$? fi # Search for all compartments # UseAPI "SearchResources" "$HOME_REGION" "" "$scratchfile" "compartment" # stat=$? SearchResources "$HOME_REGION" "compartment" > $scratchfile stat=$? result=`filecheck -s $scratchfile` if [ $stat -eq 0 -a "$result" != "" ]; then if [ "$monochrome" = false ]; then PrintUpdateString "$cycle" cycle=$? fi cat $scratchfile >> ${scratchfile}.comp printf "id\tlifecycleState\tcompartment\tcreated\n" > ${scratchfile}.name BuildCompartments mv -f ${scratchfile}.name "${configdir}/${toolsdir}/${listsdir}/$compfile" if [ "$formatstr" = "table" ]; then PrintResult "${configdir}/${toolsdir}/${listsdir}/$compfile" "Compartment" else if [ "$formatstr" = "tsv" -a "$instance_type" = "compartment" ]; then cat "${configdir}/${toolsdir}/${listsdir}/$compfile" else if [ "$formatstr" = "json" -a "$instance_type" = "compartment" ]; then PrintResult "${configdir}/${toolsdir}/${listsdir}/$compfile" "Compartment" fi fi fi else if [ "$formatstr" = "table" ]; then PrintEndString "No resources for type 'Compartment' found." "$len" fi fi fi } # List all domains function ListAllDomains() { local stat=0 local id="" local ls="" local comp="" local cdate="" local mid="" local mls="" local midcs="" local mname="" local mtype="" local mltype="" local mcdate="" local murl="" local tusers="" local tgroups="" local result="" if [ "$force" = false -a "$instance_type" != "domain" ]; then result=`filecheck -fc "${configdir}/${toolsdir}/${listsdir}/$domainfile"` else result="" fi if [ "$result" != "" ]; then if [ "$formatstr" = "table" ]; then PrintResult "$result" "Domain" else if [ "$formatstr" = "tsv" -a "$instance_type" = "domain" ]; then cat "$result" fi fi else if [ "$monochrome" = false ]; then PrintSearchString "Searching for domains..." len=$? cycle=0 fi # cat ${configdir}/${toolsdir}/${listsdir}/$compfile > /tmp/test.txt printf "id\tlifecycleState\tuniqueId\tdisplayName\ttotalUsers\ttotalGroups\ttype\tlicenseType\tcompartment\tcreated\n" > ${scratchfile}.domain while IFS=$'\t' read -r id ls comp cdate; do # $oci iam domain list --compartment-id $id --all > $scratchfile 2>&1 # stat=$? # Get a list with all domains UseAPI "ListDomains" "$HOME_REGION" "$id" "$scratchfile" stat=$? if [ "$monochrome" = false ]; then PrintUpdateString "$cycle" cycle=$? fi result=`filecheck -s $scratchfile` if [ $stat -eq 0 -a "$result" != "" ]; then while IFS=$'\t' read -r mid mls murl mname mtype mltype mcdate; do mcdate=`echo "$mcdate" | cut -d'T' -f1` midcs=`echo "$murl" | sed 's|^https://idcs-||' | cut -d'.' -f1` mltype=`echo "$mltype" | sed 's|^oracle identity cloud service|IDCS|' | sed 's| - user per month$||'` tusers=`GetIdentityDomainTotalObjects "Users" "$murl"` tgroups=`GetIdentityDomainTotalObjects "Groups" "$murl"` # mname=`ShrinkString "$mname" 40` printf "%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\n" "$mid" "$mls" "$midcs" "$mname" "$tusers" "$tgroups" "$mtype" "$mltype" "$comp" "$mcdate" "$murl" >> ${scratchfile}.domain done < $scratchfile fi done < <(cat "${configdir}/${toolsdir}/${listsdir}/$compfile" | tailfromline2) result=`filecheck -sl ${scratchfile}.domain` if [ "$result" != "" ]; then mv -f ${scratchfile}.domain "${configdir}/${toolsdir}/${listsdir}/$domainfile" if [ "$formatstr" != "json" -o "$instance_type" = "domain" ]; then PrintResult "${configdir}/${toolsdir}/${listsdir}/$domainfile" "Domain" fi else filecheck -rm ${scratchfile}.domain PrintEndString "No resources for type 'Domain' found." "$len" fi fi } # Display all resources. If regname is empty - display non regional ressources - else resource for this region function DisplayResources() { local regname=${1} local cid=${2} local stat=0 local len=0 local cycle=0 local itype="" local typelist="" local result="" if [ "$regname" = "" ]; then # Search for non regional resources if [ "$instance_type" = "all" ]; then if [ -r "${configdir}/${toolsdir}/${listsdir}/$resfile" ]; then if [ "$searchdomains" = true ]; then cat "${configdir}/${toolsdir}/${listsdir}/$resfile" | grep -v "^AvailabilityDomain " | grep -v "^Compartment " | grep -v "^Domain " | grep -v "^User " | grep -v "^Group " > $scratchfile typelist=`grep " No " "$scratchfile" | tolower | cut -d$'\t' -f1 | tr '\n' ' ' | sed 's| $||'` else cat "${configdir}/${toolsdir}/${listsdir}/$resfile" | grep -v "^AvailabilityDomain " | grep -v "^Compartment " | grep -v "^Domain " > $scratchfile typelist=`grep " No " "$scratchfile" | tolower | cut -d$'\t' -f1 | tr '\n' ' ' | sed 's| $||'` fi fi else for itype in $instance_type; do result="" if [ "$itype" != "compartment" -a "$itype" != "availabilitydomain" -a "$itype" != "domain" ]; then if [ -r "${configdir}/${toolsdir}/${listsdir}/$resfile" ]; then result=`grep -i "^$itype No " "${configdir}/${toolsdir}/${listsdir}/$resfile" | tolower | cut -d$'\t' -f1` fi fi if [ "$result" != "" ]; then if [ "$typelist" = "" ]; then typelist="$result" else typelist="${typelist} $result" fi fi done fi else # Search for regional resources if [ "$instance_type" = "all" ]; then if [ -r "${configdir}/${toolsdir}/${listsdir}/$resfile" ]; then cat "${configdir}/${toolsdir}/${listsdir}/$resfile" | grep -v "^App " > $scratchfile typelist=`grep " Yes " $scratchfile | tolower | cut -d$'\t' -f1 | tr '\n' ' ' | sed 's| $||'` else typelist="all" fi else for itype in $instance_type; do result=`grep -i "^$itype Yes " "${configdir}/${toolsdir}/${listsdir}/$resfile" | tolower | cut -d$'\t' -f1` if [ "$result" != "" ]; then if [ "$typelist" = "" ]; then typelist="$result" else typelist="${typelist} $result" fi fi done fi fi if [ "$typelist" = "" ]; then if [ "$regname" = "" -a "$formatstr" = "table" ]; then printf "\n" fi else if [ "$formatstr" = "table" ]; then if [ "$regname" = "" ]; then printf "\n" printf "******** More non regional resources ********\n" > $scratchfile else # ${scratchfile}.regn: "regionName\tstatus\tisHomeRegion\tregionKey\trealmKey\tavds\tdescription\n" # result=`grep -i "^$key " ${scratchfile}.regn` # if [ "$result" != "" ]; then # avds=`echo "$result" | cut -d$'\t' -f4` # description=`echo "$result" | cut -d$'\t' -f5` # fi if [ "$home" = "Yes" ]; then home="(Home) " else home="" fi if [ "$avds" != "" -a "$description" != "" ]; then printf '*** Region: %s %s- Key: %s - #AD: %s - Name: %s ***\n' "$regname" "$home" "$key" "$avds" "$description" > $scratchfile else printf "******** Region: %s %s- Key: %s ********\n" "$regname" "$home" "$key" > $scratchfile fi fi # Print the header print-header --import $scratchfile $phopt fi # Walk through all resource types for itype in $typelist; do if [ "$regname" = "" ]; then if [ "$monochrome" = false ]; then if [ $len -eq 0 ]; then PrintSearchString "Searching for non regional resources..." len=$? cycle=0 else PrintUpdateString "$cycle" cycle=$? fi fi printf "id\tlifecycleState\tdisplayName\tcompartment\tcreated\n" > ${scratchfile}.inst # UseAPI "SearchResources" "$HOME_REGION" "" "$scratchfile" "$itype" # stat=$? SearchResources "$HOME_REGION" "$itype" > $scratchfile stat=$? else if [ "$monochrome" = false ]; then if [ $len -eq 0 ]; then cycle=0 if [ "$typelist" = "all" ]; then PrintSearchString "Searching for all resources in region '$regname'..." len=$? else PrintSearchString "Searching for regional resources in region '$regname'..." len=$? fi else PrintUpdateString "$cycle" cycle=$? fi fi printf "id\tlifecycleState\tdisplayName\tavailabilityDomain\tcompartment\tcreated\n" > ${scratchfile}.inst # UseAPI "SearchResources" "$regname" "$cid" "$scratchfile" "$itype" # stat=$? SearchResources "$regname" "$itype" "compartmentId" "$cid" > $scratchfile stat=$? fi # if [ $stat -eq 0 -a "$optparam" = "detail" ]; then # if [ "$monochrome" = false ]; then # PrintUpdateString "$cycle" # cycle=$? # fi # # if [ "$regname" = "" ]; then # GetResource "$itype" "$HOME_REGION" >> ${scratchfile}.json # stat=$? # else # GetResource "$itype" "$regname" >> ${scratchfile}.json # stat=$? # fi # fi result=`filecheck -s ${scratchfile}.inst` if [ $stat -eq 0 -a "$result" != "" ]; then while IFS=$'\t' read -r id ls name avd comp cdate; do if [ "$id" != "" ]; then # Display only the first 30 letters of name (if it is longer) dname=`ShrinkString "$name" 40` # Get rid og the time after the date cdate=`echo "$cdate" | cut -d'T' -f1` # Print lifecycleState in upper case letters ls=`echo "$ls" | toupper` if [ -r "${configdir}/${toolsdir}/${listsdir}/$compfile" ]; then cname=`grep -i "^$comp " "${configdir}/${toolsdir}/${listsdir}/$compfile" | cut -d$'\t' -f3` if [ "$cname" = "" ]; then cname="$comp" fi else cname="$comp" fi if [ "$regname" = "" ]; then printf "%s\t%s\t%s\t%s\t%s\n" "$id" "$ls" "$dname" "$cname" "$cdate" >> ${scratchfile}.inst else printf "%s\t%s\t%s\t%s\t%s\t%s\n" "$id" "$ls" "$dname" "$avd" "$cname" "$cdate" >> ${scratchfile}.inst fi if [ "$formatstr" = "json" ]; then if [ "$monochrome" = false ]; then PrintUpdateString "$cycle" cycle=$? fi if [ "$regname" = "" ]; then GetResource "$name" "$HOME_REGION" "$id" >> ${scratchfile}.json stat=$? else GetResource "$name" "$regname" "$id" >> ${scratchfile}.json stat=$? fi fi fi done < <(cat $scratchfile | sort) result=`filecheck -sl ${scratchfile}.inst` if [ "$result" != "" ]; then # Print obiects found PrintResult "${scratchfile}.inst" "$itype" fi fi done if [ "$formatstr" = "table" ]; then if [ $len -eq 0 ]; then printf "\n" else PrintEndString "" "$len" fi fi fi } # Create a header String function DisplayHeader() { local num=0 local result="" if [ "$formatstr" = "table" ]; then if [ "$param" = "search" ]; then echo "OCI object (active resources) report" > $scratchfile if [ "$searchdomains" = true ]; then echo "Action: $param (Identity Domains)" >> $scratchfile else echo "Action: $param" >> $scratchfile fi # num=`echo "$instance_type" | wc -w` result=`echo "$instance_type" | sed 's| |,|g'` echo "Type: $result" >> $scratchfile if [ "$compartment_id" = "" ]; then echo "Compartment: all" >> $scratchfile else echo "Compartment: $compartment_id" >> $scratchfile fi if [ "$region_str" = "" ]; then echo "Region: all" >> $scratchfile else echo "Region: $region_str" >> $scratchfile fi else echo "OCI object" > $scratchfile echo "Action: $param" >> $scratchfile fi result=`filecheck -s $scratchfile` if [ "$result" != "" ]; then printf "\n" print-header --import $scratchfile $phopt # Cleanup filecheck -rm $scratchfile fi fi } # Preset force=false monochrome=false searchdomains=false hadheader=0 len=0 cycle=0 idcs=0 namespace="" region_str="" compartment_id="" instance_type="" formatstr="" tableformat="" param="" result="" # Check parameters: Loop until all parameters are used up while [ $# -gt 0 ]; do pname=${1} case "$pname" in -c | --compartment-id) shift if [ "$1" != "" ]; then compartment_id=`echo "$1" | tolower` result=`echo "$compartment_id" | grep '^ocid1\.tenancy\.oc1\.'` if [ "$result" = "" ]; then result=`echo $compartment_id | grep '^ocid1\.compartment\.oc1\.'` if [ "$result" = "" ]; then errstr="Invalid compartment ocid '$compartment_id' specified after parameter '$pname'." fi fi shift else errstr="Please specify a compartment or tenancy ocid after parameter '$pname'." fi ;; -r | --region) shift if [ "$1" != "" ]; then if [ "$region_str" = "" ]; then region_str=`echo "$1" | tolower` result=`echo $region_str | grep '^..-.*-.'` if [ "$result" = "" ]; then errstr="Invalid region string '$region_str' specified after parameter '$pname'." fi fi shift else errstr="Please specify a region string after parameter '$pname'." fi ;; -t | --type) shift if [ "$1" != "" ]; then if [ "$instance_type" = "" ]; then instance_type=`ConvertKeys "$1"` else errstr="Option '$pname' used more then once." fi shift else errstr="Please specify a resource type after parameter '$pname'." fi ;; -o | --output) shift if [ "$1" != "" ]; then if [ "$formatstr" = "" ]; then formatstr=`echo $1 | tolower` if [ "$formatstr" != "line" -a "$formatstr" != "json" -a "$formatstr" != "tsv" -a "$formatstr" != "table" ]; then errstr="Unknown format '$formatstr' after parameter '$pname'. Please choose from 'line', 'json', 'tsv' or 'table'." else case "$formatstr" in line) tableformat="$pname $formatstr" formatstr="table" ;; tsv) monochrome=false ;; json) tableformat="$pname $formatstr" monochrome=false ;; esac fi else errstr="Option '$pname' used more then once." fi shift else errstr="Please specify a format ('line', 'json', 'tsv' or 'table') after parameter '$pname'." fi ;; -v | --version) shift showversion=true ;; -h | --help) shift showhelp=true ;; -f | --force) shift force=true ;; -m | --monochrome) shift monochrome=true ;; -d | --domains) shift searchdomains=true ;; *) paramck=`echo "$1" | grep '^-'` # Types don't begin with '-' if [ "$param" = "" ]; then param=`echo "$1" | tolower` else errstr="Unknown additional parameter: '$1'." fi shift esac done # Set defaults if [ "$instance_type" = "" ]; then instance_type="all" fi if [ "$formatstr" = "" ]; then formatstr="table" fi # Download API files Initialize # Plausibility check if [ "$region_str" != "" ]; then if [ -r "${configdir}/${toolsdir}/${listsdir}/$regfile" ]; then result=`grep " ${region_str} " "${configdir}/${toolsdir}/${listsdir}/$regfile"` if [ "$result" = "" ]; then errstr="Selected region '$region_str' seems not to be a valid region." fi fi fi if [ "$instance_type" != "all" ]; then if [ -r "${configdir}/${toolsdir}/${listsdir}/$resfile" ]; then for itype in $instance_type; do result=`grep -i "^${itype} " "${configdir}/${toolsdir}/${listsdir}/$resfile"` if [ "$result" = "" ]; then errstr="Selected type '$itype' seems not to be a valid resource type." fi done fi fi if [ "$param" = "" -o "$param" = "search" ]; then if [ "$formatstr" = "tsv" -o "$formatstr" = "json" ]; then stat=`echo "$instance_type" | wc -w` if [ "$instance_type" = "all" -o $stat -gt 1 ]; then errstr="Only one resource type can be searched when using option 'output' with 'tsv' or 'json'." fi fi fi # Display help or error message DisplayHelp ### Main # Color for print-header the header if [ "$monochrome" = false ]; then phopt="--color $blue" # phopt: Color option for print-header else phopt="" fi # Check if OCI-API is configured jq=`filecheck -x jq` ociapi=`filecheck -x oci-api` if [ "$ociapi" = "" -o "$jq" = "" ]; then exitcode=97 errormsg $exitcode "($progstr) 'oci-api' or 'jq' not installed." else if [ "$HOME_REGION" != "" -a "$TENANCY_ID" != "" ]; then UseAPI "GetNamespace" "$HOME_REGION" "$TENANCY_ID" "$scratchfile" stat=$? result=`filecheck -s $scratchfile` if [ $stat -gt 0 -o "$result" = "" ]; then exitcode=97 errormsg $exitcode "($progstr) 'oci-api' not configured correct." else namespace=`cat $scratchfile` fi filecheck -rm $scratchfile else exitcode=97 errormsg $exitcode "($progstr) OCI API 'oci-api' not configured. Please 'source .admintools'." fi fi if [ $exitcode -eq 0 ]; then # if no paramater was specified - we are searching objects if [ "$param" = "" ]; then param="search" fi case "$param" in search) DisplayHeader ;; list) DisplayHeader ListAllResourceTypes ;; check) DisplayHeader CheckAllResourceTypes ;; analyze) exitcode=2 errormsg $exitcode "($progstr) Action '$param' not yet implemented." ;; *) exitcode=2 errormsg $exitcode "($progstr) Action '$param' unknown." esac if [ $exitcode -eq 0 -a "$param" != "list" -a "$param" != "check" ]; then # Create a list with all subscribed regions # $oci iam region-subscription list --tenancy-id "$TENANCY_ID" --all | convert-json "isHomeRegion,regionKey,regionName,status" \ # --quiet --output tsv | sort > ${scratchfile}.regn # Check if we specified a region and if this region is subscribed GetRegionSubscriptions if [ -r "${scratchfile}.regn" ]; then # Check if external variable $HOME_REGION is really the home region result=`grep " Yes " "${scratchfile}.regn"` if [ "$result" != "" ]; then result=`echo "$result" | cut -d$'\t' -f1` if [ "$result" != "$HOME_REGION" ]; then exitcode=95 errormsg $exitcode "($progstr) Home region found ('$result') is different then ext. variable 'HOME_REGION' ('$HOME_REGION')." fi else exitcode=95 errormsg $exitcode "($progstr) Home region could not be validated." fi # Check if the region specified in parameters is subscribed if [ "$region_str" != "" ]; then result=`grep "^${region_str} READY " "${scratchfile}.regn"` if [ "$result" = "" ]; then exitcode=96 errormsg $exitcode "($progstr) Specified region '$region_str' not subscribed or not READY." else # Shorten Region Subscription List to selected region head -n 1 ${scratchfile}.regn > $scratchfile echo "$result" >> $scratchfile mv -f $scratchfile ${scratchfile}.regn fi fi else exitcode=96 errormsg $exitcode "($progstr) Could not get subscribed regions." fi if [ $exitcode -eq 0 ]; then if [ "$param" = "search" ]; then # Display all subscribed regions if [ -r "${scratchfile}.regn" ]; then # Print result if [ "$formatstr" = "table" ]; then if [ "$region_str" != "" ]; then printf "\nRegion selected:\n\n" else printf "\nRegion Subscriptions (Service: IAM) found:\n\n" fi if [ "$monochrome" = false ]; then print-table --import ${scratchfile}.regn $tableformat --green "READY" --red "IN_PROGRESS" --bold "YES" else print-table --import ${scratchfile}.regn $tableformat fi fi # Display all availability domains for all subscribed regions CheckResType "availabilitydomain" stat=$? if [ $stat -gt 0 ]; then GetAvailabilityDomains if [ "$instance_type" != "availabilitydomain" ]; then DeleteResType "availabilitydomain" fi fi fi # List compartments as directory list if [ "$instance_type" != "availabilitydomain" ]; then ListAllCompartments fi if [ "$searchdomains" = true ]; then if [ "$formatstr" = "table" ]; then printf "\n" printf "******** Identity domain resources ********\n" | print-header $phopt fi # List domains if available if [ "$instance_type" != "compartment" -a "$instance_type" != "availabilitydomain" ]; then ListAllDomains fi # Check if we have more then one idcs instance result=`filecheck -sl "${configdir}/${toolsdir}/${listsdir}/$domainfile"` if [ "$result" != "" ]; then idcs=`cat "${configdir}/${toolsdir}/${listsdir}/$domainfile" | wc -l` let idcs-- else searchdomains=false fi if [ $idcs -gt 0 ]; then if [ "$instance_type" != "compartment" -a "$instance_type" != "availabilitydomain" -a "$instance_type" != "domain" ]; then CheckResType "user" stat=$? if [ $stat -gt 0 ]; then DisplayIdentityDomainResource "User" DeleteResType "user" fi CheckResType "group" stat=$? if [ $stat -gt 0 ]; then DisplayIdentityDomainResource "Group" DeleteResType "group" fi CheckResType "app" stat=$? if [ $stat -gt 0 ]; then DisplayIdentityDomainResource "App" DeleteResType "app" fi else searchdomains=false fi fi fi # printf "\nHOME_REGION: '$HOME_REGION'\n" # # UseAPI "SearchResources" "$HOME_REGION" "" "$scratchfile" "user" # stat=$? # if [ $stat -eq 0 ]; then # cat $scratchfile # else # printf "\nError searching root compartment: '$stat'\n" # fi # # UseAPI "SearchResources" "$HOME_REGION" "ocid1.compartment.oc1..aaaaaaaamdtmyakblsneavmja2iecil443rg47r2ol5npze3db65pccm5iaa" "$scratchfile" "user" # stat=$? # if [ $stat -eq 0 ]; then # cat $scratchfile # else # printf "\nError searching georgs compartment: '$stat'\n" # fi # If compartment id was specified, check if it exists and only search in this compartment if [ "$compartment_id" != "" ]; then if [ "$formatstr" = "table" ]; then result=`grep "^${compartment_id} ACTIVE" "${configdir}/${toolsdir}/${listsdir}/$compfile"` if [ "$result" = "" ]; then printf "\n" errormsg 0 "Selected comaprtment '$compartment_id' not found. Searching all compartments." printf "\n" compartment_id="" else result=`echo "$result" | cut -d$'\t' -f3` printf "\nSelected compartment: %s\n\n" "${result}" fi fi else # Display non regional resources DisplayResources fi # Display all regional resources in all regions or selected region if [ -r "${scratchfile}.regn" ]; then # ${scratchfile}.regn: "regionName\tstatus\tisHomeRegion\tregionKey\trealmKey\tavds\tdescription\n" while IFS=$'\t' read -r regname regstat home key rkey avds description; do if [ "$regname" != "" -a "$regstat" = "READY" ]; then DisplayResources "$regname" "$compartment_id" fi done < <(cat ${scratchfile}.regn | tailfromline2) fi if [ "$formatstr" = "table" ]; then printf '****** No more resource types to display. Scan completed. ******\n' | print-header $phopt printf "$bell" >>/dev/stderr fi fi fi fi fi # Cleanup and exit Cleanup exit $exitcode