|
| 1 | +#!/bin/bash |
| 2 | +# Copyright 2018, Oracle Corporation and/or its affiliates. All rights reserved. |
| 3 | +# Licensed under the Universal Permissive License v 1.0 as shown at http://oss.oracle.com/licenses/upl. |
| 4 | +# |
| 5 | +# Description: |
| 6 | +# Use this script to delete all kubernetes resources associated |
| 7 | +# with a set of given domains. Alternatively, run the script |
| 8 | +# in a test mode to show what would be deleted without actually |
| 9 | +# performing the deletes. |
| 10 | +# |
| 11 | +# Usage: |
| 12 | +# See "function usage" below or call this script with no parameters. |
| 13 | +# |
| 14 | + |
| 15 | +function usage { |
| 16 | +cat << EOF |
| 17 | + Usage: |
| 18 | +
|
| 19 | + $(basename $0) -d domain-uid,domain-uid,... [-s max-seconds] [-t] |
| 20 | + $(basename $0) -d all [-s max-seconds] [-t] |
| 21 | + $(basename $0) -h |
| 22 | +
|
| 23 | + Perform a best-effort delete of the kubernetes resources for |
| 24 | + the given domain(s), and retry until either max-seconds is reached |
| 25 | + or all resources were deleted (default $default_maxwaitsecs seconds). |
| 26 | +
|
| 27 | + The domains can be specified as a comma-separated list of |
| 28 | + domain-uids (no spaces), or the keyword 'all'. The domains can be |
| 29 | + located in any kubernetes namespace. |
| 30 | +
|
| 31 | + Specify '-t' to run the script in a test mode which will |
| 32 | + show kubernetes commands but not actually perform them. |
| 33 | +
|
| 34 | + The script runs in three phases: |
| 35 | +
|
| 36 | + Phase 1: Set the startupControl of each domain to NONE if |
| 37 | + it's not already NONE. This should cause each |
| 38 | + domain's operator to initiate a controlled shutdown |
| 39 | + of the domain. Immediately proceed to phase 2. |
| 40 | +
|
| 41 | + Phase 2: Wait up to half of max-seconds for WebLogic |
| 42 | + Server pods to exit normally, and then proceed |
| 43 | + to phase 3. |
| 44 | +
|
| 45 | + Phase 3: Periodically delete all remaining kubernetes resources |
| 46 | + for the specified domains, including any pods |
| 47 | + leftover from phase 2. Exit and fail if max-seconds |
| 48 | + is exceeded and there are any leftover kubernetes |
| 49 | + resources. |
| 50 | +
|
| 51 | + This script exits with a zero status on success, and a |
| 52 | + non-zero status on failure. |
| 53 | +EOF |
| 54 | +} |
| 55 | + |
| 56 | + |
| 57 | +# |
| 58 | +# getDomainResources domain(s) outfilename |
| 59 | +# |
| 60 | +# Usage: |
| 61 | +# getDomainResources domainA,domainB,... outfilename |
| 62 | +# getDomainResources all outfilename |
| 63 | +# |
| 64 | +# Internal helper function |
| 65 | +# |
| 66 | +# File output is all domain related resources for the given domain uids, one per line, |
| 67 | +# in the form: 'kind name [-n namespace]'. For example: |
| 68 | +# PersistentVolumeClaim domain1-pv-claim -n default |
| 69 | +# PersistentVolume domain1-pv |
| 70 | +# |
| 71 | +function getDomainResources { |
| 72 | + if [ "$1" = "all" ]; then |
| 73 | + local label_selector="weblogic.domainUID" |
| 74 | + else |
| 75 | + local label_selector="weblogic.domainUID in ($1)" |
| 76 | + fi |
| 77 | + |
| 78 | + # first, let's get all namespaced types with -l $label_selector |
| 79 | + |
| 80 | + local namespaced_types="pod,job,deploy,rs,service,pvc,ingress,cm,serviceaccount,role,rolebinding,secret" |
| 81 | + |
| 82 | + # if domain crd exists, look for domains too: |
| 83 | + kubectl get crd domains.weblogic.oracle > /dev/null 2>&1 |
| 84 | + if [ $? -eq 0 ]; then |
| 85 | + namespaced_types="domain,$namespaced_types" |
| 86 | + fi |
| 87 | + |
| 88 | + kubectl get $namespaced_types \ |
| 89 | + -l "$label_selector" \ |
| 90 | + -o=jsonpath='{range .items[*]}{.kind}{" "}{.metadata.name}{" -n "}{.metadata.namespace}{"\n"}{end}' \ |
| 91 | + --all-namespaces=true > $2 |
| 92 | + |
| 93 | + # now, get all non-namespaced types with -l $label_selector |
| 94 | + |
| 95 | + kubectl get pv,crd,clusterroles,clusterrolebindings \ |
| 96 | + -l "$label_selector" \ |
| 97 | + -o=jsonpath='{range .items[*]}{.kind}{" "}{.metadata.name}{"\n"}{end}' \ |
| 98 | + --all-namespaces=true >> $2 |
| 99 | +} |
| 100 | + |
| 101 | +# |
| 102 | +# deleteDomains domain(s) maxwaitsecs |
| 103 | +# |
| 104 | +# Usage: |
| 105 | +# deleteDomains domainA,domainB,... maxwaitsecs |
| 106 | +# deleteDomains all maxwaitsecs |
| 107 | +# |
| 108 | +# Internal helper function |
| 109 | +# This function first sets the startupControl of each Domain to NONE |
| 110 | +# and waits up to half of $2 for pods to 'self delete'. It then deletes |
| 111 | +# all remaining k8s resources for domain $1 (including any remaining pods) |
| 112 | +# and retries up to $2 seconds. |
| 113 | +# |
| 114 | +# If $1 has special value "all", it deletes all domains in all namespaces. |
| 115 | +# |
| 116 | +# If global $test_mode is true, show candidate actions but don't actually perform them |
| 117 | +# |
| 118 | +function deleteDomains { |
| 119 | + |
| 120 | + if [ "$test_mode" = "true" ]; then |
| 121 | + echo @@ Test mode! Displaying commands for deleting kubernetes resources with label weblogic.domainUID \'$1\' without actually deleting them. |
| 122 | + else |
| 123 | + echo @@ Deleting kubernetes resources with label weblogic.domainUID \'$1\'. |
| 124 | + fi |
| 125 | + |
| 126 | + local maxwaitsecs=${2:-$default_maxwaitsecs} |
| 127 | + local tempfile="/tmp/$(basename $0).tmp.$$" # == /tmp/[script-file-name].tmp.[pid] |
| 128 | + local mstart=`date +%s` |
| 129 | + local phase=1 |
| 130 | + |
| 131 | + while : ; do |
| 132 | + # get all k8s resources with matching domain-uid labels and put them in $tempfile |
| 133 | + getDomainResources $1 $tempfile |
| 134 | + |
| 135 | + # get a count of all k8s resources with matching domain-uid labels |
| 136 | + local allcount=`wc -l $tempfile | awk '{ print $1 }'` |
| 137 | + |
| 138 | + # get a count of all WLS pods (any pod with a matching domain-uid label that doesn't have 'traefik' embedded in its name) |
| 139 | + local podcount=`grep "^Pod" $tempfile | grep -v traefik | wc -l | awk '{ print $1 }'` |
| 140 | + |
| 141 | + local mnow=`date +%s` |
| 142 | + |
| 143 | + echo @@ $allcount resources remaining after $((mnow - mstart)) seconds, including $podcount WebLogic Server pods. Max wait is $maxwaitsecs seconds. |
| 144 | + |
| 145 | + # Exit if all k8s resources deleted or max wait seconds exceeded. |
| 146 | + |
| 147 | + if [ $allcount -eq 0 ]; then |
| 148 | + echo @@ Success. |
| 149 | + rm -f $tempfile |
| 150 | + exit 0 |
| 151 | + elif [ $((mnow - mstart)) -gt $maxwaitsecs ]; then |
| 152 | + echo @@ Error! Max wait of $maxwaitsecs seconds exceeded with $allcount resources remaining, including $podcount WebLogic Server pods. Giving up. Remaining resources: |
| 153 | + cat $tempfile |
| 154 | + rm -f $tempfile |
| 155 | + exit $allcount |
| 156 | + fi |
| 157 | + |
| 158 | + # In phase 1, set the startupControl of each domain to NONE and then immediately |
| 159 | + # proceed to phase 2. If there are no domains or WLS pods, we also immediately go to phase 2. |
| 160 | + |
| 161 | + if [ $phase -eq 1 -a $podcount -gt 0 ]; then |
| 162 | + echo @@ "Setting startupControl to NONE on each domain (this should cause operator(s) to initiate a controlled shutdown of the domain's pods.)" |
| 163 | + cat $tempfile | grep "^Domain" | while read line; do |
| 164 | + local name="`echo $line | awk '{ print $2 }'`" |
| 165 | + local namespace="`echo $line | awk '{ print $4 }'`" |
| 166 | + if [ "$test_mode" = "true" ]; then |
| 167 | + echo "kubectl patch domain $name -n $namespace -p '{\"spec\":{\"startupControl\":\"NONE\"}}' --type merge" |
| 168 | + else |
| 169 | + kubectl patch domain $name -n $namespace -p '{"spec":{"startupControl":"NONE"}}' --type merge |
| 170 | + fi |
| 171 | + done |
| 172 | + fi |
| 173 | + phase=2 |
| 174 | + |
| 175 | + # In phase 2, wait for the WLS pod count to go down to 0 for at most half |
| 176 | + # of 'maxwaitsecs'. Otherwise proceed immediately to phase 3. |
| 177 | + |
| 178 | + if [ $phase -eq 2 ]; then |
| 179 | + if [ $podcount -eq 0 ]; then |
| 180 | + echo @@ All pods shutdown, about to directly delete remaining resources. |
| 181 | + elif [ $((mnow - mstart)) -gt $((maxwaitsecs / 2)) ]; then |
| 182 | + echo @@ Warning! $podcount WebLogic Server pods remaining but wait time exceeds half of max wait seconds. About to directly delete all remaining resources, including the leftover pods. |
| 183 | + else |
| 184 | + echo @@ "Waiting for operator to shutdown pods (will wait for no more than half of max wait seconds before directly deleting them)." |
| 185 | + sleep 3 |
| 186 | + continue |
| 187 | + fi |
| 188 | + fi |
| 189 | + phase=3 |
| 190 | + |
| 191 | + # In phase 3, directly delete all k8s resources for the given domainUids |
| 192 | + # (including any leftover WLS pods from phases 1 & 2). |
| 193 | + |
| 194 | + cat $tempfile | while read line; do |
| 195 | + if [ "$test_mode" = "true" ]; then |
| 196 | + echo kubectl delete $line --ignore-not-found |
| 197 | + else |
| 198 | + kubectl delete $line --ignore-not-found |
| 199 | + fi |
| 200 | + done |
| 201 | + sleep 3 |
| 202 | + done |
| 203 | +} |
| 204 | + |
| 205 | +# main entry point |
| 206 | + |
| 207 | +# default when to stop retrying (override via command line) |
| 208 | +default_maxwaitsecs=120 |
| 209 | + |
| 210 | +# optional test mode that lists what would be deleted without |
| 211 | +# actually deleting (override via command line) |
| 212 | +test_mode=false |
| 213 | + |
| 214 | +domains="" |
| 215 | + |
| 216 | +# parse command line options |
| 217 | +while getopts ":d:s:th" opt; do |
| 218 | + case $opt in |
| 219 | + d) domains="${OPTARG}" |
| 220 | + ;; |
| 221 | + |
| 222 | + s) maxwaitsecs="${OPTARG}" |
| 223 | + ;; |
| 224 | + |
| 225 | + t) test_mode="true" |
| 226 | + ;; |
| 227 | + |
| 228 | + h) usage |
| 229 | + exit 0 |
| 230 | + ;; |
| 231 | + |
| 232 | + *) usage |
| 233 | + exit 9999 |
| 234 | + ;; |
| 235 | + esac |
| 236 | +done |
| 237 | + |
| 238 | +if [ "$domains" = "" ]; then |
| 239 | + usage |
| 240 | + exit 9999 |
| 241 | +fi |
| 242 | + |
| 243 | +if [ ! -x "$(command -v kubectl)" ]; then |
| 244 | + echo "@@ Error! kubectl is not installed." |
| 245 | + exit 9999 |
| 246 | +fi |
| 247 | + |
| 248 | +deleteDomains "${domains}" "${maxwaitsecs:-$default_maxwaitsecs}" |
0 commit comments