github.com/verrazzano/verrazzano@v1.7.1/platform-operator/scripts/install/k8s-dump-objects.sh (about) 1 #!/usr/bin/env bash 2 # 3 # Copyright (c) 2020, 2023, Oracle and/or its affiliates. 4 # Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. 5 # 6 SCRIPT_DIR=$(cd $(dirname "$0"); pwd -P) 7 8 export DIAGNOSTIC_LOG="${DIAGNOSTIC_LOG:-${SCRIPT_DIR}/build/logs/diagnostics.log}" 9 export LOG_FILE="${DIAGNOSTIC_LOG}" 10 . ${SCRIPT_DIR}/logging.sh 11 12 13 # Dump Diagnostic header with message 14 # $1 message - message given by failure to identify cause 15 # Usage: 16 # dump_header "message" 17 function dump_header() { 18 local message=$1 19 20 if [ -z "$message" ] ; then 21 log "================================ DIAGNOSTIC OUTPUT START =================================" 22 log "" 23 else 24 log "================================ DIAGNOSTIC OUTPUT START: ${message} =================================" 25 log "" 26 fi 27 } 28 29 # Dump Diagnostic footer 30 # Usage: 31 # dump_footer 32 function dump_footer() { 33 log "" 34 log "================================ DIAGNOSTIC OUTPUT END ===================================" 35 } 36 37 # Dump specified objects based on described requirements 38 # $1 command - command type specified 39 # $2 object type - i.e. namespaces, pods, jobs 40 # $3 namespace - namespace of the objects 41 # $4 object name regex - regex to retrieve certain jobs by name 42 # $5 (optional) fields - field selectors for kubectl organized as shown here: https://kubernetes.io/docs/concepts/overview/working-with-objects/field-selectors/ 43 # $6 (optional) message - dump header message to inform the cause of the output 44 # $7 (optional) container - container in which the logs should be retrieved 45 # Usage: 46 # dump_objects "command" "objectType" "namespace" "objectRegex" "fields" "message" "container" 47 function dump_objects() { 48 local command=$1 49 local type=$2 50 local namespace=$3 51 local regex=$4 52 local fields=$5 53 local message=$6 54 local container=$7 55 56 if [[ -z "$type" || -z "$namespace" ]] ; then 57 error "Object type and namespace must be specified to describe objects." 58 exit 1 59 fi 60 61 local object_names=($(kubectl get "${type}" --no-headers -o custom-columns=":metadata.name" --field-selector="${fields}" -n "${namespace}"| grep -E "${regex}")) 62 63 dump_header "$message" 64 65 if [ -z "$object_names" ] ; then 66 log "No resources of object type: \"${type}\" in namespace: \"${namespace}\" with the current specifications were located" 67 fi 68 69 for object in "${object_names[@]}" 70 do 71 log "" 72 log "========================================================" 73 log "Command: ${command}, type: ${type}, name: ${object}" 74 log "========================================================" 75 if [ "$command" == "describe" ] ; then 76 kubectl "${command}" "${type}" "${object}" -n "${namespace}" 77 elif [ "$command" == "logs" ]; then 78 if [ -z "$container" ] ; then 79 kubectl "${command}" "${object}" -n "${namespace}" 80 else 81 kubectl "${command}" "${object}" -n "${namespace}" -c "${container}" 82 fi 83 elif [ "$command" == "previousLogs" ]; then 84 if [ -z "$container" ] ; then 85 kubectl "logs" "-p" "${object}" -n "${namespace}" 86 else 87 kubectl "logs" "-p" "${object}" -n "${namespace}" -c "${container}" 88 fi 89 fi 90 done 91 92 dump_footer 93 } 94 95 # format the field selectors for a given array 96 # $1 selector - kubernetes selector: metadata.name, metadata.namespace, status.phase 97 # $2 eq - "=" or "!=" 98 # $3 state - state of the object 99 # Usage: 100 # format_field_selectors "selector" "=" "status" 101 function format_field_selectors() { 102 states=() 103 for state in "${@:3}" 104 do 105 formatted_state="$(tr '[:lower:]' '[:upper:]' <<< ${state:0:1})$(tr '[:upper:]' '[:lower:]' <<< ${state:1})" 106 states+=("${1}${2}${formatted_state}") 107 done 108 109 echo $(join_by , "${states[@]}") 110 } 111 112 113 # join an array with a specified value 114 # $1 join - value to join by 115 # $2 values - values in which to join 116 # Usage: 117 # join_by , "${ARRAY[@]}" 118 function join_by() { 119 local IFS="$1" 120 shift 121 echo "$*" 122 } 123 124 # prints usage message for this script to consoleerr 125 # Usage: 126 # usage 127 function usage { 128 error 129 error "usage: $0 -o object_type -n namespace -m message [-r name_regex] [-s state] [-S not_state] [-l] [-p] [-c container] [-h]" 130 error " -o object_type Type of the object (i.e. namespaces, pods, jobs, etc)" 131 error " -n namespace Namespace of the given object type" 132 error " -r name_regex Regex to retrieve certain objects by name (Optional)" 133 error " -s state Specified state the described object should be in (i.e. Running) (Multiple values allowed) (Optional)" 134 error " -S not_state Specified state that the described object should not be in (Multiple values allowed) (Optional)" 135 error " -m message Message for the diagnostic header to inform on cause of output" 136 error " -l Retrieve logs for specified object" 137 error " -p Retrieve previous logs for specified object" 138 error " -c container Container in which to pull logs from" 139 error " -h Help" 140 error 141 exit 1 142 } 143 144 NAMESPACE="default" 145 NAME_REGEX="" 146 STATES=() 147 NOT_STATES=() 148 MESSAGE="" 149 COMMAND="describe" 150 while getopts o:n:r:s:S:m:lpc:h flag 151 do 152 case "${flag}" in 153 o) OBJECT_TYPE=${OPTARG};; 154 n) NAMESPACE=${OPTARG};; 155 r) NAME_REGEX=${OPTARG};; 156 s) STATES+=("${OPTARG}");; 157 S) NOT_STATES+=("${OPTARG}");; 158 m) MESSAGE=${OPTARG};; 159 l) COMMAND="logs";; 160 p) COMMAND="previousLogs";; 161 c) CONTAINER="${OPTARG}";; 162 h) usage;; 163 *) usage;; 164 esac 165 done 166 shift $((OPTIND -1)) 167 168 STATE_FORMAT=$(format_field_selectors "status.phase" "=" "${STATES[@]}") 169 NOT_STATE_FORMAT=$(format_field_selectors "status.phase" "!=" "${NOT_STATES[@]}") 170 FIELD_SELECTORS="${STATE_FORMAT},${NOT_STATE_FORMAT}" 171 172 dump_objects "${COMMAND}" "${OBJECT_TYPE}" "${NAMESPACE}" "${NAME_REGEX}" "${FIELD_SELECTORS}" "${MESSAGE}" "${CONTAINER}"