-
Notifications
You must be signed in to change notification settings - Fork 79
/
rhcos-toolbox
executable file
·223 lines (195 loc) · 6.98 KB
/
rhcos-toolbox
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
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
#!/bin/bash
set -eo pipefail
trap cleanup EXIT
# Defaults
REGISTRY=registry.redhat.io
IMAGE=rhel8/support-tools
AUTHFILE=/var/lib/kubelet/config.json
TOOLBOX_NAME=toolbox-"$(whoami)"
TOOLBOXRC="${HOME}"/.toolboxrc
setup() {
# Allow user overrides
if [ -f "${TOOLBOXRC}" ]; then
echo ".toolboxrc file detected, overriding defaults..."
source "${TOOLBOXRC}"
fi
TOOLBOX_IMAGE="${REGISTRY}"/"${IMAGE}"
}
run() {
if ! image_exists; then
image_pull
if container_exists; then
sudo podman rm "${TOOLBOX_NAME}"
fi
elif ! image_fresh; then
read -r -p "There is a newer version of ${TOOLBOX_IMAGE} available. Would you like to pull it? [y/N] "
if [[ ${REPLY} =~ ^([Yy][Ee][Ss]|[Yy])+$ ]]; then
image_pull
if container_exists; then
sudo podman rm "${TOOLBOX_NAME}"
fi
else
echo "Skipping retrieval of new image.."
fi
fi
local runlabel=$(image_runlabel)
if ! container_exists; then
echo "Spawning a container '${TOOLBOX_NAME}' with image '${TOOLBOX_IMAGE}'"
if [[ -z "${runlabel}" ]] || [[ "${runlabel}" == "<no value>" ]]; then
container_create
else
echo "Detected RUN label in the container image. Using that as the default..."
container_create_runlabel
fi
else
echo "Container '${TOOLBOX_NAME}' already exists. Trying to start..."
echo "(To remove the container and start with a fresh toolbox, run: sudo podman rm '${TOOLBOX_NAME}')"
fi
local state=$(container_state)
if [[ "${state}" == configured ]] || [[ "${state}" == created ]] || [[ "${state}" == exited ]] || [[ "${state}" == stopped ]]; then
container_start
elif [[ "${state}" != running ]]; then
echo "Container '${TOOLBOX_NAME}' in unknown state: '$state'"
return 1
fi
if [[ "$#" -eq "0" ]]; then
echo "Container started successfully. To exit, type 'exit'."
fi
container_exec "$@"
}
cleanup() {
sudo podman stop "${TOOLBOX_NAME}" &>/dev/null
}
container_exists() {
sudo podman container inspect "${TOOLBOX_NAME}" &>/dev/null
}
container_state() {
sudo podman container inspect "${TOOLBOX_NAME}" --format '{{.State.Status}}'
}
image_exists() {
sudo podman image inspect "${TOOLBOX_IMAGE}" &>/dev/null
}
# returns 0 if the image on disk is "fresh", i.e. no newer image on remote
# registry. (or if we couldn't inspect the registry successfully)
image_fresh() {
echo "Checking if there is a newer version of ${TOOLBOX_IMAGE} available..."
local_date=$(sudo podman image inspect "${TOOLBOX_IMAGE}" --format '{{.Created}}')
if ! remote_date=$(sudo skopeo inspect --authfile "${AUTHFILE}" docker://"${TOOLBOX_IMAGE}" --format '{{.Created}}'); then
echo "Error inspecting ${TOOLBOX_IMAGE} via skopeo"
return
fi
# if the date on the registry is *NOT* newer than the local image date
# then we return 1. (doing a less-than comparison of the strings always
# fails if they are the same, hence the weird conditional here)
! [[ "${remote_date}" > "${local_date}" ]]
}
image_runlabel() {
sudo podman image inspect "${TOOLBOX_IMAGE}" --format '{{- if index .Labels "run" -}}{{.Labels.run}}{{- end -}}'
}
image_pull() {
if ! sudo --preserve-env podman pull --authfile "${AUTHFILE}" "${TOOLBOX_IMAGE}"; then
read -r -p "Would you like to manually authenticate to registry: '${REGISTRY}' and try again? [y/N] "
if [[ ${REPLY} =~ ^([Yy][Ee][Ss]|[Yy])+$ ]]; then
sudo --preserve-env podman login --authfile "${AUTHFILE}" "${REGISTRY}"
sudo --preserve-env podman pull --authfile "${AUTHFILE}" "${TOOLBOX_IMAGE}"
else
echo "Exiting..."
exit 1
fi
fi
}
container_create() {
if ! sudo podman create \
--hostname toolbox \
--name "${TOOLBOX_NAME}" \
--privileged \
--net=host \
--pid=host \
--ipc=host \
--tty \
--interactive \
-e HOST=/host \
-e NAME="${TOOLBOX_NAME}" \
-e IMAGE="${IMAGE}" \
--security-opt label=disable \
--volume /run:/run \
--volume /var/log:/var/log \
--volume /etc/machine-id:/etc/machine-id \
--volume /etc/localtime:/etc/localtime \
--volume /:/host \
"${TOOLBOX_IMAGE}" 2>&1; then
echo "$0: failed to create container '${TOOLBOX_NAME}'"
exit 1
fi
}
container_start() {
if ! sudo podman start "${TOOLBOX_NAME}" 2>&1; then
echo "$0: failed to start container '${TOOLBOX_NAME}'"
exit 1
fi
}
container_create_runlabel() {
# Variable replacement logic reproduced from:
# https://github.com/containers/podman/blob/29d7ab3f82e38c442e449739e218349b9a4a16ea/pkg/domain/infra/abi/containers_runlabel.go#L226
local pod
pod="$(echo "${runlabel}" \
| sed 's/podman run/sudo podman create/' \
| sed 's/--name NAME/--name ${TOOLBOX_NAME}/' \
| sed 's/NAME=NAME/NAME=${TOOLBOX_NAME}/' \
| sed 's/IMAGE=IMAGE/IMAGE=${TOOLBOX_IMAGE}/' \
| sed 's/host IMAGE/host ${TOOLBOX_IMAGE}/')"
if ! eval "${pod}" ; then
echo "$0: failed to create container from runlabel '${TOOLBOX_NAME}'"
exit 1
fi
}
container_exec() {
if [[ "$#" -eq 0 ]]; then
cmd=$(sudo podman image inspect "${TOOLBOX_IMAGE}" | jq -re ".[].Config.Cmd[0]") || cmd="/bin/sh"
sudo podman exec \
--env LANG="${LANG}" \
--env TERM="${TERM}" \
--tty \
--interactive \
"${TOOLBOX_NAME}" \
"${cmd}"
else
sudo podman exec \
--env LANG="${LANG}" \
--env TERM="${TERM}" \
--tty \
--interactive \
"${TOOLBOX_NAME}" \
"$@"
fi
}
show_help() {
echo "USAGE: toolbox [-h/--help] [command]
toolbox is a small script that launches a container to let you bring in your favorite debugging or admin tools.
The toolbox container is a pet container and will be restarted on following runs.
To remove the container and start fresh, do sudo podman rm ${TOOLBOX_NAME}.
Options:
-h/--help: Shows this help message
You may override the following variables by setting them in ${TOOLBOXRC}:
- REGISTRY: The registry to pull from. Default: ${REGISTRY}
- IMAGE: The image and tag from the registry to pull. Default: ${IMAGE}
- TOOLBOX_NAME: The name to use for the local container. Default: ${TOOLBOX_NAME}
- AUTHFILE: The location where your registry credentials are stored. Default: ${AUTHFILE}
Example toolboxrc:
REGISTRY=my.special.registry.example.com
IMAGE=debug:latest
TOOLBOX_NAME=special-debug-container
AUTHFILE=/home/core/.docker/config.json"
}
main() {
# Execute setup first so we get proper variables
setup
# If we are passed a help switch, show help and exit
if [[ "$1" =~ ^(--help|-h)$ ]]; then
show_help
exit 0
fi
run "$@"
cleanup
}
main "$@"