podman

Форк
0
/
podman-registry 
282 строки · 8.6 Кб
1
#! /bin/bash
2
#
3
# podman-registry - start/stop/monitor a local instance of registry:2
4
#
5
ME=$(basename $0)
6

7
###############################################################################
8
# BEGIN defaults
9

10
PODMAN_REGISTRY_IMAGE=quay.io/libpod/registry:2.8
11

12
PODMAN_REGISTRY_USER=
13
PODMAN_REGISTRY_PASS=
14
PODMAN_REGISTRY_PORT=
15

16
# Podman binary to run
17
PODMAN=${PODMAN:-$(dirname $0)/../bin/podman}
18

19
# END   defaults
20
###############################################################################
21
# BEGIN help messages
22

23
missing=" argument is missing; see $ME -h for details"
24
usage="Usage: $ME [options] [start|stop|ps|logs]
25

26
$ME manages a local instance of a container registry.
27

28
When called to start a registry, $ME will pull an image
29
into a local temporary directory, create an htpasswd, start the
30
registry, and dump a series of environment variables to stdout:
31

32
    \$ $ME start
33
    PODMAN_REGISTRY_IMAGE=\"docker.io/library/registry:2.8\"
34
    PODMAN_REGISTRY_PORT=\"5050\"
35
    PODMAN_REGISTRY_USER=\"userZ3RZ\"
36
    PODMAN_REGISTRY_PASS=\"T8JVJzKrcl4p6uT\"
37

38
Expected usage, therefore, is something like this in a script
39

40
    eval \$($ME start)
41

42
To stop the registry, you will need to know the port number:
43

44
    $ME -P \$PODMAN_REGISTRY_PORT stop
45

46
Override the default image, port, user, password with:
47

48
  -i IMAGE      registry image to pull (default: $PODMAN_REGISTRY_IMAGE)
49
  -u USER       registry user (default: random)
50
  -p PASS       password for registry user (default: random)
51
  -P PORT       port to bind to (on 127.0.0.1) (default: random, 5000-5999)
52

53
Other options:
54

55
  -h            display usage message
56
"
57

58
die () {
59
    echo "$ME: $*" >&2
60
    exit 1
61
}
62

63
# END   help messages
64
###############################################################################
65
# BEGIN option processing
66

67
while getopts "i:u:p:P:hv" opt; do
68
    case "$opt" in
69
        i)         PODMAN_REGISTRY_IMAGE=$OPTARG ;;
70
        u)         PODMAN_REGISTRY_USER=$OPTARG  ;;
71
        p)         PODMAN_REGISTRY_PASS=$OPTARG  ;;
72
        P)         PODMAN_REGISTRY_PORT=$OPTARG  ;;
73
        h)         echo "$usage"; exit 0;;
74
        v)         verbose=1 ;;
75
        \?)        echo "Run '$ME -h' for help" >&2; exit 1;;
76
    esac
77
done
78
shift $((OPTIND-1))
79

80
# END   option processing
81
###############################################################################
82
# BEGIN helper functions
83

84
function random_string() {
85
    local length=${1:-10}
86

87
    head /dev/urandom | tr -dc a-zA-Z0-9 | head -c$length
88
}
89

90
function podman() {
91
    if [ -z "${PODMAN_REGISTRY_PORT}" ]; then
92
        die "podman port undefined; please invoke me with -P PORT"
93
    fi
94

95
    if [ -z "${PODMAN_REGISTRY_WORKDIR}" ]; then
96
        PODMAN_REGISTRY_WORKDIR=${TMPDIR:-/tmp}/podman-registry-${PODMAN_REGISTRY_PORT}
97
        if [ ! -d ${PODMAN_REGISTRY_WORKDIR} ]; then
98
            die "$ME: directory does not exist: ${PODMAN_REGISTRY_WORKDIR}"
99
        fi
100
    fi
101

102
    # Reset $PODMAN, so ps/logs/stop use same args as the initial start
103
    PODMAN="$(<${PODMAN_REGISTRY_WORKDIR}/PODMAN)"
104

105
    ${PODMAN} --root    ${PODMAN_REGISTRY_WORKDIR}/root        \
106
              --runroot ${PODMAN_REGISTRY_WORKDIR}/runroot     \
107
              "$@"
108
}
109

110
###############
111
#  must_pass  #  Run a command quietly; abort with error on failure
112
###############
113
function must_pass() {
114
    local log=${PODMAN_REGISTRY_WORKDIR}/log
115

116
    "$@" &> $log
117
    if [ $? -ne 0 ]; then
118
        echo "$ME: Command failed: $*" >&2
119
        cat $log                       >&2
120

121
        # If we ever get here, it's a given that the registry is not running.
122
        # Clean up after ourselves.
123
        ${PODMAN} unshare rm -rf ${PODMAN_REGISTRY_WORKDIR}
124
        exit 1
125
    fi
126
}
127

128
###################
129
#  wait_for_port  #  Returns once port is available on localhost
130
###################
131
function wait_for_port() {
132
    local port=$1                      # Numeric port
133

134
    local host=127.0.0.1
135
    local _timeout=5
136

137
    # Wait
138
    while [ $_timeout -gt 0 ]; do
139
        { exec {unused_fd}<> /dev/tcp/$host/$port; } &>/dev/null && return
140
        sleep 1
141
        _timeout=$(( $_timeout - 1 ))
142
    done
143

144
    die "Timed out waiting for port $port"
145
}
146

147
# END   helper functions
148
###############################################################################
149
# BEGIN action processing
150

151
function do_start() {
152
    # If called without a port, assign a random one in the 5xxx range
153
    if [ -z "${PODMAN_REGISTRY_PORT}" ]; then
154
        for port in $(shuf -i 5000-5999);do
155
            if ! { exec {unused_fd}<> /dev/tcp/127.0.0.1/$port; } &>/dev/null; then
156
                PODMAN_REGISTRY_PORT=$port
157
                break
158
            fi
159
        done
160
    fi
161

162
    PODMAN_REGISTRY_WORKDIR=${TMPDIR:-/tmp}/podman-registry-${PODMAN_REGISTRY_PORT}
163
    if [ -d ${PODMAN_REGISTRY_WORKDIR} ]; then
164
        die "$ME: directory exists: ${PODMAN_REGISTRY_WORKDIR} (another registry might already be running on this port)"
165
    fi
166

167
    # Randomly-generated username and password, if none given on command line
168
    if [ -z "${PODMAN_REGISTRY_USER}" ]; then
169
        PODMAN_REGISTRY_USER="user$(random_string 4)"
170
    fi
171
    if [ -z "${PODMAN_REGISTRY_PASS}" ]; then
172
        PODMAN_REGISTRY_PASS=$(random_string 15)
173
    fi
174

175
    # For the next few commands, die on any error
176
    set -e
177

178
    mkdir -p ${PODMAN_REGISTRY_WORKDIR}
179

180
    # Preserve initial podman path & args, so all subsequent invocations
181
    # of this script are consistent with the first one.
182
    echo "$PODMAN" >${PODMAN_REGISTRY_WORKDIR}/PODMAN
183

184
    local AUTHDIR=${PODMAN_REGISTRY_WORKDIR}/auth
185
    mkdir -p $AUTHDIR
186

187
    # Pull registry image, but into a separate container storage
188
    mkdir -p ${PODMAN_REGISTRY_WORKDIR}/root
189
    mkdir -p ${PODMAN_REGISTRY_WORKDIR}/runroot
190

191
    set +e
192

193
    # Give it three tries, to compensate for flakes
194
    podman pull ${PODMAN_REGISTRY_IMAGE}      &>/dev/null ||
195
        podman pull ${PODMAN_REGISTRY_IMAGE}  &>/dev/null ||
196
        must_pass podman pull ${PODMAN_REGISTRY_IMAGE}
197

198
    # Registry image needs a cert. Self-signed is good enough.
199
    local CERT=$AUTHDIR/domain.crt
200
    must_pass openssl req -newkey rsa:4096 -nodes -sha256              \
201
              -keyout ${AUTHDIR}/domain.key -x509 -days 2              \
202
              -out ${AUTHDIR}/domain.crt                               \
203
              -subj "/C=US/ST=Foo/L=Bar/O=Red Hat, Inc./CN=localhost"
204

205
    # Store credentials where container will see them. We can't run
206
    # this one via must_pass because we need its stdout.
207
    htpasswd -Bbn ${PODMAN_REGISTRY_USER} ${PODMAN_REGISTRY_PASS}   \
208
           > $AUTHDIR/htpasswd
209
    if [ $? -ne 0 ]; then
210
        rm -rf ${PODMAN_REGISTRY_WORKDIR}
211
        die "Command failed: htpasswd"
212
    fi
213

214
    # In case someone needs to debug
215
    echo "${PODMAN_REGISTRY_USER}:${PODMAN_REGISTRY_PASS}" \
216
         > $AUTHDIR/htpasswd-plaintext
217

218
    # Run the registry container.
219
    must_pass podman run --quiet -d                                     \
220
              -p ${PODMAN_REGISTRY_PORT}:5000                           \
221
              --name registry                                           \
222
              -v $AUTHDIR:/auth:Z                                       \
223
              -e "REGISTRY_AUTH=htpasswd"                               \
224
              -e "REGISTRY_AUTH_HTPASSWD_REALM=Registry Realm"          \
225
              -e "REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd"           \
226
              -e "REGISTRY_HTTP_TLS_CERTIFICATE=/auth/domain.crt"       \
227
              -e "REGISTRY_HTTP_TLS_KEY=/auth/domain.key"               \
228
              ${PODMAN_REGISTRY_IMAGE}
229

230
    # Confirm that registry started and port is active
231
    wait_for_port $PODMAN_REGISTRY_PORT
232

233
    # Dump settings. Our caller will use these to access the registry.
234
    for v in IMAGE PORT USER PASS; do
235
        echo "PODMAN_REGISTRY_${v}=\"$(eval echo \$PODMAN_REGISTRY_${v})\""
236
    done
237
}
238

239

240
function do_stop() {
241
    podman stop registry
242
    podman rm -f registry
243

244
    # Use straight podman, not our alias function, to avoid 'overlay: EBUSY'
245
    cmd="rm -rf ${PODMAN_REGISTRY_WORKDIR}"
246
    if [[ $(id -u) -eq 0 ]]; then
247
        $cmd
248
    else
249
        ${PODMAN} unshare $cmd
250
    fi
251
}
252

253

254
function do_ps() {
255
    podman ps -a
256
}
257

258

259
function do_logs() {
260
    podman logs registry
261
}
262

263
# END   action processing
264
###############################################################################
265
# BEGIN command-line processing
266

267
# First command-line arg must be an action
268
action=${1?ACTION$missing}
269
shift
270

271
case "$action" in
272
    start)  do_start  ;;
273
    stop)   do_stop   ;;
274
    ps)     do_ps     ;;
275
    logs)   do_logs   ;;
276
    *)      die "Unknown action '$action'; must be start / stop / ps / logs" ;;
277
esac
278

279
# END   command-line processing
280
###############################################################################
281

282
exit 0
283

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.