| 1 | #!/bin/sh |
| 2 | # SPDX-License-Identifier: GPL-v3+ |
| 3 | # |
| 4 | # Check if we need to install a Go toolchain. |
| 5 | # |
| 6 | # Scripts that use this should call the ensure_go_toolchain function |
| 7 | # after sourcing this file to handle things correctly. |
| 8 | # |
| 9 | # If a working Go toolchain is either present or was installed, then the |
| 10 | # function will return 0. If a working Go toolchain is not present and one |
| 11 | # cannot be installed, then it will instead return 1, with the variable |
| 12 | # GOLANG_FAILURE_REASON set to an error message indicating what went wrong. |
| 13 | |
| 14 | GOLANG_MIN_MAJOR_VERSION='1' |
| 15 | GOLANG_MIN_MINOR_VERSION='26' |
| 16 | GOLANG_MIN_PATCH_VERSION='0' |
| 17 | GOLANG_MIN_VERSION="${GOLANG_MIN_MAJOR_VERSION}.${GOLANG_MIN_MINOR_VERSION}.${GOLANG_MIN_PATCH_VERSION}" |
| 18 | |
| 19 | GOLANG_TEMP_PATH="${TMPDIR}/go-toolchain" |
| 20 | |
| 21 | check_go_version() { |
| 22 | version="$("${go}" version | awk '{ print $3 }' | sed 's/^go//')" |
| 23 | version_major="$(echo "${version}" | cut -f 1 -d '.')" |
| 24 | version_minor="$(echo "${version}" | cut -f 2 -d '.')" |
| 25 | version_patch="$(echo "${version}" | cut -f 3 -d '.')" |
| 26 | |
| 27 | if [ -z "${version_major}" ] || [ "${version_major}" -lt "${GOLANG_MIN_MAJOR_VERSION}" ]; then |
| 28 | return 1 |
| 29 | elif [ "${version_major}" -gt "${GOLANG_MIN_MAJOR_VERSION}" ]; then |
| 30 | return 0 |
| 31 | fi |
| 32 | |
| 33 | if [ -z "${version_minor}" ] || [ "${version_minor}" -lt "${GOLANG_MIN_MINOR_VERSION}" ]; then |
| 34 | return 1 |
| 35 | elif [ "${version_minor}" -gt "${GOLANG_MIN_MINOR_VERSION}" ]; then |
| 36 | return 0 |
| 37 | fi |
| 38 | |
| 39 | if [ -n "${version_patch}" ] && [ "${version_patch}" -ge "${GOLANG_MIN_PATCH_VERSION}" ]; then |
| 40 | return 0 |
| 41 | fi |
| 42 | |
| 43 | return 1 |
| 44 | } |
| 45 | |
| 46 | install_go_toolchain() { |
| 47 | GOLANG_ARCHIVE_NAME="${GOLANG_TEMP_PATH}/golang.tar.gz" |
| 48 | GOLANG_CHECKSUM_FILE="${GOLANG_TEMP_PATH}/golang.sha256sums" |
| 49 | |
| 50 | case "$(uname -s)" in |
| 51 | Linux) |
| 52 | case "$(uname -m)" in |
| 53 | i?86) |
| 54 | GOLANG_ARCHIVE_URL="https://go.dev/dl/go1.26.4.linux-386.tar.gz" |
| 55 | GOLANG_ARCHIVE_CHECKSUM="5ca0982791791559d11a0eba939617a94c3f37c21aa514a55c415b9167efc658" |
| 56 | ;; |
| 57 | x86_64) |
| 58 | GOLANG_ARCHIVE_URL="https://go.dev/dl/go1.26.4.linux-amd64.tar.gz" |
| 59 | GOLANG_ARCHIVE_CHECKSUM="1153d3d50e0ac764b447adfe05c2bcf08e889d42a02e0fe0259bd47f6733ad7f" |
| 60 | ;; |
| 61 | aarch64) |
| 62 | GOLANG_ARCHIVE_URL="https://go.dev/dl/go1.26.4.linux-arm64.tar.gz" |
| 63 | GOLANG_ARCHIVE_CHECKSUM="ef758ae7c6cf9267c9c0ef080b8965f453d89ab2d25d9eb22de4405925238768" |
| 64 | ;; |
| 65 | armv*) |
| 66 | GOLANG_ARCHIVE_URL="https://go.dev/dl/go1.26.4.linux-armv6l.tar.gz" |
| 67 | GOLANG_ARCHIVE_CHECKSUM="8db458e995f18a9427a745cefe7a3323962fa2548c4715148963311f300d3b1a" |
| 68 | ;; |
| 69 | ppc64le) |
| 70 | GOLANG_ARCHIVE_URL="https://go.dev/dl/go1.26.4.linux-ppc64le.tar.gz" |
| 71 | GOLANG_ARCHIVE_CHECKSUM="53f49b8c7eace2d30389327b4a516b13321f90377fdf5929a6b63174609bc22e" |
| 72 | ;; |
| 73 | riscv64) |
| 74 | GOLANG_ARCHIVE_URL="https://go.dev/dl/go1.26.4.linux-riscv64.tar.gz" |
| 75 | GOLANG_ARCHIVE_CHECKSUM="2b9ba137baaa3031fd74330cb36ab54c5abe380867ca9fbab7c552f3db740555" |
| 76 | ;; |
| 77 | s390x) |
| 78 | GOLANG_ARCHIVE_URL="https://go.dev/dl/go1.26.4.linux-s390x.tar.gz" |
| 79 | GOLANG_ARCHIVE_CHECKSUM="1e12a2318f3dd4c57027c865f6cb51f5d1e36b02d10f3e6316ce7b61a27b3ca1" |
| 80 | ;; |
| 81 | *) |
| 82 | GOLANG_FAILURE_REASON="Linux $(uname -m) platform is not supported out-of-box by Go, you must install a toolchain for it yourself." |
| 83 | return 1 |
| 84 | ;; |
| 85 | esac |
| 86 | ;; |
| 87 | FreeBSD) |
| 88 | case "$(uname -m)" in |
| 89 | 386) |
| 90 | GOLANG_ARCHIVE_URL="https://go.dev/dl/go1.26.4.freebsd-386.tar.gz" |
| 91 | GOLANG_ARCHIVE_CHECKSUM="f4325e0f9a5894e79c60b5e692af55a1e6f261b8ea73dcd20eced8372ad08233" |
| 92 | ;; |
| 93 | amd64) |
| 94 | GOLANG_ARCHIVE_URL="https://go.dev/dl/go1.26.4.freebsd-amd64.tar.gz" |
| 95 | GOLANG_ARCHIVE_CHECKSUM="e91e96c0d3bd8f770e5a0facaf21d010a84e1c9440d830210cb3c223f0b7fb50" |
| 96 | ;; |
| 97 | arm) |
| 98 | GOLANG_ARCHIVE_URL="https://go.dev/dl/go1.26.4.freebsd-arm.tar.gz" |
| 99 | GOLANG_ARCHIVE_CHECKSUM="36e45b3a843087f0f95a71f2ed453ea7e1727e684644d13f8b4c6c93fd977d41" |
| 100 | ;; |
| 101 | arm64) |
| 102 | GOLANG_ARCHIVE_URL="https://go.dev/dl/go1.26.4.freebsd-arm64.tar.gz" |
| 103 | GOLANG_ARCHIVE_CHECKSUM="34aee1071d74cc23703d1b415c5fa44f840d29fd3733dac34944d83cfada3ff3" |
| 104 | ;; |
| 105 | # broken: https://go.dev/doc/go1.26#freebsd |
| 106 | # riscv64) |
| 107 | # GOLANG_ARCHIVE_URL="https://go.dev/dl/go1.26.4.freebsd-riscv64.tar.gz" |
| 108 | # GOLANG_ARCHIVE_CHECKSUM="7b0cc61246cf6fc9e576135cfcd2b95e870b0f2ee5bf057325b2d76119001e4e" |
| 109 | # ;; |
| 110 | *) |
| 111 | GOLANG_FAILURE_REASON="FreeBSD $(uname -m) platform is not supported out-of-box by Go, you must install a toolchain for it yourself." |
| 112 | return 1 |
| 113 | ;; |
| 114 | esac |
| 115 | ;; |
| 116 | *) |
| 117 | GOLANG_FAILURE_REASON="We do not support automatic handling of a Go toolchain on this system, you must install one manually." |
| 118 | return 1 |
| 119 | ;; |
| 120 | esac |
| 121 | |
| 122 | if [ -d '/usr/local/go' ]; then |
| 123 | if [ -f '/usr/local/go/.installed-by-netdata' ]; then |
| 124 | rm -rf /usr/local/go |
| 125 | else |
| 126 | GOLANG_FAILURE_REASON="Refusing to overwrite existing Go toolchain install at /usr/local/go, it needs to be updated manually." |
| 127 | return 1 |
| 128 | fi |
| 129 | fi |
| 130 | |
| 131 | mkdir -p "${GOLANG_TEMP_PATH}" |
| 132 | |
| 133 | if ! curl --fail -q -sSL --connect-timeout 10 --retry 3 --output "${GOLANG_ARCHIVE_NAME}" "${GOLANG_ARCHIVE_URL}"; then |
| 134 | GOLANG_FAILURE_REASON="Failed to download Go toolchain." |
| 135 | return 1 |
| 136 | fi |
| 137 | |
| 138 | echo "${GOLANG_ARCHIVE_CHECKSUM} ${GOLANG_ARCHIVE_NAME}" >"${GOLANG_CHECKSUM_FILE}" |
| 139 | |
| 140 | if ! sha256sum -c "${GOLANG_CHECKSUM_FILE}"; then |
| 141 | GOLANG_FAILURE_REASON="Invalid checksum for downloaded Go toolchain." |
| 142 | return 1 |
| 143 | fi |
| 144 | |
| 145 | if ! tar -C /usr/local/ --no-same-owner -xzf "${GOLANG_ARCHIVE_NAME}"; then |
| 146 | GOLANG_FAILURE_REASON="Failed to extract Go toolchain." |
| 147 | return 1 |
| 148 | fi |
| 149 | |
| 150 | touch /usr/local/go/.installed-by-netdata |
| 151 | |
| 152 | rm -rf "${GOLANG_TEMP_PATH}" |
| 153 | } |
| 154 | |
| 155 | ensure_go_toolchain() { |
| 156 | go="$(PATH="/usr/local/go/bin:${PATH}" command -v go 2>/dev/null)" |
| 157 | |
| 158 | need_go_install=0 |
| 159 | |
| 160 | if [ -z "${go}" ]; then |
| 161 | need_go_install=1 |
| 162 | elif ! check_go_version; then |
| 163 | need_go_install=1 |
| 164 | fi |
| 165 | |
| 166 | if [ "${need_go_install}" -eq 1 ]; then |
| 167 | if ! install_go_toolchain; then |
| 168 | return 1 |
| 169 | fi |
| 170 | |
| 171 | rm -rf "${GOLANG_TEMP_PATH}" || true |
| 172 | fi |
| 173 | |
| 174 | return 0 |
| 175 | } |