github.com/palantir/witchcraft-go-server/v2@v2.76.0/godelw (about)

     1  #!/bin/bash
     2  
     3  set -euo pipefail
     4  
     5  # Version and checksums for godel. Values are populated by the godel "dist" task.
     6  VERSION=2.106.0
     7  DARWIN_AMD64_CHECKSUM=65eae013a46a05743ff95a5164d3d9974fd58ad634f30ed7ae147405ce8635e7
     8  DARWIN_ARM64_CHECKSUM=02cb7ddf2ea32402a5441230c60fa5ee7a70f58b93ee2fd76cc965d1486eb9b5
     9  LINUX_AMD64_CHECKSUM=9dbf94144174aa8c9b2e138950652a0697806514be096cf25a7ca3c69ea05847
    10  LINUX_ARM64_CHECKSUM=be7d0f39e0073161c29b1d15a582736fd9e7e56ec0ebaa1b0375e58be7e1a662
    11  
    12  # Downloads file at URL to destination path using wget or curl. Prints an error and exits if wget or curl is not present.
    13  function download {
    14      local url=$1
    15      local dst=$2
    16  
    17      # determine whether wget, curl or both are present
    18      set +e
    19      command -v wget >/dev/null 2>&1
    20      local wget_exists=$?
    21      command -v curl >/dev/null 2>&1
    22      local curl_exists=$?
    23      set -e
    24  
    25      # if one of wget or curl is not present, exit with error
    26      if [ "$wget_exists" -ne 0 -a "$curl_exists" -ne 0 ]; then
    27          echo "wget or curl must be present to download distribution. Install one of these programs and try again or install the distribution manually."
    28          exit 1
    29      fi
    30  
    31      if [ "$wget_exists" -eq 0 ]; then
    32          # attempt download using wget
    33          echo "Downloading $url to $dst..."
    34          local progress_opt=""
    35          if wget --help | grep -q '\--show-progress'; then
    36              progress_opt="-q --show-progress"
    37          fi
    38          set +e
    39          wget -O "$dst" $progress_opt "$url"
    40          rv=$?
    41          set -e
    42          if [ "$rv" -eq 0 ]; then
    43              # success
    44              return
    45          fi
    46  
    47          echo "Download failed using command: wget -O $dst $progress_opt $url"
    48  
    49          # curl does not exist, so nothing more to try: exit
    50          if [ "$curl_exists" -ne 0 ]; then
    51              echo "Download failed using wget and curl was not found. Verify that the distribution URL is correct and try again or install the distribution manually."
    52              exit 1
    53          fi
    54          # curl exists, notify that download will be attempted using curl
    55          echo "Attempting download using curl..."
    56      fi
    57  
    58      # attempt download using curl
    59      echo "Downloading $url to $dst..."
    60      set +e
    61      curl -f -L -o "$dst" "$url"
    62      rv=$?
    63      set -e
    64      if [ "$rv" -ne 0 ]; then
    65          echo "Download failed using command: curl -f -L -o $dst $url"
    66          if [ "$wget_exists" -eq 0 ]; then
    67              echo "Download failed using wget and curl. Verify that the distribution URL is correct and try again or install the distribution manually."
    68          else
    69              echo "Download failed using curl and wget was not found. Verify that the distribution URL is correct and try again or install the distribution manually."
    70          fi
    71          exit 1
    72      fi
    73  }
    74  
    75  # verifies that the provided checksum matches the computed SHA-256 checksum of the specified file. If not, echoes an
    76  # error and exits.
    77  function verify_checksum {
    78      local file=$1
    79      local expected_checksum=$2
    80      local computed_checksum=$(compute_sha256 $file)
    81      if [ "$expected_checksum" != "$computed_checksum" ]; then
    82          echo "SHA-256 checksum for $file did not match expected value."
    83          echo "Expected: $expected_checksum"
    84          echo "Actual:   $computed_checksum"
    85          exit 1
    86      fi
    87  }
    88  
    89  # computes the SHA-256 hash of the provided file. Uses openssl, shasum or sha1sum program.
    90  function compute_sha256 {
    91      local file=$1
    92      if command -v openssl >/dev/null 2>&1; then
    93          # print SHA-256 hash using openssl
    94          openssl dgst -sha256 "$file" | sed -E 's/SHA(2-)?256\(.*\)= //'
    95      elif command -v shasum >/dev/null 2>&1; then
    96          # Darwin systems ship with "shasum" utility
    97          shasum -a 256 "$file" | sed -E 's/[[:space:]]+.+//'
    98      elif command -v sha256sum >/dev/null 2>&1; then
    99          # Most Linux systems ship with sha256sum utility
   100          sha256sum "$file" | sed -E 's/[[:space:]]+.+//'
   101      else
   102          echo "Could not find program to calculate SHA-256 checksum for file"
   103          exit 1
   104      fi
   105  }
   106  
   107  # Verifies that the tgz file at the provided path contains the paths/files that would be expected in a valid gödel
   108  # distribution with the provided version.
   109  function verify_dist_tgz_valid {
   110      local tgz_path=$1
   111      local version=$2
   112  
   113      local expected_paths=("godel-$version/" "godel-$version/bin/darwin-amd64/godel" "godel-$version/bin/darwin-arm64/godel" "godel-$version/bin/linux-amd64/godel" "godel-$version/bin/linux-arm64/godel" "godel-$version/wrapper/godelw" "godel-$version/wrapper/godel/config/")
   114      local files=($(tar -tf "$tgz_path"))
   115  
   116      # this is a double-for loop, but fine since $expected_paths is small and bash doesn't have good primitives for set/map/list manipulation
   117      for curr_line in "${files[@]}"; do
   118          # if all expected paths have been found, terminate
   119          if [[ ${#expected_paths[*]} == 0 ]]; then
   120              break
   121          fi
   122  
   123          # check for expected path and splice out if match is found
   124          idx=0
   125          for curr_expected in "${expected_paths[@]}"; do
   126              if [ "$curr_expected" = "$curr_line" ]; then
   127                  expected_paths=(${expected_paths[@]:0:idx} ${expected_paths[@]:$(($idx + 1))})
   128                  break
   129              fi
   130              idx=$idx+1
   131          done
   132      done
   133  
   134      # if any expected paths still remain, raise error and exit
   135      if [[ ${#expected_paths[*]} > 0 ]]; then
   136          echo "Required paths were not present in $tgz_path: ${expected_paths[@]}"
   137          exit 1
   138      fi
   139  }
   140  
   141  # Verifies that the gödel binary in the distribution reports the expected version when called with the "version"
   142  # argument. Assumes that a valid gödel distribution directory for the given version exists in the provided directory.
   143  function verify_godel_version {
   144      local base_dir=$1
   145      local version=$2
   146      local os=$3
   147      local arch=$4
   148  
   149      local expected_output="godel version $version"
   150      local version_output=$($base_dir/godel-$version/bin/$os-$arch/godel version)
   151  
   152      if [ "$expected_output" != "$version_output" ]; then
   153          echo "Version reported by godel executable did not match expected version: expected \"$expected_output\", was \"$version_output\""
   154          exit 1
   155      fi
   156  }
   157  
   158  # directory of godelw script
   159  SCRIPT_HOME=$(cd "$(dirname "$0")" && pwd)
   160  
   161  # use $GODEL_HOME or default value
   162  GODEL_BASE_DIR=${GODEL_HOME:-$HOME/.godel}
   163  
   164  # determine OS
   165  OS=""
   166  EXPECTED_CHECKSUM=""
   167  case "$(uname)-$(uname -m)" in
   168      Darwin-x86_64)
   169          OS=darwin
   170          ARCH=amd64
   171          EXPECTED_CHECKSUM=$DARWIN_AMD64_CHECKSUM
   172          ;;
   173      Darwin-arm64)
   174          OS=darwin
   175          ARCH=arm64
   176          EXPECTED_CHECKSUM=$DARWIN_ARM64_CHECKSUM
   177          ;;
   178      Linux-x86_64)
   179          OS=linux
   180          ARCH=amd64
   181          EXPECTED_CHECKSUM=$LINUX_AMD64_CHECKSUM
   182          ;;
   183      Linux-aarch64)
   184          OS=linux
   185          ARCH=arm64
   186          EXPECTED_CHECKSUM=$LINUX_ARM64_CHECKSUM
   187          ;;
   188      *)
   189          echo "Unsupported operating system-architecture: $(uname)-$(uname -m)"
   190          exit 1
   191          ;;
   192  esac
   193  
   194  # path to godel binary
   195  CMD=$GODEL_BASE_DIR/dists/godel-$VERSION/bin/$OS-$ARCH/godel
   196  
   197  # godel binary is not present -- download distribution
   198  if [ ! -f "$CMD" ]; then
   199      # get download URL
   200      PROPERTIES_FILE=$SCRIPT_HOME/godel/config/godel.properties
   201      if [ ! -f "$PROPERTIES_FILE" ]; then
   202          echo "Properties file must exist at $PROPERTIES_FILE"
   203          exit 1
   204      fi
   205      DOWNLOAD_URL=$(cat "$PROPERTIES_FILE" | sed -E -n "s/^distributionURL=//p")
   206      if [ -z "$DOWNLOAD_URL" ]; then
   207          echo "Value for property \"distributionURL\" was empty in $PROPERTIES_FILE"
   208          exit 1
   209      fi
   210      DOWNLOAD_CHECKSUM=$(cat "$PROPERTIES_FILE" | sed -E -n "s/^distributionSHA256=//p")
   211  
   212      # create downloads directory if it does not already exist
   213      mkdir -p "$GODEL_BASE_DIR/downloads"
   214  
   215      # download tgz and verify its contents
   216      # Download to unique location that includes PID ($$) and use trap ensure that temporary download file is cleaned up
   217      # if script is terminated before the file is moved to its destination.
   218      DOWNLOAD_DST=$GODEL_BASE_DIR/downloads/godel-$VERSION-$$.tgz
   219      download "$DOWNLOAD_URL" "$DOWNLOAD_DST"
   220      trap 'rm -rf "$DOWNLOAD_DST"' EXIT
   221      if [ -n "$DOWNLOAD_CHECKSUM" ]; then
   222          verify_checksum "$DOWNLOAD_DST" "$DOWNLOAD_CHECKSUM"
   223      fi
   224      verify_dist_tgz_valid "$DOWNLOAD_DST" "$VERSION"
   225  
   226      # create temporary directory for unarchiving, unarchive downloaded file and verify directory
   227      TMP_DIST_DIR=$(mktemp -d "$GODEL_BASE_DIR/tmp_XXXXXX" 2>/dev/null || mktemp -d -t "$GODEL_BASE_DIR/tmp_XXXXXX")
   228      trap 'rm -rf "$TMP_DIST_DIR"' EXIT
   229      tar zxvf "$DOWNLOAD_DST" -C "$TMP_DIST_DIR" >/dev/null 2>&1
   230      verify_godel_version "$TMP_DIST_DIR" "$VERSION" "$OS" "$ARCH"
   231  
   232      # rename downloaded file to remove PID portion
   233      mv "$DOWNLOAD_DST" "$GODEL_BASE_DIR/downloads/godel-$VERSION.tgz"
   234  
   235      # if destination directory for distribution already exists, remove it
   236      if [ -d "$GODEL_BASE_DIR/dists/godel-$VERSION" ]; then
   237          rm -rf "$GODEL_BASE_DIR/dists/godel-$VERSION"
   238      fi
   239  
   240      # ensure that parent directory of destination exists
   241      mkdir -p "$GODEL_BASE_DIR/dists"
   242  
   243      # move expanded distribution directory to destination location. The location of the unarchived directory is known to
   244      # be in the same directory tree as the destination, so "mv" should always work.
   245      mv "$TMP_DIST_DIR/godel-$VERSION" "$GODEL_BASE_DIR/dists/godel-$VERSION"
   246  
   247      # edge case cleanup: if the destination directory "$GODEL_BASE_DIR/dists/godel-$VERSION" was created prior to the
   248      # "mv" operation above, then the move operation will move the source directory into the destination directory. In
   249      # this case, remove the directory. It should always be safe to remove this directory because if the directory
   250      # existed in the distribution and was non-empty, then the move operation would fail (because non-empty directories
   251      # cannot be overwritten by mv). All distributions of a given version are also assumed to be identical. The only
   252      # instance in which this would not work is if the distribution purposely contained an empty directory that matched
   253      # the name "godel-$VERSION", and this is assumed to never be true.
   254      if [ -d "$GODEL_BASE_DIR/dists/godel-$VERSION/godel-$VERSION" ]; then
   255          rm -rf "$GODEL_BASE_DIR/dists/godel-$VERSION/godel-$VERSION"
   256      fi
   257  fi
   258  
   259  verify_checksum "$CMD" "$EXPECTED_CHECKSUM"
   260  
   261  # execute command
   262  $CMD --wrapper "$SCRIPT_HOME/$(basename "$0")" "$@"