github.com/hanks177/podman/v4@v4.1.3-0.20220613032544-16d90015bc83/hack/podman-registry (about)

     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.6
    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 --help 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.6\"
    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      ${PODMAN} --root    ${PODMAN_REGISTRY_WORKDIR}/root        \
   103                --runroot ${PODMAN_REGISTRY_WORKDIR}/runroot     \
   104                "$@"
   105  }
   106  
   107  ###############
   108  #  must_pass  #  Run a command quietly; abort with error on failure
   109  ###############
   110  function must_pass() {
   111      local log=${PODMAN_REGISTRY_WORKDIR}/log
   112  
   113      "$@" &> $log
   114      if [ $? -ne 0 ]; then
   115          echo "$ME: Command failed: $*" >&2
   116          cat $log                       >&2
   117  
   118          # If we ever get here, it's a given that the registry is not running.
   119          # Clean up after ourselves.
   120          ${PODMAN} unshare rm -rf ${PODMAN_REGISTRY_WORKDIR}
   121          exit 1
   122      fi
   123  }
   124  
   125  # END   helper functions
   126  ###############################################################################
   127  # BEGIN action processing
   128  
   129  function do_start() {
   130      # If called without a port, assign a random one in the 5xxx range
   131      if [ -z "${PODMAN_REGISTRY_PORT}" ]; then
   132          for port in $(shuf -i 5000-5999);do
   133              if ! { exec 3<> /dev/tcp/127.0.0.1/$port; } &>/dev/null; then
   134                  PODMAN_REGISTRY_PORT=$port
   135                  break
   136              fi
   137          done
   138      fi
   139  
   140      PODMAN_REGISTRY_WORKDIR=${TMPDIR:-/tmp}/podman-registry-${PODMAN_REGISTRY_PORT}
   141      if [ -d ${PODMAN_REGISTRY_WORKDIR} ]; then
   142          die "$ME: directory exists: ${PODMAN_REGISTRY_WORKDIR} (another registry might already be running on this port)"
   143      fi
   144  
   145      # Randomly-generated username and password, if none given on command line
   146      if [ -z "${PODMAN_REGISTRY_USER}" ]; then
   147          PODMAN_REGISTRY_USER="user$(random_string 4)"
   148      fi
   149      if [ -z "${PODMAN_REGISTRY_PASS}" ]; then
   150          PODMAN_REGISTRY_PASS=$(random_string 15)
   151      fi
   152  
   153      # For the next few commands, die on any error
   154      set -e
   155  
   156      mkdir -p ${PODMAN_REGISTRY_WORKDIR}
   157  
   158      local AUTHDIR=${PODMAN_REGISTRY_WORKDIR}/auth
   159      mkdir -p $AUTHDIR
   160  
   161      # Pull registry image, but into a separate container storage
   162      mkdir -p ${PODMAN_REGISTRY_WORKDIR}/root
   163      mkdir -p ${PODMAN_REGISTRY_WORKDIR}/runroot
   164  
   165      set +e
   166  
   167      # Give it three tries, to compensate for flakes
   168      podman pull ${PODMAN_REGISTRY_IMAGE}      &>/dev/null ||
   169          podman pull ${PODMAN_REGISTRY_IMAGE}  &>/dev/null ||
   170          must_pass podman pull ${PODMAN_REGISTRY_IMAGE}
   171  
   172      # Registry image needs a cert. Self-signed is good enough.
   173      local CERT=$AUTHDIR/domain.crt
   174      must_pass openssl req -newkey rsa:4096 -nodes -sha256              \
   175                -keyout ${AUTHDIR}/domain.key -x509 -days 2              \
   176                -out ${AUTHDIR}/domain.crt                               \
   177                -subj "/C=US/ST=Foo/L=Bar/O=Red Hat, Inc./CN=localhost"
   178  
   179      # Store credentials where container will see them. We can't run
   180      # this one via must_pass because we need its stdout.
   181      podman run --rm                                               \
   182             --entrypoint htpasswd ${PODMAN_REGISTRY_IMAGE}         \
   183             -Bbn ${PODMAN_REGISTRY_USER} ${PODMAN_REGISTRY_PASS}   \
   184             > $AUTHDIR/htpasswd
   185      if [ $? -ne 0 ]; then
   186          rm -rf ${PODMAN_REGISTRY_WORKDIR}
   187          die "Command failed: podman run [htpasswd]"
   188      fi
   189  
   190      # In case someone needs to debug
   191      echo "${PODMAN_REGISTRY_USER}:${PODMAN_REGISTRY_PASS}" \
   192           > $AUTHDIR/htpasswd-plaintext
   193  
   194      # Run the registry container.
   195      must_pass podman run --quiet -d                                     \
   196                -p ${PODMAN_REGISTRY_PORT}:5000                           \
   197                --name registry                                           \
   198                -v $AUTHDIR:/auth:Z                                       \
   199                -e "REGISTRY_AUTH=htpasswd"                               \
   200                -e "REGISTRY_AUTH_HTPASSWD_REALM=Registry Realm"          \
   201                -e "REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd"           \
   202                -e "REGISTRY_HTTP_TLS_CERTIFICATE=/auth/domain.crt"       \
   203                -e "REGISTRY_HTTP_TLS_KEY=/auth/domain.key"               \
   204                registry:2.6
   205  
   206      # Dump settings. Our caller will use these to access the registry.
   207      for v in IMAGE PORT USER PASS; do
   208          echo "PODMAN_REGISTRY_${v}=\"$(eval echo \$PODMAN_REGISTRY_${v})\""
   209      done
   210  }
   211  
   212  
   213  function do_stop() {
   214      podman stop registry
   215      podman rm -f registry
   216  
   217      # Use straight podman, not our alias function, to avoid 'overlay: EBUSY'
   218      ${PODMAN} unshare rm -rf ${PODMAN_REGISTRY_WORKDIR}
   219  }
   220  
   221  
   222  function do_ps() {
   223      podman ps -a
   224  }
   225  
   226  
   227  function do_logs() {
   228      podman logs registry
   229  }
   230  
   231  # END   action processing
   232  ###############################################################################
   233  # BEGIN command-line processing
   234  
   235  # First command-line arg must be an action
   236  action=${1?ACTION$missing}
   237  shift
   238  
   239  case "$action" in
   240      start)  do_start  ;;
   241      stop)   do_stop   ;;
   242      ps)     do_ps     ;;
   243      logs)   do_logs   ;;
   244      *)      die "Unknown action '$action'; must be start / stop / ps / logs" ;;
   245  esac
   246  
   247  # END   command-line processing
   248  ###############################################################################
   249  
   250  exit 0