Add check to avoid auto-installing new major versions of Netdata. (#15898)
* Add check to avoid auto-installing new major versions of Netdata. With the specific intent of avoiding breaking user’s systems. * Add latest tag check override. * Fix local testing fallback case. * Fix version parsing code. * Allow major version updates in CI jobs. * Fix fetching latest tag. * Properly fix CI jobs. * Switch to using a list of accepted major versions. And pre-populate it with versions we think are fine. * Fix CI again. * Fix check logic.
Austin S. Hemmelgarn committed
Jan 17, 2024 at 06:49 UTC
b70e223e80f432b4dd46d3653f4c071a3c0b9b3f
5 files changed
+145
-19
.github/scripts/run-updater-check.sh
+2
-1
@@ -12,7 +12,8 @@ echo "::group::>>> Pre-Update Netdata Build Info"
12
netdata -W buildinfo
13
echo "::endgroup::"
14
echo ">>> Updating Netdata..."
15
-export NETDATA_BASE_URL="http://localhost:8080/artifacts/" # Pull the tarball from the local web server.
15
+export NETDATA_BASE_URL="http://localhost:8080/artifacts" # Pull the tarball from the local web server.
16
+echo 'NETDATA_ACCEPT_MAJOR_VERSIONS="1 9999"' > /etc/netdata/netdata-updater.conf
17
timeout 3600 /netdata/packaging/installer/netdata-updater.sh --not-running-from-cron --no-updater-self-update
18
19
case "$?" in
.github/workflows/build.yml
+7
-4
@@ -492,14 +492,17 @@ jobs:
492
id: prepare
493
if: needs.file-check.outputs.run == 'true'
494
run: |
495
- mkdir -p artifacts/download/latest || exit 1
496
- echo "9999.0.0-0" > artifacts/download/latest/latest-version.txt || exit 1
497
- cp dist-tarball/* artifacts/download/latest || exit 1
498
- cd artifacts/download/latest || exit 1
495
+ mkdir -p artifacts/download/v9999.0.0 || exit 1
496
+ mkdir -p artifacts/latest || exit 1
497
+ echo "v9999.0.0" > artifacts/latest/latest-version.txt || exit 1
498
+ cp dist-tarball/* artifacts/download/v9999.0.0 || exit 1
499
+ cd artifacts/download/v9999.0.0 || exit 1
500
ln -s ${{ needs.build-dist.outputs.distfile }} netdata-latest.tar.gz || exit 1
501
ls -lFh
502
sha256sum -b ./* > "sha256sums.txt" || exit 1
503
cat sha256sums.txt
504
+ cd ../.. || exit 1
505
+ ls -lR
506
- name: Fetch test environment
507
id: fetch-test-environment
508
if: needs.file-check.outputs.run == 'true'
packaging/installer/UPDATE.md
+2
@@ -204,6 +204,8 @@ The following configuration options are currently supported:
204
as a scheduled task. This random delay helps avoid issues resulting from too many nodes trying to reconnect to
205
the Cloud at the same time. The default value is 3600, which corresponds to one hour. Most users should not ever
206
need to change this.
207
+- `NETDATA_MAJOR_VERSION_UPDATES`: If set to a value other than 0, then new major versions will be installed
208
+ without user confirmation. Must be set to a non-zero value for automated updates to install new major versions.
209
- `NETDATA_NO_SYSTEMD_JOURNAL`: If set to a value other than 0, skip attempting to install the
210
`netdata-plugin-systemd-journal` package on supported systems on update. This optional package will be installed
211
by default on supported systems by the updater if this option is not set. Only affects systems using native packages.
packaging/installer/netdata-updater.sh
+111
-11
@@ -28,7 +28,7 @@
28
# Author: Pavlos Emm. Katsoulakis <paul@netdata.cloud>
29
# Author: Austin S. Hemmelgarn <austin@netdata.cloud>
30
31
-# Next unused error code: U001B
31
+# Next unused error code: U001D
32
33
set -e
34
@@ -36,10 +36,12 @@ PACKAGES_SCRIPT="https://raw.githubusercontent.com/netdata/netdata/master/packag
36
37
NETDATA_STABLE_BASE_URL="${NETDATA_BASE_URL:-https://github.com/netdata/netdata/releases}"
38
NETDATA_NIGHTLY_BASE_URL="${NETDATA_BASE_URL:-https://github.com/netdata/netdata-nightlies/releases}"
39
+NETDATA_DEFAULT_ACCEPT_MAJOR_VERSIONS="1 2"
40
41
# Following variables are intended to be overridden by the updater config file.
42
NETDATA_UPDATER_JITTER=3600
43
NETDATA_NO_SYSTEMD_JOURNAL=0
44
+NETDATA_ACCEPT_MAJOR_VERSIONS=''
45
46
script_dir="$(CDPATH='' cd -- "$(dirname -- "$0")" && pwd -P)"
47
@@ -171,6 +173,38 @@ _get_scheduler_type() {
173
fi
174
}
175
176
+confirm() {
177
+ prompt="${1} [y/n]"
178
+
179
+ while true; do
180
+ echo "${prompt}"
181
+ read -r yn
182
+
183
+ case "$yn" in
184
+ [Yy]*) return 0;;
185
+ [Nn]*) return 1;;
186
+ *) echo "Please answer yes or no.";;
187
+ esac
188
+ done
189
+}
190
+
191
+warn_major_update() {
192
+ nmv_suffix="New major versions generally involve breaking changes, and may not work in the same way as older versions."
193
+
194
+ if [ "${INTERACTIVE}" -eq 0 ]; then
195
+ warning "Would update to a new major version of Netdata. ${nmv_suffix}"
196
+ warning "To install the new major version anyway, either run the updater interactively, or include the new major version number in the NETDATA_ACCEPT_MAJOR_VERSIONS variable in ${UPDATER_CONFIG_PATH}."
197
+ fatal "Aborting update to new major version to avoid breaking things." U001B
198
+ else
199
+ warning "This update will install a new major version of Netdata. ${nmv_suffix}"
200
+ if confirm "Are you sure you want to update to a new major version of Netdata?"; then
201
+ notice "User accepted update to new major version of Netdata."
202
+ else
203
+ fatal "Aborting update to new major version at user request." U001C
204
+ fi
205
+ fi
206
+}
207
+
208
install_build_dependencies() {
209
bash="$(command -v bash 2> /dev/null)"
210
@@ -394,19 +428,33 @@ download() {
428
429
get_netdata_latest_tag() {
430
url="${1}/latest"
397
- dest="${2}"
431
432
check_for_curl
433
434
if [ -n "${curl}" ]; then
402
- tag=$("${curl}" "${url}" -s -L -I -o /dev/null -w '%{url_effective}' | grep -m 1 -o '[^/]*$')
435
+ tag=$("${curl}" "${url}" -s -L -I -o /dev/null -w '%{url_effective}' | grep -Eom 1 '[^/]*/?$')
436
elif command -v wget >/dev/null 2>&1; then
404
- tag=$(wget -S -O /dev/null "${url}" 2>&1 | grep -m 1 Location | grep -o '[^/]*$')
437
+ tag=$(wget -S -O /dev/null "${url}" 2>&1 | grep -m 1 Location | grep -Eo '[^/]*/?$')
438
else
439
fatal "I need curl or wget to proceed, but neither of them are available on this system." U0006
440
fi
441
409
- echo "${tag}" >"${dest}"
442
+ # Fallback case for simpler local testing.
443
+ if echo "${tag}" | grep -Eq 'latest/?$'; then
444
+ if _safe_download "${url}/latest-version.txt" ./ndupdate-version.txt; then
445
+ tag="$(cat ./ndupdate-version.txt)"
446
+
447
+ if grep -q 'Not Found' ./ndupdate-version.txt; then
448
+ tag="latest"
449
+ fi
450
+
451
+ rm -f ./ndupdate-version.txt
452
+ else
453
+ tag="latest"
454
+ fi
455
+ fi
456
+
457
+ echo "${tag}"
458
}
459
460
newer_commit_date() {
@@ -494,9 +542,9 @@ parse_version() {
542
543
get_latest_version() {
544
if [ "${RELEASE_CHANNEL}" = "stable" ]; then
497
- get_netdata_latest_tag "${NETDATA_STABLE_BASE_URL}" /dev/stdout
545
+ get_netdata_latest_tag "${NETDATA_STABLE_BASE_URL}"
546
else
499
- get_netdata_latest_tag "${NETDATA_NIGHTLY_BASE_URL}" /dev/stdout
547
+ get_netdata_latest_tag "${NETDATA_NIGHTLY_BASE_URL}"
548
fi
549
}
550
@@ -513,6 +561,7 @@ update_available() {
561
info "Force update requested"
562
return 0
563
fi
564
+
565
basepath="$(dirname "$(dirname "$(dirname "${NETDATA_LIB_DIR}")")")"
566
searchpath="${basepath}/bin:${basepath}/sbin:${basepath}/usr/bin:${basepath}/usr/sbin:${PATH}"
567
searchpath="${basepath}/netdata/bin:${basepath}/netdata/sbin:${basepath}/netdata/usr/bin:${basepath}/netdata/usr/sbin:${searchpath}"
@@ -542,6 +591,27 @@ update_available() {
591
return 1
592
else
593
info "Update available"
594
+
595
+ if [ "${current_version}" -ne 0 ] && [ "${latest_version}" -ne 0 ]; then
596
+ current_major="$(${ndbinary} -v | cut -f 2 -d ' ' | cut -f 1 -d '.' | tr -d 'v')"
597
+ latest_major="$(echo "${latest_tag}" | cut -f 1 -d '.' | tr -d 'v')"
598
+
599
+ if [ "${current_major}" -ne "${latest_major}" ]; then
600
+ update_safe=0
601
+
602
+ for v in ${NETDATA_ACCEPT_MAJOR_VERSIONS}; do
603
+ if [ "${current_major}" -eq "${v}" ]; then
604
+ update_safe=1
605
+ break
606
+ fi
607
+ done
608
+
609
+ if [ "${update_safe}" -eq 0 ]; then
610
+ warn_major_update
611
+ fi
612
+ fi
613
+ fi
614
+
615
return 0
616
fi
617
}
@@ -561,11 +631,11 @@ set_tarball_urls() {
631
fi
632
633
if [ "$1" = "stable" ]; then
564
- latest="$(get_netdata_latest_tag "${NETDATA_STABLE_BASE_URL}" /dev/stdout)"
634
+ latest="$(get_netdata_latest_tag "${NETDATA_STABLE_BASE_URL}")"
635
export NETDATA_TARBALL_URL="${NETDATA_STABLE_BASE_URL}/download/$latest/${filename}"
636
export NETDATA_TARBALL_CHECKSUM_URL="${NETDATA_STABLE_BASE_URL}/download/$latest/sha256sums.txt"
637
else
568
- tag="$(get_netdata_latest_tag "${NETDATA_NIGHTLY_BASE_URL}" /dev/stdout)"
638
+ tag="$(get_netdata_latest_tag "${NETDATA_NIGHTLY_BASE_URL}")"
639
export NETDATA_TARBALL_URL="${NETDATA_NIGHTLY_BASE_URL}/download/${tag}/${filename}"
640
export NETDATA_TARBALL_CHECKSUM_URL="${NETDATA_NIGHTLY_BASE_URL}/download/${tag}/sha256sums.txt"
641
fi
@@ -714,6 +784,15 @@ update_static() {
784
exit 0
785
}
786
787
+get_new_binpkg_major() {
788
+ case "${pm_cmd}" in
789
+ apt-get) apt-get --just-print upgrade 2>&1 | grep Inst | grep ' netdata ' | cut -f 3 -d ' ' | tr -d '[]' | cut -f 1 -d '.' ;;
790
+ yum) yum check-update netdata | grep -E '^netdata ' | awk '{print $2}' | cut -f 1 -d '.' ;;
791
+ dnf) dnf check-update netdata | grep -E '^netdata ' | awk '{print $2}' | cut -f 1 -d '.' ;;
792
+ zypper) zypper list-updates | grep '| netdata |' | cut -f 5 -d '|' | tr -d ' ' | cut -f 1 -d '.' ;;
793
+ esac
794
+}
795
+
796
update_binpkg() {
797
os_release_file=
798
if [ -s "/etc/os-release" ] && [ -r "/etc/os-release" ]; then
@@ -824,6 +903,24 @@ update_binpkg() {
903
fi
904
done
905
906
+ current_major="$(netdata -v | cut -f 2 -d ' ' | cut -f 1 -d '.' | tr -d 'v')"
907
+ latest_major="$(get_new_binpkg_major)"
908
+
909
+ if [ -n "${latest_major}" ] && [ "${latest_major}" -ne "${current_major}" ]; then
910
+ update_safe=0
911
+
912
+ for v in ${NETDATA_ACCEPT_MAJOR_VERSIONS}; do
913
+ if [ "${current_major}" -eq "${v}" ]; then
914
+ update_safe=1
915
+ break
916
+ fi
917
+ done
918
+
919
+ if [ "${update_safe}" -eq 0 ]; then
920
+ warn_major_update
921
+ fi
922
+ fi
923
+
924
# shellcheck disable=SC2086
925
env ${env} ${pm_cmd} ${upgrade_subcmd} ${pkg_install_opts} netdata >&3 2>&3 || fatal "Failed to update Netdata package." U000F
926
@@ -902,11 +999,14 @@ if [ -r "$(dirname "${ENVIRONMENT_FILE}")/.install-type" ]; then
999
. "$(dirname "${ENVIRONMENT_FILE}")/.install-type" || fatal "Failed to source $(dirname "${ENVIRONMENT_FILE}")/.install-type" U0015
1000
fi
1001
905
-if [ -r "$(dirname "${ENVIRONMENT_FILE}")/netdata-updater.conf" ]; then
1002
+UPDATER_CONFIG_PATH="$(dirname "${ENVIRONMENT_FILE}")/netdata-updater.conf"
1003
+if [ -r "${UPDATER_CONFIG_PATH}" ]; then
1004
# shellcheck source=/dev/null
907
- . "$(dirname "${ENVIRONMENT_FILE}")/netdata-updater.conf"
1005
+ . "${UPDATER_CONFIG_PATH}"
1006
fi
1007
1008
+[ -z "${NETDATA_ACCEPT_MAJOR_VERSIONS}" ] && NETDATA_ACCEPT_MAJOR_VERSIONS="${NETDATA_DEFAULT_ACCEPT_MAJOR_VERSIONS}"
1009
+
1010
while [ -n "${1}" ]; do
1011
case "${1}" in
1012
--not-running-from-cron) NETDATA_NOT_RUNNING_FROM_CRON=1 ;;
system/netdata-updater.conf
+23
-3
@@ -2,10 +2,30 @@
2
#
3
# When run non-interactively, the updater script will delay some
4
# random number of seconds up to NETDATA_UPDATER_JITTER before
5
-# actually running the update. The default is 3600 (one
6
-# hour). Most users should not need to change this.
5
+# actually running the update. The default is 3600 (one hour). Most
6
+# users should not need to change this.
7
#NETDATA_UPDATER_JITTER="3600"
8
9
+# By default, the updater will update to new major versions without asking
10
+# for user confirmation once we consider them ready for general usage.
11
+#
12
+# You can override this behavior by setting NETDATA_ACCEPT_MAJOR_VERSIONS
13
+# to a space separated list of major versions you are willing to update
14
+# to. Attempts to update to newer major versions not listed in this variable
15
+# will be treated as a fatal error.
16
+#
17
+# An empty value is equivalent to the default behavior.
18
+#
19
+# This only applies to static builds and local builds. If you are using
20
+# our native packages, use your package manager’s existing functionality
21
+# to prevent updates (for example, pinning versions on APT-based systems,
22
+# or the DNF versionlock plugin on RHEL/Fedora).
23
+#
24
+# To lock yourself to a specific major version, set this value to exactly
25
+# that major version number. For example, to stay on version 1.x even
26
+# if 2.x has been released, set this to a value of `1`.
27
+#NETDATA_ACCEPT_MAJOR_VERSIONS=''
28
+
29
# On systems using our native packages, the updater will by default
30
# attempt to install optional plugin packages that would be installed by
31
# default on clean installs if those packages are supported on the system.
@@ -13,7 +33,7 @@
33
# This behavior can be disabled on a per-package basis using the below
34
# variables. Setting the variable to a value other than 0 will disable
35
# the corresponding package (note that you still need to remove the package
16
-# yourself if you don0t want it, this just controls whether the updater
36
+# yourself if you don't want it, this just controls whether the updater
37
# will try to ensure it’s installed or not).
38
#
39
# NETDATA_NO_SYSTEMD_JOURNAL controls the `netdata-plugin-systemd-journal`