...
1#!/usr/bin/env bash
2
3# Copyright 2014 The Kubernetes Authors.
4#
5# Licensed under the Apache License, Version 2.0 (the "License");
6# you may not use this file except in compliance with the License.
7# You may obtain a copy of the License at
8#
9# http://www.apache.org/licenses/LICENSE-2.0
10#
11# Unless required by applicable law or agreed to in writing, software
12# distributed under the License is distributed on an "AS IS" BASIS,
13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14# See the License for the specific language governing permissions and
15# limitations under the License.
16
17# Controls verbosity of the script output and logging.
18KUBE_VERBOSE="${KUBE_VERBOSE:-2}"
19
20# Handler for when we exit automatically on an error.
21# Borrowed from https://gist.github.com/ahendrix/7030300
22kube::log::errexit() {
23 local err="${PIPESTATUS[*]}"
24
25 # If the shell we are in doesn't have errexit set (common in subshells) then
26 # don't dump stacks.
27 set +o | grep -qe "-o errexit" || return
28
29 set +o xtrace
30 local code="${1:-1}"
31 # Print out the stack trace described by $function_stack
32 if [ ${#FUNCNAME[@]} -gt 2 ]
33 then
34 kube::log::error "Call tree:"
35 for ((i=1;i<${#FUNCNAME[@]}-1;i++))
36 do
37 kube::log::error " ${i}: ${BASH_SOURCE[${i}+1]}:${BASH_LINENO[${i}]} ${FUNCNAME[${i}]}(...)"
38 done
39 fi
40 kube::log::error_exit "Error in ${BASH_SOURCE[1]}:${BASH_LINENO[0]}. '${BASH_COMMAND}' exited with status ${err}" "${1:-1}" 1
41}
42
43kube::log::install_errexit() {
44 # trap ERR to provide an error handler whenever a command exits nonzero this
45 # is a more verbose version of set -o errexit
46 trap 'kube::log::errexit' ERR
47
48 # setting errtrace allows our ERR trap handler to be propagated to functions,
49 # expansions and subshells
50 set -o errtrace
51}
52
53# Print out the stack trace
54#
55# Args:
56# $1 The number of stack frames to skip when printing.
57kube::log::stack() {
58 local stack_skip=${1:-0}
59 stack_skip=$((stack_skip + 1))
60 if [[ ${#FUNCNAME[@]} -gt ${stack_skip} ]]; then
61 echo "Call stack:" >&2
62 local i
63 for ((i=1 ; i <= ${#FUNCNAME[@]} - stack_skip ; i++))
64 do
65 local frame_no=$((i - 1 + stack_skip))
66 local source_file=${BASH_SOURCE[${frame_no}]}
67 local source_lineno=${BASH_LINENO[$((frame_no - 1))]}
68 local funcname=${FUNCNAME[${frame_no}]}
69 echo " ${i}: ${source_file}:${source_lineno} ${funcname}(...)" >&2
70 done
71 fi
72}
73
74# Log an error and exit.
75# Args:
76# $1 Message to log with the error
77# $2 The error code to return
78# $3 The number of stack frames to skip when printing.
79kube::log::error_exit() {
80 local message="${1:-}"
81 local code="${2:-1}"
82 local stack_skip="${3:-0}"
83 stack_skip=$((stack_skip + 1))
84
85 if [[ ${KUBE_VERBOSE} -ge 4 ]]; then
86 local source_file=${BASH_SOURCE[${stack_skip}]}
87 local source_line=${BASH_LINENO[$((stack_skip - 1))]}
88 echo "!!! Error in ${source_file}:${source_line}" >&2
89 [[ -z ${1-} ]] || {
90 echo " ${1}" >&2
91 }
92
93 kube::log::stack ${stack_skip}
94
95 echo "Exiting with status ${code}" >&2
96 fi
97
98 exit "${code}"
99}
100
101# Log an error but keep going. Don't dump the stack or exit.
102kube::log::error() {
103 timestamp=$(date +"[%m%d %H:%M:%S]")
104 echo "!!! ${timestamp} ${1-}" >&2
105 shift
106 for message; do
107 echo " ${message}" >&2
108 done
109}
110
111# Print an usage message to stderr. The arguments are printed directly.
112kube::log::usage() {
113 echo >&2
114 local message
115 for message; do
116 echo "${message}" >&2
117 done
118 echo >&2
119}
120
121kube::log::usage_from_stdin() {
122 local messages=()
123 while read -r line; do
124 messages+=("${line}")
125 done
126
127 kube::log::usage "${messages[@]}"
128}
129
130# Print out some info that isn't a top level status line
131kube::log::info() {
132 local V="${V:-0}"
133 if (( KUBE_VERBOSE < V )); then
134 return
135 fi
136
137 for message; do
138 echo "${message}"
139 done
140}
141
142# Just like kube::log::info, but no \n, so you can make a progress bar
143kube::log::progress() {
144 for message; do
145 echo -e -n "${message}"
146 done
147}
148
149kube::log::info_from_stdin() {
150 local messages=()
151 while read -r line; do
152 messages+=("${line}")
153 done
154
155 kube::log::info "${messages[@]}"
156}
157
158# Print a status line. Formatted to show up in a stream of output.
159kube::log::status() {
160 local V="${V:-0}"
161 if (( KUBE_VERBOSE < V )); then
162 return
163 fi
164
165 timestamp=$(date +"[%m%d %H:%M:%S]")
166 echo "+++ ${timestamp} ${1}"
167 shift
168 for message; do
169 echo " ${message}"
170 done
171}
View as plain text