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")" "$@"