~philroche/ubuntu-on-ec2/ec2-publishing-scripts-querydata-arch

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
#!/bin/bash

VERBOSITY=0
TEMP_D=""
TAB=$'\t'
OIFS=$IFS
TAG_NAME="reap-by"
set -f

error() { echo "$@" 1>&2; }
errorp() { printf "$@" 1>&2; }
fail() { [ $# -eq 0 ] || error "$@"; exit 1; }
failp() { [ $# -eq 0 ] || errorp "$@"; exit 1; }

Usage() {
	cat <<EOF
Usage: ${0##*/} [ options ]

   Reap (terminate) instances that have opted in to lifetime control
   by presense of a given tag.

   After launching an instance, tag it with:
      $TAG_NAME=DATE
   where DATE is anything valid for gnu date.  Then, running this
   program will reap instances that have lived past their reap-by

   options:
       --regions     R    operate only in listed regions
                          default (all regions in ec2-list-all-regions)
    -v|--verbose          increase verbosity
       --dry-run          only list what would be done
    -t|--tag         T    name of tag to look for. default: ${TAG_NAME}
EOF
}

bad_Usage() { Usage 1>&2; [ $# -eq 0 ] || error "$@"; exit 1; }
cleanup() {
	local pids
	pids=$(jobs -pr)
	if [ -n "$pids" ]; then
		pids=$(echo $pids)
		error "killing and waiting on child pids: $pids"
		kill -SIGTERM $pids
		wait $pids
	fi
	[ -z "${TEMP_D}" -o ! -d "${TEMP_D}" ] || rm -Rf "${TEMP_D}"
}

debugp() {
	local level=${1}; shift;
	[ "${level}" -gt "${VERBOSITY}" ] && return
	printf "$@" 1>&2;
}
debug() {
	local level=${1}; shift;
	[ "${level}" -gt "${VERBOSITY}" ] && return
	echo "$(date): ${@}" 1>&2
}

short_opts="hmrv"
long_opts="help,dry-run,tag-name:,regions:,verbose"
getopt_out=$(getopt --name "${0##*/}" \
	--options "${short_opts}" --long "${long_opts}" -- "$@") &&
	eval set -- "${getopt_out}" ||
	bad_Usage

## <<insert default variables here>>
regions=( )
max_age=""
dry_run=0
tagname=${TAG_NAME}

while [ $# -ne 0 ]; do
	cur=${1}; next=${2};
	case "$cur" in
		-h|--help) Usage ; exit 0;;
		-r|--regions) regions=( "${regions[@]}" ${next//,/ } ); shift;;
		-v|--verbose) VERBOSITY=$((${VERBOSITY}+1));;
		   --dry-run) dry_run=1;;
		-t|--tag-name) tagname=$next; shift;;
		--) shift; break;;
	esac
	shift;
done

[ $# -eq 0 ] || bad_Usage "unexpected arguments: $*"

TEMP_D=$(mktemp -d "${TMPDIR:-/tmp}/${0##*/}.XXXXXX") ||
   fail "failed to make tempdir"
trap cleanup EXIT

my_start_time=$(date "+%s")

# program starts here
if [ "${#regions[@]}" -eq 0 ]; then
   out=$(ec2-list-all-regions) || fail "failed to get list of regions"
   regions=( $out )
fi

for reg in "${regions[@]}"; do
	debug 2 "describe-tags --region=$reg --filter key=$tagname"
	xc2 describe-tags "--region=$reg" --filter "key=$tagname" \
		> "${TEMP_D}/$reg.tags" &
	pids[${#pids[@]}]=$!
done

for((i=0;i<${#pids[@]};i++)); do
	wait "${pids[$i]}" ||
		fail "describe-instances in $reg failed"
done

# just make sure there are no empty fields (set -- doesn't respect them)
# now instead, a '.' indicates empty
for r in "${regions[@]}"; do
	sed -i -e 's,\t\t,\t.\t,g' -e 's,\t\t,\t.\t,g' "$TEMP_D/$r.tags" ||
		fail "failed to fix empty fields in tags from $r"
done

OFMT="%-16s %-11s %-8s %s\n"

IFS="$TAB"
for reg in "${regions[@]}"; do
	#TAG  i-aa7744cd  instance reap-by  Fri, 27 Apr 2012 13:17:14 -0400
	while read label iid rtype tagname reapdate; do
		[ "$rtype" = "instance" ] || continue
		reap_seconds=$(date "+%s" "--date=${reapdate}") ||
			fail "failed to convert $reapdate to unix seconds"

		if [ "${my_start_time}" -ge "${reap_seconds}" ]; then
			op="kill"
			printf "%s " "$iid " >> "$TEMP_D/$reg.to-kill"
		else
			op="pass"
		fi
		printf "$OFMT" "$reg" "$iid" "$op" "$reapdate" >> "$TEMP_D/$reg.summary"
	done < "$TEMP_D/$reg.tags"
done
IFS="$OIFS"

debugp 1 "$OFMT" "#region" "instance" "action" "reapdate"
for reg in "${regions[@]}"; do
	if [ ! -f "$TEMP_D/$reg.summary" ]; then
		debugp 2 "$OFMT" "$reg" "i-0000000" "" ""
		iids=""
	else
		cat "$TEMP_D/$reg.summary"
		printf "\n" >> "${TEMP_D}/$reg.to-kill" && read iids < "${TEMP_D}/$reg.to-kill" ||
			fail "failed to read iids from file for $reg (iids=$iids)"
	fi
	[ -n "$iids" ] || continue
	[ $dry_run -eq 0 ] || continue
	xc2 terminate-instances $iids >> "${TEMP_D}/term.out" ||
		fail "failed to terminate instances $iids in $region"
done

exit 0
# vi: ts=4 noexpandtab