From 78c0af21016a9c349815093057c41011b6a8be21 Mon Sep 17 00:00:00 2001 From: oscar Date: Wed, 1 Feb 2023 15:27:15 +0100 Subject: [PATCH 01/43] doc: fixed docs --- README.md | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/README.md b/README.md index 45e86cb5d..ae6e57184 100644 --- a/README.md +++ b/README.md @@ -105,11 +105,7 @@ Supplemental software and/or configurations can be installed in 3 ways on SafeSc A "SafeScale `Feature`" is a file in YAML format that describes the operations to check/add/remove software and/or configuration on a target (Host or Cluster). -A `Feature` can describe operations using different methods: -- `package`: just define the package(s) concerned -- `bash`: uses bash snippets -- `helm`: uses helm chart, the "package" engine for Kubernetes -- `ansible`: defines playbook to run, SafeScale providing inventory +A `Feature` can describe operations using bash snippets. Additionally, a `Feature` is able to apply: - reverse proxy rules From c9b3f3ec37b8c7e91b04803649c617c0871de7c8 Mon Sep 17 00:00:00 2001 From: oscar Date: Wed, 1 Feb 2023 15:58:38 +0100 Subject: [PATCH 02/43] chores: added release script --- build/releaseit.sh | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 build/releaseit.sh diff --git a/build/releaseit.sh b/build/releaseit.sh new file mode 100644 index 000000000..39fb308db --- /dev/null +++ b/build/releaseit.sh @@ -0,0 +1,17 @@ +#! /bin/bash -x + +docker system prune -a -f +./create-docker.sh -f +docker system prune -a -f +GOOSX=darwin GOARCHX=arm64 ./create-docker2.sh -f +docker system prune -a -f +GOOSX=linux GOARCHX=arm ./create-docker2.sh -f +docker system prune -a -f +GOOSX=windows GOARCHX=amd64 ./create-docker2.sh -f +docker system prune -a -f +mv ./exported-windows-amd64/safescale ./exported-windows-amd64/safescale.exe +mv ./exported-windows-amd64/safescaled ./exported-windows-amd64/safescaled.exe +tar -czf safescale-$1-linux-amd64.tar.gz ./exported/sa* +tar -czf safescale-$1-linux-arm.tar.gz ./exported-linux-arm/sa* +tar -czf safescale-$1-darwin-arm64.tar.gz ./exported-darwin-arm64/sa* +tar -czf safescale-$1-windows-amd64.tar.gz ./exported-windows-amd64/sa* From 9cbe03661c677c16f6665b0b5fdcfe10574f03a2 Mon Sep 17 00:00:00 2001 From: oscar Date: Wed, 1 Feb 2023 17:42:17 +0100 Subject: [PATCH 03/43] feat: enables remotedesktop only if we ask for it when cluster is created --- cli/safescale/commands/cluster.go | 6 ++++++ lib/backend/resources/abstract/cluster.go | 1 + lib/backend/resources/operations/cluster.go | 20 ++++++++++--------- .../operations/converters/protocol.go | 1 + lib/protocol/safescale.proto | 1 + 5 files changed, 20 insertions(+), 9 deletions(-) diff --git a/cli/safescale/commands/cluster.go b/cli/safescale/commands/cluster.go index e797b02df..7ca7fd663 100644 --- a/cli/safescale/commands/cluster.go +++ b/cli/safescale/commands/cluster.go @@ -415,6 +415,10 @@ var clusterCreateCommand = cli.Command{ Name: "disable", Usage: "Allows to disable addition of default features (can be used several times to disable several features)", }, + cli.StringSliceFlag{ + Name: "enable", + Usage: "Allows to enable addition of features (can be used several times to enable several features)", + }, cli.StringFlag{ Name: "os", Usage: "Defines the operating system to use", @@ -492,6 +496,7 @@ var clusterCreateCommand = cli.Command{ keep := c.Bool("keep-on-failure") cidr := c.String("cidr") disable := c.StringSlice("disable") + enable := c.StringSlice("enable") los := c.String("os") gatewaySSHPort := uint32(c.Int("gwport")) @@ -533,6 +538,7 @@ var clusterCreateCommand = cli.Command{ KeepOnFailure: keep, Cidr: cidr, Disabled: disable, + Enabled: enable, Os: los, GlobalSizing: globalDef, GatewaySizing: gatewaysDef, diff --git a/lib/backend/resources/abstract/cluster.go b/lib/backend/resources/abstract/cluster.go index a3432d93b..82b693933 100755 --- a/lib/backend/resources/abstract/cluster.go +++ b/lib/backend/resources/abstract/cluster.go @@ -51,6 +51,7 @@ type ClusterRequest struct { Force bool // set to True in order to ignore sizing recommendations FeatureParameters []string // contains parameter values of automatically installed Features DefaultSshPort uint // default ssh port for gateways // nolint + Enabled []string // enabled features } // ClusterIdentity contains the bare minimum information about a cluster diff --git a/lib/backend/resources/operations/cluster.go b/lib/backend/resources/operations/cluster.go index eae9e86a0..404a0a79f 100755 --- a/lib/backend/resources/operations/cluster.go +++ b/lib/backend/resources/operations/cluster.go @@ -2247,17 +2247,19 @@ func (instance *Cluster) configureCluster(inctx context.Context, req abstract.Cl // FIXME: Enable this ONLY after remotedesktop feature is UPDATED AND TESTED // Also, EOL, unsafe, undocumented, 4 releases have passed since 1.0.0 was published - /* - xerr := instance.installRemoteDesktop(ctx, parameters, req) - xerr = debug.InjectPlannedFail(xerr) - if xerr != nil { - // Break execution flow only if the Feature cannot be run (file transfer, Host unreachable, ...), not if it ran but has failed - if annotation, found := xerr.Annotation("ran_but_failed"); !found || !annotation.(bool) { - chRes <- result{xerr} - return + for _, v := range req.Enabled { // if some explicitly asks for it + if v == "remotedesktop" { + xerr := instance.installRemoteDesktop(ctx, parameters, req) + xerr = debug.InjectPlannedFail(xerr) + if xerr != nil { + // Break execution flow only if the Feature cannot be run (file transfer, Host unreachable, ...), not if it ran but has failed + if annotation, found := xerr.Annotation("ran_but_failed"); !found || !annotation.(bool) { + chRes <- result{xerr} + return + } } } - */ + } // Install ansible feature on Cluster (all masters) // aaaand it's gone... /* diff --git a/lib/backend/resources/operations/converters/protocol.go b/lib/backend/resources/operations/converters/protocol.go index 0a79b2b80..287d29621 100755 --- a/lib/backend/resources/operations/converters/protocol.go +++ b/lib/backend/resources/operations/converters/protocol.go @@ -183,6 +183,7 @@ func ClusterRequestFromProtocolToAbstract(in *protocol.ClusterCreateRequest) (_ InitialMasterCount: uint(masterCount), FeatureParameters: in.GetParameters(), DefaultSshPort: uint(in.DefaultSshPort), + Enabled: in.GetEnabled(), } return &out, nil } diff --git a/lib/protocol/safescale.proto b/lib/protocol/safescale.proto index ed2ca8497..c791da8f5 100755 --- a/lib/protocol/safescale.proto +++ b/lib/protocol/safescale.proto @@ -853,6 +853,7 @@ message ClusterCreateRequest { bool force = 17; // ignore cluster sizing recommendations repeated string parameters = 18; // contains optional parameters for automatically installed Features uint32 default_ssh_port = 19; // contains the default ssh port for cluster gateways + repeated string enabled = 20; } message ClusterResizeRequest { From 33e66121e0f1db6fb6d9e031abe53d7c94d2c33d Mon Sep 17 00:00:00 2001 From: oscar Date: Thu, 2 Feb 2023 08:31:06 +0100 Subject: [PATCH 04/43] clean: removed python3-setuptools --- Makefile | 24 ++++++++------ .../iaas/userdata/newscripts/userdata.init.sh | 31 +++++++++++++++++++ .../userdata/newscripts/userdata.netsec.sh | 6 ++-- .../iaas/userdata/scripts/userdata.init.sh | 31 +++++++++++++++++++ .../iaas/userdata/scripts/userdata.netsec.sh | 6 ++-- 5 files changed, 82 insertions(+), 16 deletions(-) diff --git a/Makefile b/Makefile index 1a859a50e..d38517f5a 100755 --- a/Makefile +++ b/Makefile @@ -135,6 +135,10 @@ sharetests: @echo "settings go build tags for sharetests" @$(eval BUILD_TAGS = "sharetests,$(BUILD_TAGS)") +labeltests: + @echo "settings go build tags for labeltests" + @$(eval BUILD_TAGS = "labeltests,$(BUILD_TAGS)") + ifeq ($(OS),Windows_NT) releasearchive: @printf "%b" "$(OK_COLOR)$(OK_STRING) Creating release archive $(NO_COLOR)\n"; @@ -539,12 +543,12 @@ gofmt: begin err: begin generate @printf "%b" "$(OK_COLOR)$(INFO_STRING) Running errcheck, $(NO_COLOR)target $(OBJ_COLOR)$(@)$(NO_COLOR)\n"; - @$(GO) list ./... 2>&1 | grep -v mock | grep -v rules | grep -v cli | xargs errcheck -asserts | grep -v test | grep -v .pb. | grep -v nolint | $(TEE) err_results.log + @$(GO) list ./... 2>&1 | grep -v mock | grep -v rules | grep -v cli | xargs errcheck -asserts | grep -v test | grep -v .pb. | grep -v nolint 2>&1 | $(TEE) err_results.log @if [ -s ./err_results.log ]; then printf "%b" "$(ERROR_COLOR)$(ERROR_STRING) errcheck FAILED !$(NO_COLOR)\n";exit 1;else printf "%b" "$(OK_COLOR)$(OK_STRING) CONGRATS. NO PROBLEMS DETECTED ! $(NO_COLOR)\n";fi; vet: begin generate @printf "%b" "$(OK_COLOR)$(INFO_STRING) Running vet checks, $(NO_COLOR)target $(OBJ_COLOR)$(@)$(NO_COLOR)\n"; - @$(GO) list ./... | grep -v mock | grep -v rules | grep -v cli | xargs $(GO) vet | $(TEE) vet_results.log + @$(GO) list ./... | grep -v mock | grep -v rules | grep -v cli | xargs $(GO) vet 2>&1 | $(TEE) vet_results.log @if [ -s ./vet_results.log ]; then printf "%b" "$(ERROR_COLOR)$(ERROR_STRING) vet FAILED !$(NO_COLOR)\n";exit 1;else printf "%b" "$(OK_COLOR)$(OK_STRING) CONGRATS. NO PROBLEMS DETECTED ! $(NO_COLOR)\n";fi semgrep: begin @@ -553,9 +557,9 @@ semgrep: begin @($(WHICH) ruleguard > /dev/null || (echo "ruleguard not installed in your system" && exit 1)) ifeq ($(shell $(MD5) --status -c sums.log 2>/dev/null && echo 0 || echo 1 ),1) @$(RM) semgrep_results.log || true - @ruleguard -c=0 -rules build/rules/ruleguard.rules.$(CERR).go ./... 2>&1 | tr '\n' '\0' | xargs -0 -n2 | grep -v nolint | grep -v _test.go | grep -v mock | grep -v .pb. | awk 'NF' | $(TEE) semgrep_results.log - @ruleguard -c=0 -rules build/rules/ruleguard.rules.json.go ./... 2>&1 | tr '\n' '\0' | xargs -0 -n2 | grep -v nolint | grep -v mock | grep -v _test.go | grep -v .pb. | awk 'NF' | $(TEE) -a semgrep_results.log - @ruleguard -c=0 -rules build/rules/ruleguard.rules.locks.go ./... 2>&1 | tr '\n' '\0' | xargs -0 -n2 | grep -v defer | grep -v nolint | grep -v mock | grep -v _test.go | grep -v .pb. | awk 'NF' | $(TEE) -a semgrep_results.log + @ruleguard -c=0 -rules build/rules/ruleguard.rules.$(CERR).go ./... 2>&1 | tr '\n' '\0' | xargs -0 -n2 | grep -v nolint | grep -v _test.go | grep -v mock | grep -v .pb. | awk 'NF' 2>&1 | $(TEE) semgrep_results.log + @ruleguard -c=0 -rules build/rules/ruleguard.rules.json.go ./... 2>&1 | tr '\n' '\0' | xargs -0 -n2 | grep -v nolint | grep -v mock | grep -v _test.go | grep -v .pb. | awk 'NF' 2>&1 | $(TEE) -a semgrep_results.log + @ruleguard -c=0 -rules build/rules/ruleguard.rules.locks.go ./... 2>&1 | tr '\n' '\0' | xargs -0 -n2 | grep -v defer | grep -v nolint | grep -v mock | grep -v _test.go | grep -v .pb. | awk 'NF' 2>&1 | $(TEE) -a semgrep_results.log @if [ -s ./semgrep_results.log ]; then printf "%b" "$(ERROR_COLOR)$(ERROR_STRING) semgrep FAILED, look at semgrep_results.log !$(NO_COLOR)\n";exit 1;else printf "%b" "$(OK_COLOR)$(OK_STRING) CONGRATS. NO PROBLEMS DETECTED ! $(NO_COLOR)\n";fi else @printf "%b" "$(OK_COLOR)$(OK_STRING) Nothing to do $(NO_COLOR)target $(OBJ_COLOR)$(@)$(NO_COLOR)\n"; @@ -569,7 +573,7 @@ metalint: begin @($(WHICH) golangci-lint > /dev/null || (echo "golangci-lint not installed in your system" && exit 1)) ifeq ($(shell $(MD5) --status -c sums.log 2>/dev/null && echo 0 || echo 1 ),1) @$(RM) metalint_results.log || true - @golangci-lint --color never --timeout=16m --no-config --disable=unused --disable=goconst --disable=maligned --enable=unparam --enable=deadcode --disable=gocyclo --enable=varcheck --enable=staticcheck --enable=structcheck --disable=typecheck --enable=errcheck --enable=ineffassign --enable=interfacer --enable=unconvert --enable=gosec --enable=megacheck --enable=gocritic --enable=dogsled --disable=funlen --disable=gochecknoglobals --enable=depguard run ./lib/... 2>/dev/null | tr '\n' '\0' | xargs -0 -n3 | grep -v nolint | grep -v _test.go | grep -v .pb. | grep -v "\s*^\s*" | grep -v ^[[:space:]]*$ | $(TEE) metalint_results.log + @golangci-lint --color never --timeout=16m --no-config --disable=unused --disable=goconst --disable=maligned --enable=unparam --enable=deadcode --disable=gocyclo --enable=varcheck --enable=staticcheck --enable=structcheck --disable=typecheck --enable=errcheck --enable=ineffassign --enable=interfacer --enable=unconvert --enable=gosec --enable=megacheck --enable=gocritic --enable=dogsled --disable=funlen --disable=gochecknoglobals --enable=depguard run ./lib/... 2>/dev/null | tr '\n' '\0' | xargs -0 -n3 | grep -v nolint | grep -v _test.go | grep -v .pb. | grep -v "\s*^\s*" | grep -v ^[[:space:]]*$ 2>&1 | $(TEE) metalint_results.log @if [ -s ./metalint_results.log ]; then printf "%b" "$(ERROR_COLOR)$(ERROR_STRING) metalint FAILED, look at metalint_results.log !$(NO_COLOR)\n";exit 1;else printf "%b" "$(OK_COLOR)$(OK_STRING) CONGRATS. NO PROBLEMS DETECTED ! $(NO_COLOR)\n";fi else @printf "%b" "$(OK_COLOR)$(OK_STRING) Nothing to do $(NO_COLOR)target $(OBJ_COLOR)$(@)$(NO_COLOR)\n"; @@ -590,7 +594,7 @@ style: begin @($(WHICH) golangci-lint > /dev/null || (echo "golangci-lint not installed in your system" && exit 1)) ifeq ($(shell $(MD5) --status -c sums.log 2>/dev/null && echo 0 || echo 1 ),1) @$(RM) style_results.log || true - @golangci-lint --color never --timeout=10m --no-config --disable=unused --disable=goconst --disable=gocyclo --enable=errcheck --enable=stylecheck --disable=typecheck --enable=deadcode --enable=revive --enable=gocritic --enable=staticcheck --enable=gosimple --enable=govet --enable=ineffassign --enable=varcheck run ./... 2>/dev/null | tr '\n' ' ' | tr "^" '\0' | xargs -0 -n1 | grep -v _test.go | grep -v nolint | grep -v .pb. | grep -v typecheck | awk 'NF' | $(TEE) style_results.log + @golangci-lint --color never --timeout=10m --no-config --disable=unused --disable=goconst --disable=gocyclo --enable=errcheck --enable=stylecheck --disable=typecheck --enable=deadcode --enable=revive --enable=gocritic --enable=staticcheck --enable=gosimple --enable=govet --enable=ineffassign --enable=varcheck run ./... 2>/dev/null | tr '\n' ' ' | tr "^" '\0' | xargs -0 -n1 | grep -v _test.go | grep -v nolint | grep -v .pb. | grep -v typecheck | awk 'NF' 2>&1 | $(TEE) style_results.log @if [ -s ./style_results.log ]; then printf "%b" "$(ERROR_COLOR)$(ERROR_STRING) style FAILED, look at style_results.log !$(NO_COLOR)\n";exit 1;else printf "%b" "$(OK_COLOR)$(OK_STRING) CONGRATS. NO PROBLEMS DETECTED ! $(NO_COLOR)\n";fi else @printf "%b" "$(OK_COLOR)$(OK_STRING) Nothing to do $(NO_COLOR)target $(OBJ_COLOR)$(@)$(NO_COLOR)\n"; @@ -614,7 +618,7 @@ badpractices: begin @($(WHICH) ireturn > /dev/null || (echo "ireturn not installed in your system" && exit 1)) ifeq ($(shell $(MD5) --status -c sums.log 2>/dev/null && echo 0 || echo 1 ),1) @$(RM) practices_results.log || true - @ireturn ./... 2>&1 | grep -v mock_ | grep -v fail.Error | $(TEE) practices_results.log + @ireturn ./... 2>&1 | grep -v mock_ | grep -v fail.Error 2>&1 | $(TEE) practices_results.log @if [ -s ./practices_results.log ]; then printf "%b" "$(ERROR_COLOR)$(ERROR_STRING) maint FAILED, look at practices_results.log !$(NO_COLOR)\n";exit 1;else printf "%b" "$(OK_COLOR)$(OK_STRING) CONGRATS. NO PROBLEMS DETECTED ! $(NO_COLOR)\n";fi else @printf "%b" "$(OK_COLOR)$(OK_STRING) Nothing to do $(NO_COLOR)target $(OBJ_COLOR)$(@)$(NO_COLOR)\n"; @@ -627,7 +631,7 @@ ctxcheck: begin @($(WHICH) contextcheck > /dev/null || (echo "contextcheck not installed in your system" && exit 1)) ifeq ($(shell $(MD5) --status -c sums.log 2>/dev/null && echo 0 || echo 1 ),1) @$(RM) ctxcheck_results.log || true - @contextcheck ./lib/backend/resources/operations/... 2>&1 | grep -v mock_ | grep -v fail.Error | grep -v nolint | $(TEE) ctxcheck_results.log + @contextcheck ./lib/backend/resources/operations/... 2>&1 | grep -v mock_ | grep -v fail.Error | grep -v nolint 2>&1 | $(TEE) ctxcheck_results.log @if [ -s ./ctxcheck_results.log ]; then printf "%b" "$(ERROR_COLOR)$(ERROR_STRING) maint FAILED, look at ctxcheck_results.log !$(NO_COLOR)\n";exit 1;else printf "%b" "$(OK_COLOR)$(OK_STRING) CONGRATS. NO PROBLEMS DETECTED ! $(NO_COLOR)\n";fi else @printf "%b" "$(OK_COLOR)$(OK_STRING) Nothing to do $(NO_COLOR)target $(OBJ_COLOR)$(@)$(NO_COLOR)\n"; @@ -637,7 +641,7 @@ warnings: begin @printf "%b" "$(OK_COLOR)$(INFO_STRING) Running warnings checks, $(NO_COLOR)target $(OBJ_COLOR)$(@)$(NO_COLOR)\n"; @($(WHICH) golangci-lint > /dev/null || (echo "golangci-lint not installed in your system" && exit 1)) @$(RM) warnings_results.log || true - @golangci-lint --color never --timeout=16m run ./... 2>/dev/null | tr '\n' ' ' | sed -e "s/\^/\n/g" | grep -v nolint | grep -v rangeValCopy | grep -v json.camel | grep -v magic.numbers | grep -v _test.go | grep -v .pb. | $(TEE) warnings_results.log + @golangci-lint --color never --timeout=16m run ./... 2>/dev/null | tr '\n' ' ' | sed -e "s/\^/\n/g" | grep -v nolint | grep -v rangeValCopy | grep -v json.camel | grep -v magic.numbers | grep -v _test.go | grep -v .pb. 2>&1 | $(TEE) warnings_results.log @if [ -s ./warnings_results.log ]; then printf "%b" "$(ERROR_COLOR)$(ERROR_STRING) warnings FAILED, look at warnings_results.log !$(NO_COLOR)\n";exit 1;else printf "%b" "$(OK_COLOR)$(OK_STRING) CONGRATS. NO PROBLEMS DETECTED ! $(NO_COLOR)\n";fi show-cov: begin diff --git a/lib/backend/iaas/userdata/newscripts/userdata.init.sh b/lib/backend/iaas/userdata/newscripts/userdata.init.sh index aa9ca25a3..6039218bf 100644 --- a/lib/backend/iaas/userdata/newscripts/userdata.init.sh +++ b/lib/backend/iaas/userdata/newscripts/userdata.init.sh @@ -250,6 +250,34 @@ function disable_upgrades() { esac } +export -f disable_upgrades + +# try using dnf instead of yum if available +function sfYum() { + rc=-1 + if [[ -n $(which dnf) ]]; then + dnf "$@" && rc=$? + else + yum "$@" && rc=$? + fi + [ $rc -eq -1 ] && return 1 + return $rc +} +export -f sfYum + +function remove_setuptools() { + case $LINUX_KIND in + debian | ubuntu) + # If it's not there, nothing to do + sudo dpkg -l python3-setuptools || true + sudo dpkg -l python3-setuptools | grep ii && echo "python3-setuptools already there" + sudo dpkg -l python3-setuptools | grep ii && sudo apt-get remove -y python3-setuptools + ;; + redhat | fedora | centos) + sfYum remove -y python3-setuptools || true + esac +} +export -f remove_setuptools function no_daily_update() { case $LINUX_KIND in @@ -284,6 +312,7 @@ function no_daily_update() { ;; esac } +export -f no_daily_update # ---- Main export DEBIAN_FRONTEND=noninteractive @@ -310,6 +339,8 @@ drop_user create_user +remove_setuptools + no_daily_update touch /etc/cloud/cloud-init.disabled diff --git a/lib/backend/iaas/userdata/newscripts/userdata.netsec.sh b/lib/backend/iaas/userdata/newscripts/userdata.netsec.sh index dcef6ace1..8ec2064f4 100644 --- a/lib/backend/iaas/userdata/newscripts/userdata.netsec.sh +++ b/lib/backend/iaas/userdata/newscripts/userdata.netsec.sh @@ -108,7 +108,7 @@ function reset_fw() { sfRetry4 "sfApt update" || failure 207 "reset_fw(): failure running apt update" sfRetry4 "sfApt -y autoclean autoremove" || failure 210 "reset_fw(): failure running cleanup" sfRetry4 "sfApt install -q -y --no-install-recommends iptables" || failure 210 "reset_fw(): failure installing iptables" - sfRetry4 "sfApt install -q -y --no-install-recommends firewalld python3 python3-pip" || failure 211 "reset_fw(): failure installing firewalld" + sfRetry4 "sfApt install -q -y --no-install-recommends firewalld python3" || failure 211 "reset_fw(): failure installing firewalld" systemctl is-active ufw &> /dev/null && { echo "Stopping ufw" @@ -125,7 +125,7 @@ function reset_fw() { sfRetry4 "sfApt update" || failure 213 "reset_fw(): failure running apt update" sfRetry4 "sfApt -y autoclean autoremove" || failure 213 "reset_fw(): failure running cleanup" sfRetry4 "sfApt install -q -y --no-install-recommends iptables" || failure 214 "reset_fw(): failure installing iptables" - sfRetry4 "sfApt install -q -y --no-install-recommends firewalld python3 python3-pip" || failure 215 "reset_fw(): failure installing firewalld" + sfRetry4 "sfApt install -q -y --no-install-recommends firewalld python3" || failure 215 "reset_fw(): failure installing firewalld" systemctl is-active ufw &> /dev/null && { echo "Stopping ufw" @@ -146,7 +146,7 @@ function reset_fw() { sudo dnf config-manager -y --disable epel-modular sudo dnf config-manager -y --disable epel fi - sfRetry4 "sfYum install -q -y firewalld python3 python3-pip" || failure 220 "reset_fw(): failure installing firewalld" + sfRetry4 "sfYum install -q -y firewalld python3" || failure 220 "reset_fw(): failure installing firewalld" fi fi ;; diff --git a/lib/backend/iaas/userdata/scripts/userdata.init.sh b/lib/backend/iaas/userdata/scripts/userdata.init.sh index aa9ca25a3..6039218bf 100644 --- a/lib/backend/iaas/userdata/scripts/userdata.init.sh +++ b/lib/backend/iaas/userdata/scripts/userdata.init.sh @@ -250,6 +250,34 @@ function disable_upgrades() { esac } +export -f disable_upgrades + +# try using dnf instead of yum if available +function sfYum() { + rc=-1 + if [[ -n $(which dnf) ]]; then + dnf "$@" && rc=$? + else + yum "$@" && rc=$? + fi + [ $rc -eq -1 ] && return 1 + return $rc +} +export -f sfYum + +function remove_setuptools() { + case $LINUX_KIND in + debian | ubuntu) + # If it's not there, nothing to do + sudo dpkg -l python3-setuptools || true + sudo dpkg -l python3-setuptools | grep ii && echo "python3-setuptools already there" + sudo dpkg -l python3-setuptools | grep ii && sudo apt-get remove -y python3-setuptools + ;; + redhat | fedora | centos) + sfYum remove -y python3-setuptools || true + esac +} +export -f remove_setuptools function no_daily_update() { case $LINUX_KIND in @@ -284,6 +312,7 @@ function no_daily_update() { ;; esac } +export -f no_daily_update # ---- Main export DEBIAN_FRONTEND=noninteractive @@ -310,6 +339,8 @@ drop_user create_user +remove_setuptools + no_daily_update touch /etc/cloud/cloud-init.disabled diff --git a/lib/backend/iaas/userdata/scripts/userdata.netsec.sh b/lib/backend/iaas/userdata/scripts/userdata.netsec.sh index dcef6ace1..8ec2064f4 100644 --- a/lib/backend/iaas/userdata/scripts/userdata.netsec.sh +++ b/lib/backend/iaas/userdata/scripts/userdata.netsec.sh @@ -108,7 +108,7 @@ function reset_fw() { sfRetry4 "sfApt update" || failure 207 "reset_fw(): failure running apt update" sfRetry4 "sfApt -y autoclean autoremove" || failure 210 "reset_fw(): failure running cleanup" sfRetry4 "sfApt install -q -y --no-install-recommends iptables" || failure 210 "reset_fw(): failure installing iptables" - sfRetry4 "sfApt install -q -y --no-install-recommends firewalld python3 python3-pip" || failure 211 "reset_fw(): failure installing firewalld" + sfRetry4 "sfApt install -q -y --no-install-recommends firewalld python3" || failure 211 "reset_fw(): failure installing firewalld" systemctl is-active ufw &> /dev/null && { echo "Stopping ufw" @@ -125,7 +125,7 @@ function reset_fw() { sfRetry4 "sfApt update" || failure 213 "reset_fw(): failure running apt update" sfRetry4 "sfApt -y autoclean autoremove" || failure 213 "reset_fw(): failure running cleanup" sfRetry4 "sfApt install -q -y --no-install-recommends iptables" || failure 214 "reset_fw(): failure installing iptables" - sfRetry4 "sfApt install -q -y --no-install-recommends firewalld python3 python3-pip" || failure 215 "reset_fw(): failure installing firewalld" + sfRetry4 "sfApt install -q -y --no-install-recommends firewalld python3" || failure 215 "reset_fw(): failure installing firewalld" systemctl is-active ufw &> /dev/null && { echo "Stopping ufw" @@ -146,7 +146,7 @@ function reset_fw() { sudo dnf config-manager -y --disable epel-modular sudo dnf config-manager -y --disable epel fi - sfRetry4 "sfYum install -q -y firewalld python3 python3-pip" || failure 220 "reset_fw(): failure installing firewalld" + sfRetry4 "sfYum install -q -y firewalld python3" || failure 220 "reset_fw(): failure installing firewalld" fi fi ;; From f8d97ac8f553842157d32688b940076031e2bf1a Mon Sep 17 00:00:00 2001 From: oscar Date: Thu, 2 Feb 2023 09:05:22 +0100 Subject: [PATCH 05/43] feat: tainted features --- lib/backend/resources/feature.go | 1 + lib/backend/resources/operations/clusterinstall.go | 4 +++- .../resources/operations/embeddedfeatures/remotedesktop.yml | 2 ++ lib/backend/resources/operations/feature.go | 6 ++++++ 4 files changed, 12 insertions(+), 1 deletion(-) diff --git a/lib/backend/resources/feature.go b/lib/backend/resources/feature.go index 114e1be93..f52884fc5 100755 --- a/lib/backend/resources/feature.go +++ b/lib/backend/resources/feature.go @@ -68,4 +68,5 @@ type FeatureSettings struct { SkipSizingRequirements bool // tells not to check sizing requirements AddUnconditionally bool // tells to not check before addition (no effect for check or removal) IgnoreSuitability bool // allows to not check if the feature is suitable for the target + IgnoreTainted bool } diff --git a/lib/backend/resources/operations/clusterinstall.go b/lib/backend/resources/operations/clusterinstall.go index 61d73516d..ed22ce50f 100755 --- a/lib/backend/resources/operations/clusterinstall.go +++ b/lib/backend/resources/operations/clusterinstall.go @@ -1013,7 +1013,9 @@ func (instance *Cluster) installRemoteDesktop(inctx context.Context, params data params["GuacamolePort"] = 63011 params["TomcatPort"] = 9009 - r, xerr := feat.Add(ctx, instance, params, resources.FeatureSettings{}) + r, xerr := feat.Add(ctx, instance, params, resources.FeatureSettings{ + IgnoreTainted: true, + }) xerr = debug.InjectPlannedFail(xerr) if xerr != nil { chRes <- result{xerr} diff --git a/lib/backend/resources/operations/embeddedfeatures/remotedesktop.yml b/lib/backend/resources/operations/embeddedfeatures/remotedesktop.yml index c02b380e0..06ac207b2 100644 --- a/lib/backend/resources/operations/embeddedfeatures/remotedesktop.yml +++ b/lib/backend/resources/operations/embeddedfeatures/remotedesktop.yml @@ -36,6 +36,8 @@ feature: - name: TomcatPort value: 9009 description: Port tomcat must use + - name: tainted + value: 1 install: bash: diff --git a/lib/backend/resources/operations/feature.go b/lib/backend/resources/operations/feature.go index b658b9d1e..04029fa4f 100755 --- a/lib/backend/resources/operations/feature.go +++ b/lib/backend/resources/operations/feature.go @@ -551,6 +551,12 @@ func (instance *Feature) Add(ctx context.Context, target resources.Targetable, v return nil, xerr } + if !s.IgnoreTainted { + if _, ok := myV["tainted"]; ok { + return nil, fail.NewError("sorry, this feature cannot be installed") + } + } + if !s.AddUnconditionally { results, xerr := instance.Check(ctx, target, v, s) xerr = debug.InjectPlannedFail(xerr) From cdcc7945f775148b713c83bad0734e96d502c8e4 Mon Sep 17 00:00:00 2001 From: oscar Date: Thu, 2 Feb 2023 09:49:09 +0100 Subject: [PATCH 06/43] bug: metadata corruption --- lib/backend/resources/operations/cluster.go | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/lib/backend/resources/operations/cluster.go b/lib/backend/resources/operations/cluster.go index 404a0a79f..ad1d94f64 100755 --- a/lib/backend/resources/operations/cluster.go +++ b/lib/backend/resources/operations/cluster.go @@ -1795,6 +1795,10 @@ func (instance *Cluster) Delete(ctx context.Context, force bool) (ferr fail.Erro xerr := instance.delete(cleanupContextFrom(ctx), clusterName) if xerr != nil { + logrus.WithContext(cleanupContextFrom(ctx)).Error(xerr) + if strings.Contains(xerr.Error(), "Alter") { + return fail.NewError("severe metadata corruption") + } return xerr } @@ -2093,8 +2097,6 @@ func (instance *Cluster) delete(inctx context.Context, cluName string) (_ fail.E logrus.WithContext(ctx).Infof("Network '%s' successfully deleted.", networkName) } - theID, _ := instance.GetID() - // --- Delete metadata --- xerr = instance.MetadataCore.Delete(cleanupContextFrom(ctx)) if xerr != nil { @@ -2102,6 +2104,7 @@ func (instance *Cluster) delete(inctx context.Context, cluName string) (_ fail.E } if ka, err := instance.Service().GetCache(ctx); err == nil { + theID, _ := instance.GetID() if ka != nil { if theID != "" { _ = ka.Delete(ctx, fmt.Sprintf("%T/%s", instance, theID)) From 304ddf5a3f024a72cbb5d13b6d4d748934ad178e Mon Sep 17 00:00:00 2001 From: oscar Date: Thu, 2 Feb 2023 15:44:44 +0100 Subject: [PATCH 07/43] bug: wrong image selection --- lib/backend/resources/operations/cluster.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/lib/backend/resources/operations/cluster.go b/lib/backend/resources/operations/cluster.go index ad1d94f64..474c9510e 100755 --- a/lib/backend/resources/operations/cluster.go +++ b/lib/backend/resources/operations/cluster.go @@ -22,6 +22,7 @@ import ( "embed" "encoding/json" "fmt" + "github.com/CS-SI/SafeScale/v22/lib/backend/resources/operations/consts" "math" mrand "math/rand" "reflect" @@ -1200,6 +1201,10 @@ func (instance *Cluster) AddNodes(ctx context.Context, cluName string, count uin hostImage = def.Image } + if hostImage == "" { + hostImage = consts.DEFAULTOS + } + svc := instance.Service() _, nodeDef.Image, xerr = determineImageID(ctx, svc, hostImage) if xerr != nil { From c87cc09541f0eccb1db6a19b96ec7f9c5b64ca60 Mon Sep 17 00:00:00 2001 From: oscar Date: Thu, 2 Feb 2023 15:46:19 +0100 Subject: [PATCH 08/43] doc: getting started docs --- doc/GETTING_STARTED.md | 5 +- doc/getstarted/amazon.png | Bin 0 -> 30241 bytes doc/getstarted/cloud.png | Bin 0 -> 11508 bytes doc/getstarted/cluster.png | Bin 0 -> 44863 bytes doc/getstarted/credentials.jpg | Bin 0 -> 206208 bytes doc/getstarted/region.png | Bin 0 -> 35461 bytes doc/getstarted/safescale.jpg | Bin 0 -> 67786 bytes doc/getstarted/started.md | 157 +++++++++++++++++++++++++++++++++ 8 files changed, 161 insertions(+), 1 deletion(-) create mode 100644 doc/getstarted/amazon.png create mode 100644 doc/getstarted/cloud.png create mode 100644 doc/getstarted/cluster.png create mode 100644 doc/getstarted/credentials.jpg create mode 100644 doc/getstarted/region.png create mode 100644 doc/getstarted/safescale.jpg create mode 100644 doc/getstarted/started.md diff --git a/doc/GETTING_STARTED.md b/doc/GETTING_STARTED.md index a6d9c0243..6e74043f6 100644 --- a/doc/GETTING_STARTED.md +++ b/doc/GETTING_STARTED.md @@ -52,4 +52,7 @@ To get private IP addresses of these masters : If you want to remove `""` around the results, you need to add `-r` option after `jq` command ## To list all nodes into a cluster -`safescale cluster inspect | jq '.result.nodes.nodes'` \ No newline at end of file +`safescale cluster inspect | jq '.result.nodes.nodes'` + +# Get started on AWS: +https://github.com/CS-SI/SafeScale/blob/master/doc/getstarted/started.md \ No newline at end of file diff --git a/doc/getstarted/amazon.png b/doc/getstarted/amazon.png new file mode 100644 index 0000000000000000000000000000000000000000..47c8495e95e98be6d684491a8af9fde5a6f9ee12 GIT binary patch literal 30241 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 literal 0 HcmV?d00001 diff --git a/doc/getstarted/cloud.png b/doc/getstarted/cloud.png new file mode 100644 index 0000000000000000000000000000000000000000..1d1ff76d0eea4d8f6ab12167eea135876eed9c25 GIT binary patch literal 11508 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 literal 0 HcmV?d00001 diff --git a/doc/getstarted/cluster.png b/doc/getstarted/cluster.png new file mode 100644 index 0000000000000000000000000000000000000000..a896dd3397d8bd154068478cf71379ce91b1cd5a GIT binary patch literal 44863 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 LnCVwvM8^F;FN$aw literal 0 HcmV?d00001 diff --git a/doc/getstarted/credentials.jpg b/doc/getstarted/credentials.jpg new file mode 100644 index 0000000000000000000000000000000000000000..67272cf408f3719ae55c929abcf4478ccd8deec5 GIT binary patch literal 206208 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
*Ue%kKN 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%0AQFkMP+y{hlw2w04=`Is(%02P`KAs6X+!7I=F6 zikN{__CgS7dYe2syL>uaXpGCLh}$ z1V9KlTkMa563d$UO;TY#`O=go*ecs!7uonpRNRum?lb0=+^0IYQ@U?1$JNT75_9Wh%a-GXud%u!WZiEh}nQHt=D{HK5%^2ez zF0-5T4oUNE_J{4O7^BNxIntd*A^hv||sqI={SI zy#7L}`n1lF;nl#OyL9qWktR+;RdI^}CV}1e<=V<7a&^M56hADmo%^2c zg2ekriwb|R*#OOSr(0Ig&-SdTDXiRB|G2s%_v7b3d}>tZ%q<`pY-v^6k*XBvd>TyR zOY^<6QVp;Vz`cy8L=!MG)4KPh4hqKgy7l#|xj9L1&}^^gPo;f)JZz3Ff2@V}sjc21 z))yXl7j*P~c5M|kHm`hntbHK#<2C`)-d@H|a-K3DjB zg67iUojVwB;=tZoyF?E_j9(R9Zp*^$LXOBb1Ws$nw;7jcwYF(0^d!UGe(GiMKgg%o zieo?hIXL4}@|0NkNxdex&4TB@!YNo0X{WGue@y2~OzVqEf4~vA49U|94Yh?hwOFVa z^?*f0Y1CKZ_#Sp#;!?{Hc16BC75lnH1J!kw+qmBxWtfq+X=$p#hbt5tzxV74~pt1PWyU%?=W>`Ikg70=M!96l>AqZ7OmN z?N|ps)QpD6UUP4OKW`eGYWD-kUtZNkt-VdnmHllq*VeVV8NmE(P=+PfG!fQ!<7_8d zv41EzmUn~mWlXEPi5e9pcd8#v)x-1q$YYS^ESRM1-X?C#)&>B#HZu-DAEhnB@cSmA zvw781BPAoci4y8f+#BZVidqzc-=Sz9Kq{b#? zeo2hJ*oRt|`SwfDKXxahhOb$E(pGQ9(C}nakOV_+f@o&OJv64F1-+{euoWTkW!g?x zzuxbUzc#XPL5l|uwatpJu>Bjt8I#3DXdq=ZbpqQi`TTkk-zeDBKMcc^OGd$2J$u>?xv|fMr^Qb<3mtJ`RP62~T|16E$C_M2EAaD$K+BefIBIygz z;L9F3S^UoSaeyKyF7eUoZ9O=?s&O?G(gt$0b0|h~;qSu(!oG}c`z4#%U-m+wlveyn zWl%_ChbYUj#$t5&N)P zrz(Zm7=O#{oR(&R*V*dv$nFXBAFrcHMENZGC6wqeqF+Y??b_nElw3HKzV5v!moa>! z>+2gvS$=z0%h%p)zq^v^Gezy?Tf_g6IprYnaVnoaHGrs=G_RzV9K4fBkNV$_;^ZIE=)wF`hl9fseXep&WYv`-4r`|@+LZMJ~ zv4r#a0j-~pJ1>L*Mx2}Y<9ZygSF~nQ3mw})>YWE(OoxcFUBQ0!B=Ji26!yvrSKf96 zJvODbMa!}GVf3S#{$FV1SwaRb^8-#tbR9-dbLoqpW>UGDYgcuFlaIvNDzvTRku3HM z#oq@!UnHi`ec#C2-K+rOW5Yt8Rh56UX*Mq0pLjUbr&hy2)=wh4Gye2srylIPPXlJN z*P8&;H_d0OrUefj!D4Q(5q#M^4)q>9iI#dhOJy?m(9w9ciM^t1TQ#Mu)8b@Noj-A& zcwY$1JM+lX!m`ALlgNLD>Y(DTq>6Wh?ppa*q2)Cmy6tCNQcP2AuGz_FW}T)R?@sv5 zvNEnGaJ~=At32CVriA$RecPvjK=t!A@n;&xW#rdM4JlUr3aF`m(I%Qjhaj;6N+!pi z6a{dVu$#!1zv5|Ak(r@bdl=0Qf*W~;mfNO}AeiZtwfuJNvfQ4q>ul_ulD6|&U}P-# zx1HHhDu6bfNj8DxhxPTp$4t3<9u_Z56NO`L({b>j94-rL+Rs+CqVDo*`5_-$JR!Tj zmw%zz&eGK6qg~e*=HgB0?)E{!uTqA@icRQ=u{Vz?DU7T8dh;sp*YF1k0ZXrUi zR`@T#ourVuJIh&?RrKgNyZpgLmYhsh7M4v%_+Uy-(lA3l4}c8W{Jf3bZg9-6e5rYG`?tk#Bda+C5kze`Z1;h zsK4rJ?fGccdwF@ZiY&?lly^cJef^T*6=nTM%bAhG$;NKRVmL3gK8kFjo)^#u&hiwHntB7Eo`bYc-iouU>E(zYNUVVH~wXSzJEX&*RLEqI$Y~WNtJ5` zRbYb8sXb0#F}7N-=N6=p&Q~7@vYZ>cLiQ7y=K8`m&fDh>HPhj5;N=W@HeTVbsdjcV z2W(dsCB{QnO9+7xFhbMKcU*Olfv!}&!-W{0w`ywtG{N5A&66=R*fYwZHF|hfLZkn^ z>$g~fge^{jryN=O3{DJPvN0Sy#T`%L2kTDrZi-fCY{4RXU)R=Ynit4>p;NvXvj_K6 z;-WnF`}-1Ff!4QvG<)mqgnrai;_KFlEOK|#78-c?@OWTyLp0OqB<^r40%?EKHiG0lp@A7O9{plI?r3TvWA)N;oS_IKXBy`t9w z`D5JNkb@l$zAR0b4baz?l$WdnSX>N?m#IqwIl=#hy|)gE>w)q;i9iSzAh^4`Cb+vp zU-PMf!Qjw0jQQdMQhD&>upZW1elH($AoGYJxcuxYK!Au-mQB@O05o)t!*pWHY zZeMKF-OO!IB{V(?Y5E&vZl?5zkz(DM+hJp60PJwoc`5^%|Dq5;tqt6WKEd8nyRX>V zS>VtdnOfS=md6>ze0pV{(&cF6fgAS&sHb@)aP<;3`%{o;#~wTXXQub7q`G>X1P(VA zMQI(Y$M&M+hd@Q*E4#|Tct;!epLwmFH31i|AWU`eKbiVbwH~gMuWMTfvLAE00?BJ= zD?B?k8zH9PPy=4>g($V!%$~t>e$eV7J?Nf?7EsQC$S1BvJ@DpDCGCe)aaePL4iF)z6kuc9!PKZ zdrm2I@YV(R#*8*M%CKIx^9nsqtud}%?hSvRKp=G&L|uQdcn)z4yt~&prrcjMiAN2q zUSAm_`-{TS++)N=&XJx!)WaXx>T)Rm&Nzqf-D9Bv{fGc}($!>z08m+c(Q|v3Ji=pt zQ)C%8Nf^7-zbnz4$H;q>^P>+Hzi6zWG6g=1dAjQz?k4v4@o>&Rt7V^3wB_-X1)L2Njo#$tH+F(?47l6w4Ah-DZ$87Ib|uH)2Ka`N%lyOI!4o%T zK?CA3P4&*KZx#7O&1yAQGqe6pmYWM1-7Bik{3w?AGGv(^a|POf%+QH&_ossKzru8& z(E7Ecb|U-4?t24FLrw4lK}+N?=SbKw7{5Xj%hwstKD`xbiP)Rqe-u;7pS135GvuhFg~8S^gg=l$?L9n1|haRQw@FeFBm>EcIH}v0e*U$c)f_;CQqhc(7w&rv~m8j z{q5p3c!z22Ns?V>(dAUVIybYDR8?$<_sAfM=%_=pbejvY?}M^~PNagCe7tX`D^d&$ zC7|m@HT0JE!1~m}>Mv~Pd<{EWHNe4IjOV8x)1`-YpoJO)Q7ecIH*Q^K2W?OKsQatsrRce+N0pjH|sQ!$)my|BVbi&`x&7Vel zZ!`&|(cW4|UUOti*BIkDQB-cs+F5J)f52|BsB0HG($M!81*hlYFG^387gD9C()W*b z;gH14uB_bd|A*fG&mY78Wl@u>|31D$;4jLvfyWB{h+jg?XI_h| z>R(EqC>3vWa$0!mC1gzNC8LK@Gkf#pyaWcOtDd)yQNfF`Ea^%I35zO3v%9UL%yN=z zd96U2Ci>PX)1PBwUug~0Q~?C{0RRA1ToKl@Mc+q~8wku5WA0~Q^Apml?f_mrt$8~6 z7P9Y&m}C@-NEA!|7cI-m5x1o#h;wBtrBWf@c@5FXQ=?1Q|e1?w+Kl8erj`3XB&Ab0Rl=7jRyF;*#-Oi3(I2oqXmpFPtmP< zLnJ)v={Pm{mCGsmvj=YMGs(*CXb({{G)W!H%c-@FF%>_Xj^he}HFaJUAFZ0Ecpoj! zo2;c@K506eevZtH)jD3rH~6lFrz&xjbMaND+g*jEJuM!#kW3MmRIp9)R%Z;Gx-+TE zoYJq+$~o)ZIwrk>YMTrjkqE~lsLZ=ztwDNiEEhdvY!;HVUCsD-1l|`Tb?g!KFUGi!TTHF6MMJ?n*ghqE56q zir5s(@W_^RB*S>8Qy`G2#rDIiY{&{FQ4Tndo<@pU)eTZtc3|M-h-%{+{)7S`vb8O^ z4p!8=hJVzRmd6{dc`e>7S4-f-@L3C!mmw90s~K+ZNmAD)9@xA$`3?L7LBXWKSs9j0 z8?^~i6yS47065NLdX__2zSry(4SnD>!df-%0=`Bi;wMxV^a(bd9cGhPSAEg_ zw*SSZ>ccn?PQEqxZE+jDK;bWnN}S1vK03g&?U=yny-;>4|Ci>-O)hti-O&c<$I`xjL4Ex^t9IyYX1DyoDp3y1K-x_d^ z`)W~DuL;Wly5aO%;LMlTJo{OZAhaw+q7b*Vb*tayD3)9$DrK~Oa~R7c`FEGk`4(KG z_$&&px%aMjaZ5b0{cw8WcFrQSR2^cr#y3yeyrBWhwZFC9+%hSNX8`TeQGMktvUQ+>2KunYYSFW7&p%s1;qiqxH;-%d% zq;Tl+N7YkU2M$~lpMZU%Mrp8ixzkWFela}yXjS*wdJkkRyQjV9y5q`8x5we+s@~jse9hWvgUaxDPdQ9L_)w_3JEzo6 z$ip@3Z7<;;cJY}y0FlJJi8dz5nH4^9CTK0jqIw?)9u{g>72L zCww|<@o@$lq-Uw=!tpPPz)Vj!+Vs@IPurhm8%CSlF+R{zZ~gP0s#fQpzd@+n7IGcv zQ~{485?fQ_DK;ab3eCe$_G=dS39?ecr-;EL< z7#k>CCerkzY03OC5W3WS57w2Ell2Jh%!)+=q`u5mbWo`1N@%tW&AZdK^MEeVN5bou zvW*3jxEf1G>@Ep!kg7&*gDsNT=wU?tV#;<_wJ?!WfL#^aiGyd$s;+)s!5yg z$M5g4vsR$0?z_B&Udpki5;tW8Sq>O_wGWrBSIN( zre$;@cFk5*kvu%dqA_&C&5T-B7d4HNK6`M|Q9c(quPStyXmL?0EVfh?Qg`kXC+r<< z#xCCwwkgukW%2#vkGJo&ua=y(fmCm(JMSMFAAD_t`T~MuTOEl#e78j#9^f86XFuU4 zkVFY+g|mgqNXLi}uS50s%4u1OxXY9x+0J95&fKS|R;Og^l>SPNtlQM$9>y9Ul5&s$ zuOL8GtEyatb)#?e4YSdfME6wU{em6cCuPX?mI-6a32A~l*5XNugQul{NQ8s%N+^4` zYxJ(2nHzTVH9NTCH}SOubyBcHt1tJsMBGNO+3KVJhB!o8J%0-dw`MZfzth|medUA@ zZSb0wLyjhoQ5*U0IyjaP@8TQ$$S8A5Hx$)4hMF79*k(LKkTxH zh{j@6UttO5g|!>*e}22C(aWIJTueoSCUY|&(AoCI6}K@Qe0$*rF2ed&0y7))p;x&M zLC26XT2Eg3fXn3b7DqA%Z5q~o=^WhLiQ)U`gF3#7aKWp6uJ;~b(~P?x9A&` zov_eGqTU`qXt2-jal`xDYHq%rywK2c^~`*6DrCu>$cY6aNw}o?i)r*-!Fv|>DIizf zCe)DZt0kpW?7b$q%XF?y$z`LcO9+k8u`w^R!Z}knAbY z_CeCxS%3JZ?;~(q(%wf{<$NyXvD?gOHIJLWtv1l4p|HvRdhzB-qLn%t=91LUA=o+Y zu1mLoF`~l4wm~H*va^WYupj(2_st8dc98w&IAf{BO(^5=DM2AF%@uvDX+(`LdzoC6 zc?yCq5FXq@Qho(7Nxyn&ry?B9cmPhd#wJ@I;*S(jjKsAK_GC-7+wGfkiTyzZ5m#&% zYEX5J_H)N{!N6cnHZlAk z?tXI%^2NGE7_7>)tWeTtbN;1ZqjJE2QLP?LqN^m_9se~O3~$2M4>;?03H=kmscPMi zrA`>VBEa#+DQAfIQ;KH%v+x90dJG#1{YtMxznsvK1SihT}4-A;9IiZ!5! zXNqGu!u18@gM_cEh)ZHCwx-#EuumXDqJ6_8ujOd^TN8niH@HnsRUa1FVQI(|TZLAKHUt8rgLjXwITU_uf!e$~hA8Se^e%@|8_8A) zlPnuqbo-!VV7FF;kdF^BPK5UPqoA$LGrhKkE+YdO6eP!=?2DUSruvYR>d9*2Zj^|; zbnRzd&~w%*tLj*70NFZdzitzX_<1c) z!_c7-vEG-xjma$C=KG`(&DwhDM;hqa7<|TApAX+29yeHYe##9Q9{nc#DReh)tl_Sm z(j>TakEyJ!i1o`zp54i~_+Ni8L0t3j}iKMk|0$?n3C!+it#KE0e20 zcg4*P5yTjdlMBwu2Ir@;QJ0V+DCJD*)IfJ6b5a8-k7x-SizR^*yR}yB%g?`uu<7DC z=iIf_%Tw|z1d3m~-j1Jz|8oWP67g?OY74VD&G?C{;d(SkhXcx}=(vUeVj+JizjEBKC3bqUBN+j`38OR3=dT3Xcr+g0~%^q4Flp~^pt zQdeb<*(YWEDQVluYnli$9CFnL(?`=D6fqf{4vS*2cx%Q`#1N(Ryo#x1j-d2I?gBE> z*5%w9U%v!k^wBU+`8+Ya6~A!ss+lp?aQeu?l>+ShNE1p>ZJhkgEVk2~q=!fP6?Cup z=dZOgq>*s{hk&})k;y5rk6}GfU6jv-$BgySi*kVZh;nAyA&Eq3KIlXjq^YU&d>bYs z*=m6n@hIMgFO2ZDx~@ka$GS`mK$+xk97rdF<_N#(U@7(~UmhA4m z6kG}8#d5hat);JybtT`MKzF>^R)m#mnZU*~FxhQQFd~d+Kjr8U zqwyyDhVmqEjX~eRdiUWm&Hnc;h;>o=00i07+(vp%kga09uPw2Y>$9ela_W(8iGZ*# zNi7+y_Emd43MXRAKm7Jn5s=LdUzdIpBUc1tIvCt4%Li5IkMAQ;yg|VSPc~wfC0z^e z+7HK9m0x1G#y@eopu!5UKI{A1yME*yO-;JMv$k&=wE=GJ zh+lTov!^xA-q;?**Ot_ub0}c8Si%C`G`s{C-`z)TdF#03<~TUH|NJfX$iIJ;!9Q!6 zQvz~$+GLcavq1h09z$~8 zZ&xp1n z^q&#!KM(<3X1~zs4P=taZEN{I;aQ@{4`hi)seiTlQa_Q-{YB|YoI9VmYTOj54dT4@ z`5)zJ{p-0d+P3;5C_>Rvwxxb#=wV zGZ_`evDz4Nw(4>gJEaorFnMb4RE3szq-+VBgzNsSA@dr7RVXsu&kbj@10@+nmYzji}OG8}V2`LD38ikF!PIz@3-`)_pQFoSY z_^jvFwd!H8@Db#7F^wv}edpbv`?}648J}!ExMHNbOaBQMKMQ~T z(%O4bL@A!Z8H48~UVlW2B6Ka}X5~MaC3nKw+PAl6flM7R|0i8-=>0#Fc?;xZ9u)ZI zNi4teFG|!o^cA-{@f6(pY@9K{USTFwGDH!ccfwh<(81jyl=&Pu>8J>+3{KUbq%Nea&2M$fSY<`UlW^`Q~185m6i*;hznDG>V>}~9T zrgy?`e1n6SZMr(G?O43AwI}ToGxXyUK>WB`+)jK{qwI_J`0r?%z=o;CV1|k&iuvJr zzE+6}Z@=u?(oBOP9*&|Yfh-F`sT7`9sXCH;0*hcF;QY^++HsfArSs69U z?3-t#vrXTvUxyS6i@6BI@?%D`sbxG$mvBFmQNAjP>C;q6DfbKanpeKY{KmxYt!u@M zswg>GMwV*|HAnXPU% zCoHR^4j7{Q1Xgh0oqGPVq2Wkn%JsiE*w4KV5wNNY|6v9)L|V=&HUe z|2$Hv!}7Er{yer;(@n+a7yng``vcS^KRzqV>7pwj&T*?!((+ahs_R^?|Kl%;(&Ef& zo~;>dU81^<{1=n0NFoG{%g+-}k;Ap(-OsF&Y(#y%j^cCTuzmMw#)QpqaLN1Hy%LjZ zRszReJkjSTV+xC=s)8^`%R)Kmed@rAp%l|k5D5mo%dJWbtl3Fpg<4*YX_a`?E8=3I zJA>ODjd=t|yTgIu5` z;&xNY)oG*C8w<)4(coHrqO$B^a1417q*l`a^A|ofR%#)K1VBEXi%hD|^{^aGp5LBg zoJYSmj%D?w;2?e^wm#(@%=cb;&E(iey-nS5`*ZA+K9@AKCB;1I1wtTaB6=XK77nt_R-kUwtnpP#UqCR`YBZv{rsZ-?Z^_A@&O1{P z2>iZhGP8OS*g*?F9<5yCrm~KbClbTfds$u7pGC@N- zV6>GlTJ`Bz3m5g|fR?M_;yG>R9xp{v6)PROd~a4lcmf$NeL!PC(*2j8(H5WjNJ>j5 zN7UPe^NH+)d#@j}(svA>4$j3w?Er4-6Ro`Bfn9t%ClbjavVBF#K4&mOPBfiNjyUbL zF^skav4TGD3?2Ith_|+DvnJ6ef$F&LA3el0h;sKq?o4be&!tH1rQqY&45>4F%{gL} z9K)^bCUvox;mUMMi$?S~qF;qsluf-EB}W<})0&$f!H@n@Tk&xxIlYor5LN3RGZw1L zX)8U>dHRCRwYvCr83@yHPg(|VLNe0y(>=j1bIT+oqO+!Eiv?jMYK!&5&FL9I|v#Jt3Xg}bzpzyu7mU!`PZq%&Sp!F2EJv_O~ zdTS0_&(lf9Og!TnD}#zAW3K!peAn9@-3**IX?7Pc)@`+C+h)VaAJR;#iWNw-rb7)l zoIz|o9;WTVX-V_I*j*$CV}rrK_p>-#c2}O zFRn!dG)O0eF14H<{cXdsT3cY-dz1VZn9s2md{x)ir2T z2Le&t;z2&;W!KzIZU5~rN~{K}M|O7A@ty$&{bCi-UleU#$h}=gzFO`^_G#*lOpybl zba2$L+&=6XEUPL2^hy~PfcXH!t|e_>U5-!6-PAGh7L)*Q+TBD@#bUAPNW}&nfC{hFJ!fL5Hmp_QEjR zB2@}jQFGeS(26nyO}(l2d#Qo~M~=YYZzUUo)k3pFh_4FdZ@7N!5SnNx3x&+O_HII> zgx%1 zm*_e*Vi67^*Q{p0+~9)L7N2cTjJc^78$eFjo3o=vfQ&fs%AI&Zrnig|qNBfwlhmB+ zRZiyv#81B)eC><(>ZHBMGVplOp-dVlO+$eHS}T>sJxE4X+;FY7&Z8X3+8-`ilzFX! z%?22b(F!fj-jYtJD8%{1h$ffWZ66A41t+<3{! z5MY+2%~_qDS8bg;Q~MeE z<472+=;8_^BKN$*`H7%{#=V0ujZ8bUxQoV|C*DbT2{#?P=X6zB4aFT7l^b`(vIY^p z6&tB7Bt@KOQc7yGxHv28XXGFb>_B>D1^ncy?p)IR3be`6C8%t56-k@tv$i@kk$Y@a z1n8?o`K3w=VTsz<(_@26yUm`IO67Qk)K7RHZUt@O+gly>5I3vyFRPv<1wr~h5&0w1 z;M-fbI-x@C1NWWng3+zt$gL{8Rn*FUgi}7m*nz1s(~FWNmd?ON^IOPSClpUoH2HW7o~1wnEb*UbND|ziMcD`@r(bZ#6Dq z-g#uX6c$%v<)}7+i@Jl!?0%N4%IjMayNojo!U{UOE$lpHoo%Z&@ch0f`}0KX;*z^r zKh!6@{VTW7@oaR8valVQZ2)2V_Jj%+YO!G@b~BU7_-IJv6kVKS!einrx>Y_sV@j_+R@v;< zpltA!OadD(bV6(`d{h`?=^m8%78VtLYX4gQP4`&`^L;C&X|hX8?WU~lUUSK$!~)0S zbjYM%xyQk?y#SB(p5ZkL%wK*#FL#q@ALKsvE-Ff0BVkncF?b^P1Rqu^4<^8T-T_l_cbvv2~ZkB&$U@{6~s|B2Z=;msnZjwJV z7BjClEaZsr+;-vNud!^G$3J-UDU2{k3&ihnQm(Xh^F==E8B2Q~>Kz!}4asd4oJd2C zOBn7uI1vqiVNVw8OmbBlmcSP>4MpOHpSAw5sT~D=_r3l7bfo9g3USoaLQwWuY{Uu$ z)PmiY4Y6RI`Q2Z(NjVc+Pe;Y=GP_z`br$r#drDwTB=aH*h4h& zGGXYE?Gs&zB^mT4(Ti}BxcB*>tsp>B@n|}+ST*CCK*I@lxR6iEq^@3h1+Y1DV9_rp zv6X#Dte2rCo}<`OnXUMSg6b<=y>*pjI*Qw6uB)~$-uhtL#y%_g6?i`Io4fG5e&IUV=`09UfxA*v*2W4MHx{M}UwuU#! z#Qhr@Rzf?zAB8NmY`SH-zbC1>p67_(3HI*6)h9MdCAP+Z7k9T&$wjQEm)Ug@bL|1A zINjyrG4{++g*H77m3i)ptf`FFP=#7QAyKC$<9qQuCl-?)va8Zh=az>%?S;dOZ^tAk zJRUzJ%jJr+PZ#R>I(4Mdhuy{ZpUSeDpn{H#gGCrkp9=_7;N4)G1iu_+&?4d13(8x6 zpr)1>8x4vM?+ZSX(6tdBU8j@z z*5A$gmA)e?I+WT8QTKuizSZ)THVV`O+r_ba!c*~-nWMA^iN+q3oA zlAU#`rs9d2oShp|^X-%Tv32T`w?4PFRE56UM>=7W6 z&%p%Fv%XVvqE%v&BG<_y;i8S(Z+k^;CYGx1uGKQJJ8GO7OI%K`vSl&gR%(otAMmp1 z^&F&#LeuzSZj44K2m4>om+WeVe6^PvAfi5y`1UJ!m4qY74w<(x<*U&@dgR%`0_hz% zJ2lU$InOl?$~|QF?1UxT?9*1j(d=tHjZ|`jhnHo~olwR7Q%cu(-*#Rbs|=5lVsGfw ze2y25qT>D(#Di7xjINZA)RBFwj8IV^6#?52YUf6#s<)h6>A1`eS z;>0D38w=R$)pQjvhEkF%wo53wRWᴕv1NNa7xm`d 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 literal 0 HcmV?d00001 diff --git a/doc/getstarted/region.png b/doc/getstarted/region.png new file mode 100644 index 0000000000000000000000000000000000000000..86092d2e81a8c7392f7fe2b0c1f73fc3c69045a3 GIT binary patch literal 35461 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

0^59|x>PV=ZxZDj13UzFGvmAFNG!$j~ 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 I{`>NO0R6DF^#A|> literal 0 HcmV?d00001 diff --git a/doc/getstarted/started.md b/doc/getstarted/started.md new file mode 100644 index 000000000..51496ec3a --- /dev/null +++ b/doc/getstarted/started.md @@ -0,0 +1,157 @@ + +# Create and configure a free Amazon account + +First, you have to create a free Amazon account , it wll require a mail address, and a credit card (it's still free). +https://portal.aws.amazon.com/billing/signup + +![SafeScale Infra](credentials.jpg "Credentials") + +When it's created, login to console interface and configure your region (top right, in header bar) + +![SafeScale Infra](region.png "Region") + +Next step is to create credential that Safescale will use (as shown below) +https://console.aws.amazon.com/iam/home?#security_credential + +# Install and configure Safescale + +First, you have to set Amazon accesskey in Safescale configuration file. +Get bellow example and fill with your access keys to create your own file "tenants.toml" + +```toml +[[tenants]] + client = "aws" + name = "MyFreeAWS" + [tenants.identity] + AccessKeyID = "" + SecretAccessKey = "" + Username = "" + Password = "" + [tenants.compute] + Region = "eu-west-3" + Zone = "eu-west-3a" + [tenants.objectstorage] + Type = "s3" + AccessKey = "" + SecretKey = "" + Region = "" +``` + +To get binaries : + +1. Get on github : https://github.com/CS-SI/SafeScale/releases +2. Compil : https://github.com/CS-SI/SafeScale/blob/master/doc/build +3. Compil with docker : After git checkout, run ./create-docker.sh -f (for that you need to install `docker-ce`) + +Steps to launch daemon safescaled : +- Copy binaries on your client +- Launch daemon `safescaled` one time to create config dir +- Create a tenant.toml into `$HOME/.safescale` ($HOME/.safescale/tenants.toml ou /etc/safescale/tenants.toml) +- (optionally) Add env and aliases on your `.bashrc` +- export SAFESCALE_METADATA_SUFFIX="your trigram" + +# Create my own cluster with Safescale + +First, we have to start Safescale demon and set tenants previously configured + +## List tenants +```bash +safescale tenant ls +{"result":[{"name":"MyFreeAWS","provider":"aws"}],"status":"success"} +``` + +## Set current tenant + +```bash +safescale tenant set MyFreeAWS +{"result":null,"status":"success"} +``` + +Create step by step, components for a host + +## This creates a machine named gw-mynetwork acting as a gateway : +```bash +safescale network create --cidr 192.168.11.0/24 --sizing "cpu<=2,ram<=7,disk<=100" mynetwork +{"result":{"cidr":"192.168.11.0/24","id":"vpc-08f44cf1b70ccd659","name":"mynetwork","subnets":["mynetwork"]},"status":"success"} +``` + +## This retrieves information from the new host gw-mynetwork: +```bash +safescale host inspect gw-mynetwork +{"result":{"cpu":1,"creation_date":"2023-02-02T13:24:25Z","id":"i-0ba47463f8a4fd0b7","kvs":{"CreationDate":"2023-02-02T13:24:25Z","DeclaredInBucket":"0-safescale-b3a35c904fcce656410ad9b42889328f-afraid","Image":"ami-0b575d704a68bb8f3","ManagedBy":"safescale","Name":"gw-mynetwork","Revision":"e47dc4179827cf6798b9d1d5c85cc22a2a61b71b","Template":"c5.large","clusterID":"","type":"gateway"},"labels":[],"name":"gw-mynetwork","password":"+2erJ,42x39LF;,)","private_ip":"192.168.11.96","private_key":"-----BEGIN RSA PRIVATE KEY-----\nMIIEogIBAAKCAQEAn9k22PFyoa5pZ9UJfLfswtK908O1VQc9QD/71LaYdlDwRnR/\nLM+zb7xh+L1QFjE/zaJpx800Q1YQ5qQtHOEanPDO/7oGRPwsgI9l9t5Yb2KlWHAP\nzwvlmAVJwpy05Jzn3VjuHNNTOpsU7u5vEE/VFmGuGQG7mVo3HdM4W9ky+Xf6LrVf\nEBxn/S74sqs5xwk2W9f/9T7JDVrG1OdgbdN6rEaFwoSb2mUupiliZD6ZEAb65Baz\nY7XR11bvPyhVnERXmHAfon4fFVNcJIe5lVbLCT5DZoteh+tmG/QofVsffR9qSM78\n/EA1EUVaJUR7tnQVEDg27l1VwXnMxpS3dwsa1QIDAQABAoIBAFFrrPpYEhG060/O\nPeTfMqQSAEsrduP2qgZeEQJKd+JcW+cnU9gZe8bAaA7xLyf+sgcmYUc6iRJ7dmRk\n3+3D43BpYKb1tFfTMz/QyxkyLE2gK6SegA7wemQy3V1ZwPJp0dj3gWIBanWBpOoH\nXV8rqtiZrLpkHZCBWW3BtwVh3wseeZoXwX7WAXBGECw9YuYtu+jyYa1qmqO0xi+a\nLV1naECLdA2z0/p8jd/4BFWnKBVKCyQ+rQe1AbSvM+Xcwv2Fxz1UbglrfjY79OER\n9KOlpNwmSQa7/EqjFLRkmyMWVNqXpXl517ZAWNyE9rUd2Ss5nMaySHHPz2CJNiio\nWGO6SMECgYEAzrJtoVbeVUSBk+ZuAi5RFj5e1fy4Ii3jaCd5ee1fadD+R68omW4U\n9vvGcDm9QFKuxGCgPso60QZq2e5B0h1TDz8dt3oxK7f6gR/oFLy0ei2c0lem2pr/\n0IhYwz/bAGZNfK6FSXGDzwMcPUXc88Lnbpxo9HFaDb6d+.....=\n-----END RSA PRIVATE KEY-----","public_ip":"13.37.68.78","ram":4,"state":2,"state_label":"Started","tags":[],"template":"c5.large"},"status":"success"} +``` +Then you can access the machine with SSH with the user 'safescale' and the SSH key displayed in 'private_key' + + +# Cluster creation + +## This creates a cluster of machines names mycluster +```bash +safescale cluster create -C Normal -F BOH --cidr 192.168.37.0/24 mycluster +{"result":{"admin_login":"cladm","admin_password":"/T;25P:59)Nk6KG)","cidr":"192.168.37.0/24","complexity":3,"complexity_label":"Normal","default_route_ip":"192.168.37.245","disabled_features":{},"endpoint_ip":"13.39.10.217","flavor":4,"flavor_label":"BOH","installed_features":{"features":[{"name":"docker"},{"name":"ansible"},{"name":"ansible-for-cluster"}]},"last_state":1,"last_state_label":"CS_NOMINAL","name":"mycluster","network_id":"vpc-0660bb4c985551f6a","nodes":{"masters":[{"id":"i-06281e96243885904","name":"mycluster-master-2","private_ip":"192.168.37.232"},{"id":"i-00c3247a9ec9249a9","name":"mycluster-master-1","private_ip":"192.168.37.90"}],"nodes":[{"id":"i-0c9a65b2145df8bd4","name":"mycluster-node-2","private_ip":"192.168.37.83"},{"id":"i-0ba2e4bf8d47a4a01","name":"mycluster-node-3","private_ip":"192.168.37.153"},{"id":"i-0a1948dc178cbebd0","name":"mycluster-node-1","private_ip":"192.168.37.55"}]},"primary_gateway_ip":"192.168.37.245","primary_public_ip":"13.39.10.217","remote_desktop":"no remote desktop available","subnet_id":"subnet-06f83149fd8e9f18a","tenants":"aws"},"status":"success"} +``` + +## To add one node to a cluster +```bash +safescale cluster expand mycluster +{"result":{"nodes":[{"cpu":2,"creation_date":"2023-02-02T14:25:10Z","id":"i-0eae2acb8840bfd77","kvs":[{"key":"CreationDate","value":"2023-02-02T14:25:10Z"},{"key":"DeclaredInBucket","value":"0-safescale-b3a35c904fcce656410ad9b42889328f-afraid"},{"key":"Revision","value":"e47dc4179827cf6798b9d1d5c85cc22a2a61b71b"},{"key":"Template","value":"c5.xlarge"},{"key":"clusterID","value":"a1876e8e-0c09-4182-bb6d-fedf2d254945"},{"key":"type","value":"node"},{"key":"Image","value":"ami-062f3e4f04af506a4"},{"key":"ManagedBy","value":"safescale"},{"key":"Name","value":"mycluster-node-6"}],"name":"mycluster-node-6","password":"rvPg,R4,65_3_J+8","private_ip":"192.168.37.54","private_key":"-----BEGIN RSA PRIVATE KEY-----\nMIIEpAIBAAKCAQEAsK2XujbXWeywHzimsJFWz+IwfBkK5+dW82KkJ+UVJFAWTkUo\n9UTE6Fus73/XKJg7ItcBUR028hbzKulfCP8Oa0dw0wngoBwASh0EK+aWT92wPTXQ\nPTTZCzMMGDG3wTCf6EKzv4d6ChBPbJVVcLP0yMg23ICS3g3Hsk3NrwLjgVWf6gHi\n5Jzy/Sla/cYXYpMLa4FowXnK+UuL+waDyMNFmbQV/VYnjWHMoA4NHmqlKeveSgas\nNbeQs/1dYrqz1q/qBqEyjNid78pq/qG04LBbK4GnRGLAFukjb+KG6JCOHz/bqOAy\n71i0NHYqTjIrEAlkLRi2jUq1X6O4HJ3HKoXPOwIDAQABAoIBAQCM27muEu8amKPK\nIIZ1G0rVLoZtSiHxxfUC0lACJpf2fYtrF6SR9yPuBLkZsRi/Gq97FWPNYbdex4FT\nYwAL0h2S1kBTYPqfa/OnIv8iaRLJ1fsesfq18Z5hWW95EppoAfZbXGKmfsKDp4FL\nFrwpwK+WLFng7vko5F+j/nfP4kOz5lY3rHg2xcjCuYmI4qsnUMvjHfShXC0WDiHK\nG9cyUPxak1k1FxFHNYBDPY67P8iDY72I2UXBzvf1F2j9ilhFfH/4/+PJRhnICEXF\nwsT6usJO2ygju2EJq9+pwwF4F85Y3JJps3TlFfuPUmzQwfbWzIE6i6reylUopN7e\nQ931aRzRAoGBAOSyCZRoinVh7W852XbsNih0PIz4XSjluqjR71FQmD/G+n5Xcx70\nDe2875k7WFIhY9PX5UXLNU/i6VvIEqk94Bazxz0kepqCi9PihaxW0oScRYusUaRN\nI2GJbcMvOLAWHMtbGduhNnVZgKboms5cSMgDx5BJ7u1bHJlr0N9kAZKHAoGBAMXF\nq6i1SfIazmzYluoVKBVc4ENG0d/AHwNv+Aoiwjp+wihltil2rKSMwshj1pmwQCaG\n6Qhynm00wdJAIFXauehdWMsohutSCEPs8a2ioUjliZ+GIw5+2rYGi3F8K94SVXGx\n9fikz9KWzogxTLwNi1KayRe1lH+ZFMb5TMgjTGatAoGAVpVBIzrhEMfeiLmyJ2AO\nsQow0n5FZvJy1O+GV5bXzW2b8LFTGGj1zQg2/iCFs7KIhO+8Ecx5hqE2EFWTGxgd\n+vpdeDyTXmQGZFXinfjRAvvXKKY40qeRuZ+6OqdqIuB8TlFTXN+QKqWUG5z83xv5\nQiCMMYiMOLjB/yPelHTcU4kCgYEAvC9TH70hF5YaRcfyEdr/wR.....==\n-----END RSA PRIVATE KEY-----","ram":8,"state":2,"state_label":"Started","template":"c5.xlarge"}]},"status":"success"} +``` + +## To delete one node from a cluster +```bash +safescale cluster shrink mycluster +Are you sure you want to delete 1 node from Cluster mycluster ? (y/N): y +{"result":null,"status":"success"} +``` + +## To list all masters from a cluster +```bash +safescale cluster inspect mycluster | jq '.result.nodes.masters' +[ + { + "id": "i-06281e96243885904", + "name": "mycluster-master-2", + "private_ip": "192.168.37.232" + }, + { + "id": "i-00c3247a9ec9249a9", + "name": "mycluster-master-1", + "private_ip": "192.168.37.90" + } +] +``` + +## To get private IP addresses of these masters : +```bash +safescale cluster inspect mycluster | jq '.result.nodes.masters[].private_ip' +"192.168.37.232" +"192.168.37.90" +``` + +If you want to remove `""` around the results, you need to add `-r` option after `jq` command +```bash +safescale cluster inspect mycluster | jq -r '.result.nodes.masters[].private_ip' +192.168.37.232 +192.168.37.90 +``` +## To list all nodes from a cluster +```bash +safescale cluster inspect mycluster | jq '.result.nodes.nodes' +[ + { + "id": "i-0c9a65b2145df8bd4", + "name": "mycluster-node-2", + "private_ip": "192.168.37.83" + }, + { + "id": "i-0ba2e4bf8d47a4a01", + "name": "mycluster-node-3", + "private_ip": "192.168.37.153" + }, + { + "id": "i-0a1948dc178cbebd0", + "name": "mycluster-node-1", + "private_ip": "192.168.37.55" + } +] +``` From 1ed720f6bbe4d14a27cfa40a925784cab9759298 Mon Sep 17 00:00:00 2001 From: oscar Date: Fri, 3 Feb 2023 15:47:46 +0100 Subject: [PATCH 09/43] chores: changed build scripts --- build/Dockerfile | 15 +++++++++++++++ build/Dockerfile2 | 15 +++++++++++++++ build/releaseit.sh | 8 ++++---- 3 files changed, 34 insertions(+), 4 deletions(-) diff --git a/build/Dockerfile b/build/Dockerfile index 88960b3b9..ca1f139d8 100644 --- a/build/Dockerfile +++ b/build/Dockerfile @@ -33,6 +33,9 @@ RUN wget --no-check-certificate https://github.com/google/protobuf/releases/down && ln -s /usr/local/protoc/bin/protoc /usr/local/bin \ && rm /tmp/protoc-$PROTOVERSION-linux-x86_64.zip +RUN wget --no-check-certificate https://github.com/grpc/grpc-web/releases/download/1.3.1/protoc-gen-grpc-web-1.3.1-linux-x86_64 -O /usr/bin/protoc-gen-grpc-web \ +&& chmod ugo+x /usr/bin/protoc-gen-grpc-web + FROM base AS builder WORKDIR /tmp @@ -43,11 +46,18 @@ WORKDIR /tmp RUN apt-get install -y --allow-unauthenticated --no-install-recommends \ locales \ sudo \ +locate \ build-essential \ make \ +wget \ curl \ +unzip \ +vim \ git \ jq \ +iproute2 \ +iputils-ping \ +openssh-server \ python3 \ python3-pip \ && apt-get autoclean -y \ @@ -61,6 +71,9 @@ ENV LANGUAGE en_US:en ENV LC_ALL en_US.UTF-8 RUN python3 -c "print('testing UTF8: 👌')" +RUN wget --no-check-certificate https://github.com/grpc/grpc-web/releases/download/1.3.1/protoc-gen-grpc-web-1.3.1-linux-x86_64 -O /usr/bin/protoc-gen-grpc-web \ +&& chmod ugo+x /usr/bin/protoc-gen-grpc-web + ENV SHELL /bin/bash ENV GOPATH /go COPY build-safescale.sh /opt/build-safescale.sh @@ -100,3 +113,5 @@ COPY --from=builder /exported/safescaled /exported/safescaled COPY --from=builder /exported/safescale /exported/safescale COPY --from=builder /exported/go.mod /exported/go.mod COPY --from=builder /exported/go.sum /exported/go.sum +COPY --from=builder /exported/safescale_pb.js /exported/safescale_pb.js +COPY --from=builder /exported/safescale_grpc_web_pb.js /exported/safescale_grpc_web_pb.js diff --git a/build/Dockerfile2 b/build/Dockerfile2 index ce192f6f9..b24c8eb23 100644 --- a/build/Dockerfile2 +++ b/build/Dockerfile2 @@ -35,6 +35,9 @@ RUN wget --no-check-certificate https://github.com/google/protobuf/releases/down && ln -s /usr/local/protoc/bin/protoc /usr/local/bin \ && rm /tmp/protoc-$PROTOVERSION-linux-x86_64.zip +RUN wget --no-check-certificate https://github.com/grpc/grpc-web/releases/download/1.3.1/protoc-gen-grpc-web-1.3.1-linux-x86_64 -O /usr/bin/protoc-gen-grpc-web \ +&& chmod ugo+x /usr/bin/protoc-gen-grpc-web + FROM base AS builder WORKDIR /tmp @@ -45,11 +48,18 @@ WORKDIR /tmp RUN apt-get install -y --allow-unauthenticated --no-install-recommends \ locales \ sudo \ +locate \ build-essential \ make \ +wget \ curl \ +unzip \ +vim \ git \ jq \ +iproute2 \ +iputils-ping \ +openssh-server \ python3 \ python3-pip \ && apt-get autoclean -y \ @@ -63,6 +73,9 @@ ENV LANGUAGE en_US:en ENV LC_ALL en_US.UTF-8 RUN python3 -c "print('testing UTF8: 👌')" +RUN wget --no-check-certificate https://github.com/grpc/grpc-web/releases/download/1.3.1/protoc-gen-grpc-web-1.3.1-linux-x86_64 -O /usr/bin/protoc-gen-grpc-web \ +&& chmod ugo+x /usr/bin/protoc-gen-grpc-web + ENV SHELL /bin/bash ENV GOPATH /go COPY build-safescale2.sh /opt/build-safescale.sh @@ -102,3 +115,5 @@ COPY --from=builder /exported-$GOOSX-$GOARCHX/safescaled /exported-$GOOSX-$GOARC COPY --from=builder /exported-$GOOSX-$GOARCHX/safescale /exported-$GOOSX-$GOARCHX/safescale COPY --from=builder /exported-$GOOSX-$GOARCHX/go.mod /exported-$GOOSX-$GOARCHX/go.mod COPY --from=builder /exported-$GOOSX-$GOARCHX/go.sum /exported-$GOOSX-$GOARCHX/go.sum +COPY --from=builder /exported-$GOOSX-$GOARCHX/safescale_pb.js /exported-$GOOSX-$GOARCHX/safescale_pb.js +COPY --from=builder /exported-$GOOSX-$GOARCHX/safescale_grpc_web_pb.js /exported-$GOOSX-$GOARCHX/safescale_grpc_web_pb.js diff --git a/build/releaseit.sh b/build/releaseit.sh index 39fb308db..15ad9b8c2 100644 --- a/build/releaseit.sh +++ b/build/releaseit.sh @@ -11,7 +11,7 @@ GOOSX=windows GOARCHX=amd64 ./create-docker2.sh -f docker system prune -a -f mv ./exported-windows-amd64/safescale ./exported-windows-amd64/safescale.exe mv ./exported-windows-amd64/safescaled ./exported-windows-amd64/safescaled.exe -tar -czf safescale-$1-linux-amd64.tar.gz ./exported/sa* -tar -czf safescale-$1-linux-arm.tar.gz ./exported-linux-arm/sa* -tar -czf safescale-$1-darwin-arm64.tar.gz ./exported-darwin-arm64/sa* -tar -czf safescale-$1-windows-amd64.tar.gz ./exported-windows-amd64/sa* +tar -czf safescale-$1-linux-amd64.tar.gz -C ./exported/safescale ./exported/safescaled . +tar -czf safescale-$1-linux-arm.tar.gz -C ./exported-linux-arm/safescale ./exported-linux-arm/safescaled . +tar -czf safescale-$1-darwin-arm64.tar.gz -C ./exported-darwin-arm64/safescale ./exported-darwin-arm64/safescaled . +tar -czf safescale-$1-windows-amd64.tar.gz -C ./exported-windows-amd64/sa*.exe . From ebc1144cf3825ab9405a868df11740d4febaa01d Mon Sep 17 00:00:00 2001 From: oscar Date: Fri, 3 Feb 2023 15:49:20 +0100 Subject: [PATCH 10/43] chores: build with go 1.20 --- .github/workflows/go-generics.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/go-generics.yml b/.github/workflows/go-generics.yml index 369eb2543..5a53acd01 100644 --- a/.github/workflows/go-generics.yml +++ b/.github/workflows/go-generics.yml @@ -24,7 +24,7 @@ jobs: strategy: matrix: - go: [ 1.18.4, 1.19 ] + go: [ 1.18.4, 1.19, 1.20 ] tags: [ releasetags, debug, tunnel, generics ] runs-on: ubuntu-latest From 60a158b43a346f20dec4441129ca4a08affdd771 Mon Sep 17 00:00:00 2001 From: oscar Date: Fri, 3 Feb 2023 15:54:23 +0100 Subject: [PATCH 11/43] bug: detect problems installing ansible --- .../operations/embeddedfeatures/ansible.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/lib/backend/resources/operations/embeddedfeatures/ansible.yml b/lib/backend/resources/operations/embeddedfeatures/ansible.yml index 6020d8de5..edfb9266f 100644 --- a/lib/backend/resources/operations/embeddedfeatures/ansible.yml +++ b/lib/backend/resources/operations/embeddedfeatures/ansible.yml @@ -72,18 +72,18 @@ feature: export DEBIAN_FRONTEND=noninteractive sfRetry "sfApt update" apt-add-repository --yes --update ppa:ansible/ansible - sfRetry "sfApt update" - sfRetry "sfApt install -y ansible" - sfRetry "sfApt install -y git" + sfRetry "sfApt update" || sfFail 192 + sfRetry "sfApt install -y ansible" || sfFail 192 + sfRetry "sfApt install -y git" || sfFail 192 ;; debian) export DEBIAN_FRONTEND=noninteractive sfRetry "sfApt update" echo "deb http://ppa.launchpad.net/ansible/ansible/ubuntu trusty main" >> /etc/apt/sources.list sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 93C4A3FD7BB9C367 -y - sfRetry "sfApt update" - sfRetry "sfApt install -y ansible" - sfRetry "sfApt install -y git" + sfRetry "sfApt update" || sfFail 192 + sfRetry "sfApt install -y ansible" || sfFail 192 + sfRetry "sfApt install -y git" || sfFail 192 ;; centos|redhat|rhel) if [[ -n $(which dnf) ]]; then From 3c5822ea6b715579dfb684a68f526aba2fda8dd1 Mon Sep 17 00:00:00 2001 From: oscar Date: Fri, 3 Feb 2023 20:21:31 +0100 Subject: [PATCH 12/43] chores: changed build scripts --- build/build-safescale.sh | 4 +++- build/build-safescale2.sh | 4 +++- build/releaseit.sh | 22 ++++++++++++++-------- 3 files changed, 20 insertions(+), 10 deletions(-) mode change 100644 => 100755 build/releaseit.sh diff --git a/build/build-safescale.sh b/build/build-safescale.sh index edc202388..a367325ad 100755 --- a/build/build-safescale.sh +++ b/build/build-safescale.sh @@ -85,10 +85,12 @@ echo "Export" export CIBIN=/exported mkdir -p /exported -CIBIN=/exported make installci +CIBIN=/exported make installci force_sdk_js force_sdk_python [ $? -ne 0 ] && echo "Export failure" && exit 1 cp ${WRKDIR}/SafeScale/go.mod /exported cp ${WRKDIR}/SafeScale/go.sum /exported +cp ${WRKDIR}/SafeScale/lib/protocol/javascript/* /exported +cp ${WRKDIR}/SafeScale/lib/protocol/python3/* /exported exit 0 diff --git a/build/build-safescale2.sh b/build/build-safescale2.sh index ff17d8772..a11f3e120 100755 --- a/build/build-safescale2.sh +++ b/build/build-safescale2.sh @@ -88,10 +88,12 @@ echo "Export" export CIBIN=/exported-$GOOS-$GOARCH mkdir -p /exported-$GOOS-$GOARCH -CIBIN=/exported-$GOOS-$GOARCH make installci +CIBIN=/exported-$GOOS-$GOARCH make installci force_sdk_js force_sdk_python [ $? -ne 0 ] && echo "Export failure" && exit 1 cp ${WRKDIR}/SafeScale/go.mod /exported-$GOOS-$GOARCH cp ${WRKDIR}/SafeScale/go.sum /exported-$GOOS-$GOARCH +cp ${WRKDIR}/SafeScale/lib/protocol/javascript/* /exported-$GOOS-$GOARCH +cp ${WRKDIR}/SafeScale/lib/protocol/python3/* /exported-$GOOS-$GOARCH exit 0 diff --git a/build/releaseit.sh b/build/releaseit.sh old mode 100644 new mode 100755 index 15ad9b8c2..cfccfa6df --- a/build/releaseit.sh +++ b/build/releaseit.sh @@ -1,17 +1,23 @@ #! /bin/bash -x +if [ -z "$1" ]; then + echo "Must specify a version number ..." + exit 1 +fi + +export BRANCH_NAME=develop docker system prune -a -f -./create-docker.sh -f +BRANCH_NAME=develop ./create-docker.sh -f docker system prune -a -f -GOOSX=darwin GOARCHX=arm64 ./create-docker2.sh -f +BRANCH_NAME=develop GOOSX=darwin GOARCHX=arm64 ./create-docker2.sh -f docker system prune -a -f -GOOSX=linux GOARCHX=arm ./create-docker2.sh -f +BRANCH_NAME=develop GOOSX=linux GOARCHX=arm ./create-docker2.sh -f docker system prune -a -f -GOOSX=windows GOARCHX=amd64 ./create-docker2.sh -f +BRANCH_NAME=develop GOOSX=windows GOARCHX=amd64 ./create-docker2.sh -f docker system prune -a -f mv ./exported-windows-amd64/safescale ./exported-windows-amd64/safescale.exe mv ./exported-windows-amd64/safescaled ./exported-windows-amd64/safescaled.exe -tar -czf safescale-$1-linux-amd64.tar.gz -C ./exported/safescale ./exported/safescaled . -tar -czf safescale-$1-linux-arm.tar.gz -C ./exported-linux-arm/safescale ./exported-linux-arm/safescaled . -tar -czf safescale-$1-darwin-arm64.tar.gz -C ./exported-darwin-arm64/safescale ./exported-darwin-arm64/safescaled . -tar -czf safescale-$1-windows-amd64.tar.gz -C ./exported-windows-amd64/sa*.exe . +tar -czf safescale-$1-linux-amd64.tar.gz -C ./exported . +tar -czf safescale-$1-linux-arm.tar.gz -C ./exported-linux-arm . +tar -czf safescale-$1-darwin-arm64.tar.gz -C ./exported-darwin-arm64 . +tar -czf safescale-$1-windows-amd64.tar.gz -C ./exported-windows-amd64 . From d6b2a5b67e2d72f4b97d15e181ea332e439d1aa6 Mon Sep 17 00:00:00 2001 From: oscar Date: Mon, 6 Feb 2023 10:06:51 +0100 Subject: [PATCH 13/43] feat: grpc-web experiments feat: web-experiments --- cli/safescaled/main.go | 121 +++++++++++++--- go.mod | 5 + go.sum | 241 +++++++++++++++++++++++++++++++ lib/utils/heartbeat/heartbeat.go | 6 +- lib/utils/valid/consts.go | 1 + 5 files changed, 350 insertions(+), 24 deletions(-) diff --git a/cli/safescaled/main.go b/cli/safescaled/main.go index 0846c9a9c..a05e2b857 100644 --- a/cli/safescaled/main.go +++ b/cli/safescaled/main.go @@ -18,7 +18,9 @@ package main import ( "fmt" + "github.com/CS-SI/SafeScale/v22/lib/utils/valid" "net" + "net/http" "os" "os/signal" "path" @@ -26,6 +28,7 @@ import ( "strconv" "strings" "syscall" + "time" "github.com/oscarpicas/covertool/pkg/exit" "github.com/sirupsen/logrus" @@ -33,6 +36,8 @@ import ( "google.golang.org/grpc" "google.golang.org/grpc/reflection" + "github.com/improbable-eng/grpc-web/go/grpcweb" + _ "github.com/CS-SI/SafeScale/v22/lib/backend" "github.com/CS-SI/SafeScale/v22/lib/backend/iaas" "github.com/CS-SI/SafeScale/v22/lib/backend/listeners" @@ -105,31 +110,29 @@ func work(c *cli.Context) { if err != nil { logrus.Fatalf("failed to listen: %v", err) } - s := grpc.NewServer() - logrus.Infoln("Registering services") - protocol.RegisterBucketServiceServer(s, &listeners.BucketListener{}) - protocol.RegisterClusterServiceServer(s, &listeners.ClusterListener{}) - protocol.RegisterHostServiceServer(s, &listeners.HostListener{}) - protocol.RegisterFeatureServiceServer(s, &listeners.FeatureListener{}) - protocol.RegisterImageServiceServer(s, &listeners.ImageListener{}) - protocol.RegisterJobServiceServer(s, &listeners.JobManagerListener{}) - protocol.RegisterNetworkServiceServer(s, &listeners.NetworkListener{}) - protocol.RegisterSubnetServiceServer(s, &listeners.SubnetListener{}) - protocol.RegisterSecurityGroupServiceServer(s, &listeners.SecurityGroupListener{}) - protocol.RegisterShareServiceServer(s, &listeners.ShareListener{}) - protocol.RegisterSshServiceServer(s, &listeners.SSHListener{}) - protocol.RegisterTemplateServiceServer(s, &listeners.TemplateListener{}) - protocol.RegisterTenantServiceServer(s, &listeners.TenantListener{}) - protocol.RegisterVolumeServiceServer(s, &listeners.VolumeListener{}) - protocol.RegisterLabelServiceServer(s, &listeners.LabelListener{}) + s := createGrpcServer() + ns, xerr := buildGRPCWebServer(s) + if xerr != nil { + logrus.Fatalf("failed to build grpcwebshit: %v", xerr) + } + + go func() { + nl, err := net.Listen("tcp", ":50052") + if err != nil { + logrus.Fatalf("failed to listen: %v", err) + } + + err = ns.Serve(nl) + if err != nil { + logrus.Fatalf("failed to serve: %v", err) + return + } + }() // enable heartbeat go heartbeat.RunHeartbeatService(":10102") - // Register reflection service on gRPC server. - reflection.Register(s) - // Track goroutines startTrack() defer endTrack() @@ -151,6 +154,84 @@ func work(c *cli.Context) { } } +// buildGRPCWebServer wraps a *grpc.Server to handle grpcweb +func buildGRPCWebServer(grpcServer *grpc.Server) (*http.Server, fail.Error) { + if valid.IsNil(grpcServer) { + return nil, fail.InvalidParameterCannotBeNilError("grpcServer") + } + + options := []grpcweb.Option{ + grpcweb.WithCorsForRegisteredEndpointsOnly(false), + grpcweb.WithOriginFunc(func(string) bool { + return true + }), + } + + options = append(options, + grpcweb.WithWebsockets(true), + ) + options = append( + options, + grpcweb.WithWebsocketPingInterval(5*time.Second), + ) + + wrappedGrpc := grpcweb.WrapServer(grpcServer, options...) + + serveMux := http.NewServeMux() + ourHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + if r.ProtoMajor == 2 { + wrappedGrpc.ServeHTTP(w, r) + return + } + + if wrappedGrpc.IsGrpcWebRequest(r) || wrappedGrpc.IsAcceptableGrpcCorsRequest(r) { + origins, ok := r.Header["Origin"] + if ok && len(origins) > 0 { + w.Header().Set("Access-Control-Allow-Origin", strings.Join(origins, ",")) + w.Header().Set("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE") + w.Header().Set("Access-Control-Allow-Headers", "Accept, Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token, Authorization, X-User-Agent, X-Grpc-Web") + w.Header().Set("grpc-status", "") + w.Header().Set("grpc-message", "") + wrappedGrpc.ServeHTTP(w, r) + return + } + } + + // Fall back to other servers. + http.DefaultServeMux.ServeHTTP(w, r) + }) + serveMux.Handle("/", ourHandler) + + return &http.Server{ + Handler: serveMux, + }, nil +} + +func createGrpcServer() *grpc.Server { + s := grpc.NewServer() + + logrus.Infoln("Registering services") + protocol.RegisterBucketServiceServer(s, &listeners.BucketListener{}) + protocol.RegisterClusterServiceServer(s, &listeners.ClusterListener{}) + protocol.RegisterHostServiceServer(s, &listeners.HostListener{}) + protocol.RegisterFeatureServiceServer(s, &listeners.FeatureListener{}) + protocol.RegisterImageServiceServer(s, &listeners.ImageListener{}) + protocol.RegisterJobServiceServer(s, &listeners.JobManagerListener{}) + protocol.RegisterNetworkServiceServer(s, &listeners.NetworkListener{}) + protocol.RegisterSubnetServiceServer(s, &listeners.SubnetListener{}) + protocol.RegisterSecurityGroupServiceServer(s, &listeners.SecurityGroupListener{}) + protocol.RegisterShareServiceServer(s, &listeners.ShareListener{}) + protocol.RegisterSshServiceServer(s, &listeners.SSHListener{}) + protocol.RegisterTemplateServiceServer(s, &listeners.TemplateListener{}) + protocol.RegisterTenantServiceServer(s, &listeners.TenantListener{}) + protocol.RegisterVolumeServiceServer(s, &listeners.VolumeListener{}) + protocol.RegisterLabelServiceServer(s, &listeners.LabelListener{}) + + // Register reflection service on gRPC server. + reflection.Register(s) + return s +} + // assembleListenString constructs the listen string we will use in net.Listen() func assembleListenString(c *cli.Context) string { // Get listen from parameters diff --git a/go.mod b/go.mod index e66abfa54..4e660c70f 100644 --- a/go.mod +++ b/go.mod @@ -18,6 +18,7 @@ require ( github.com/golang/protobuf v1.5.2 github.com/google/gofuzz v1.2.0 github.com/gophercloud/gophercloud v0.25.0 + github.com/improbable-eng/grpc-web v0.15.0 github.com/itchyny/gojq v0.12.9 github.com/json-iterator/go v1.1.12 github.com/magiconair/properties v1.8.7 @@ -67,6 +68,7 @@ require ( github.com/cenkalti/backoff/v4 v4.1.3 // indirect github.com/cespare/xxhash/v2 v2.1.2 // indirect github.com/cpuguy83/go-md2man/v2 v2.0.1 // indirect + github.com/desertbit/timer v0.0.0-20180107155436-c41aec40b27f // indirect github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect github.com/dustin/go-humanize v1.0.0 // indirect github.com/fsnotify/fsnotify v1.5.1 // indirect @@ -84,6 +86,7 @@ require ( github.com/itchyny/timefmt-go v0.1.4 // indirect github.com/jmespath/go-jmespath v0.4.0 // indirect github.com/keybase/go-ps v0.0.0-20190827175125-91aafc93ba19 // indirect + github.com/klauspost/compress v1.11.7 // indirect github.com/kr/fs v0.1.0 // indirect github.com/mattn/go-runewidth v0.0.14 // indirect github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect @@ -101,6 +104,7 @@ require ( github.com/prometheus/common v0.33.0 // indirect github.com/prometheus/procfs v0.7.3 // indirect github.com/rivo/uniseg v0.4.3 // indirect + github.com/rs/cors v1.7.0 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/shirou/gopsutil v2.20.9+incompatible // indirect github.com/shopspring/decimal v1.2.0 // indirect @@ -118,4 +122,5 @@ require ( gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect k8s.io/apimachinery v0.23.5 // indirect + nhooyr.io/websocket v1.8.6 // indirect ) diff --git a/go.sum b/go.sum index c6aa480d9..60a57901a 100644 --- a/go.sum +++ b/go.sum @@ -55,6 +55,7 @@ github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/DATA-DOG/go-sqlmock v1.3.3/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM= +github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= github.com/Masterminds/goutils v1.1.1 h1:5nUrii3FMTL5diU80unEVvNevw1nH4+ZV4DSLVJLSYI= github.com/Masterminds/goutils v1.1.1/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU= github.com/Masterminds/semver/v3 v3.2.0 h1:3MEsd0SM6jqZojhjLWWeBY+Kcjy9i6MQAeY7YgDP83g= @@ -66,10 +67,14 @@ github.com/PuerkitoBio/purell v1.0.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbt github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= github.com/PuerkitoBio/urlesc v0.0.0-20160726150825-5bd2802263f2/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= +github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo= +github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= github.com/StackExchange/wmi v0.0.0-20190523213315-cbe66965904d h1:G0m3OIz70MZUWq3EgK3CesDbo8upS2Vm9/P3FtgI+Jk= github.com/StackExchange/wmi v0.0.0-20190523213315-cbe66965904d/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg= +github.com/VividCortex/gohistogram v1.0.0/go.mod h1:Pf5mBqqDxYaXu3hDrrU+w6nw50o/4+TcAqDqk/vUH7g= github.com/XiaoMi/pegasus-go-client v0.0.0-20210427083443-f3b6b08bc4c2 h1:pami0oPhVosjOu/qRHepRmdjD6hGILF7DBr+qQZeP10= github.com/XiaoMi/pegasus-go-client v0.0.0-20210427083443-f3b6b08bc4c2/go.mod h1:jNIx5ykW1MroBuaTja9+VpglmaJOUzezumfhLlER3oY= +github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5/go.mod h1:SkGFH1ia65gfNATL8TAiHDNxPzPdmEL5uirI2Uyuz6c= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= @@ -78,20 +83,33 @@ github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk5 github.com/allegro/bigcache/v3 v3.0.2 h1:AKZCw+5eAaVyNTBmI2fgyPVJhHkdWder3O9IrprcQfI= github.com/antihax/optional v1.0.0 h1:xK2lYat7ZLaVVcIuj82J8kIro4V6kDe0AUDFboUCwcg= github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= +github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= +github.com/apache/thrift v0.13.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= +github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= +github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= +github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= +github.com/aryann/difflib v0.0.0-20170710044230-e206f873d14a/go.mod h1:DAHtR1m6lCRdSC2Tm3DSWRPvIPr6xNKyeHdqDQSQT+A= github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY= github.com/asaskevich/govalidator v0.0.0-20200108200545-475eaeb16496 h1:zV3ejI06GQ59hwDQAvmK1qxOQGB3WuVTRoY0okPTAv0= github.com/asaskevich/govalidator v0.0.0-20200108200545-475eaeb16496/go.mod h1:oGkLhpf+kjZl6xBf758TQhh5XrAeiJv/7FRz/2spLIg= +github.com/aws/aws-lambda-go v1.13.3/go.mod h1:4UKl9IzQMoD+QF79YdCuzCwp8VbmG4VAQwij/eHl5CU= github.com/aws/aws-sdk-go v1.20.20/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= github.com/aws/aws-sdk-go v1.26.3/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= +github.com/aws/aws-sdk-go v1.27.0/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= github.com/aws/aws-sdk-go v1.44.176 h1:mxcfI3IWHemX+5fEKt5uqIS/hdbaR7qzGfJYo5UyjJE= github.com/aws/aws-sdk-go v1.44.176/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI= +github.com/aws/aws-sdk-go-v2 v0.18.0/go.mod h1:JWVYvqSMppoMJC0x5wdwiImzgXTI9FuZwxzkQq9wy+g= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= +github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= github.com/bradfitz/gomemcache v0.0.0-20220106215444-fb4bf637b56d h1:pVrfxiGfwelyab6n21ZBkbkmbevaf+WvMIiR7sr97hw= github.com/bradfitz/gomemcache v0.0.0-20220106215444-fb4bf637b56d/go.mod h1:H0wQNHz2YrLsuXOZozoeDmnHXkNCRmMW0gwFWDfEZDA= +github.com/casbin/casbin/v2 v2.1.2/go.mod h1:YcPU1XXisHhLzuxH9coDNf2FbKpjGlbCg3n9yuLkIJQ= +github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM= github.com/cenkalti/backoff/v4 v4.1.0/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw= +github.com/cenkalti/backoff/v4 v4.1.1/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw= github.com/cenkalti/backoff/v4 v4.1.3 h1:cFAlzYUlVYDysBEH2T5hyJZMh3+5+WCBvSnK6Q8UtC4= github.com/cenkalti/backoff/v4 v4.1.3/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= @@ -103,14 +121,21 @@ github.com/cheekybits/is v0.0.0-20150225183255-68e9c0620927/go.mod h1:h/aW8ynjgk github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= +github.com/clbanning/x2j v0.0.0-20191024224557-825249438eec/go.mod h1:jMjuTZXRI4dUb/I5gc9Hdhagfvm9+RyrPryS/auMzxE= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= +github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8= +github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI= github.com/coocood/freecache v1.2.1 h1:/v1CqMq45NFH9mp/Pt142reundeBM0dVUD3osQBeu/U= +github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= +github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= +github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/cpuguy83/go-md2man/v2 v2.0.1 h1:r/myEWzV9lfsM1tFLgDyu0atFtJ1fXn261LKYj/3DxU= github.com/cpuguy83/go-md2man/v2 v2.0.1/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v0.0.0-20151105211317-5215b55f46b2/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v0.0.0-20161028175848-04cdfd42973b/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -121,6 +146,8 @@ github.com/deckarep/golang-set v1.8.0 h1:sk9/l/KqpunDwP7pSjUg0keiOOLEnOBHzykLrsP github.com/deckarep/golang-set v1.8.0/go.mod h1:5nI87KwE7wgsBU1F4GKAw2Qod7p5kyS383rP6+o6qqo= github.com/denisbrodbeck/machineid v1.0.1 h1:geKr9qtkB876mXguW2X6TU4ZynleN6ezuMSRhl4D7AQ= github.com/denisbrodbeck/machineid v1.0.1/go.mod h1:dJUwb7PTidGDeYyUBmXZ2GphQBbjJCrnectwCyxcUSI= +github.com/desertbit/timer v0.0.0-20180107155436-c41aec40b27f h1:U5y3Y5UE0w7amNe7Z5G/twsBW0KEalRQXZzf8ufSh9I= +github.com/desertbit/timer v0.0.0-20180107155436-c41aec40b27f/go.mod h1:xH/i4TFMt8koVQZ6WFms69WAsDWr2XsYL3Hkl7jkoLE= github.com/dgraph-io/ristretto v0.1.1 h1:6CWw5tJNgpegArSHpNHJKldNeq03FQCwYvfMVWajOK8= github.com/dgraph-io/ristretto v0.1.1/go.mod h1:S1GPSBCYCIhmVNfcth17y2zZtQT6wzkzgwUve0VDWWA= github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= @@ -131,13 +158,19 @@ github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cu github.com/dnaeon/go-vcr v1.0.1/go.mod h1:aBB1+wY4s93YsC3HHjMBMrwTj2R9FHDzUr9KyGc8n1E= github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96/go.mod h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM= github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE= +github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo= github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= +github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs= +github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU= +github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I= +github.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M= github.com/eko/gocache/v2 v2.3.1 h1:8MMkfqGJ0KIA9OXT0rXevcEIrU16oghrGDiIDJDFCa0= github.com/eko/gocache/v2 v2.3.1/go.mod h1:l2z8OmpZHL0CpuzDJtxm267eF3mZW1NqUsMj+sKrbUs= github.com/elazarl/goproxy v0.0.0-20170405201442-c4fc26588b6e/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc= github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc= github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= +github.com/envoyproxy/go-control-plane v0.6.9/go.mod h1:SBwIajubJHhxtWwsL9s8ss4safvEdbitLhGGK48rN6g= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= @@ -146,10 +179,13 @@ github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.m github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/evanphx/json-patch v4.2.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= github.com/evanphx/json-patch v4.12.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= +github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/felixge/fgprof v0.9.3 h1:VvyZxILNuCiUCSXtPtYmmtGvb65nqXh2QFWc0Wpf2/g= github.com/felixge/fgprof v0.9.3/go.mod h1:RdbpDgzqYVh/T9fPELJyV7EYJuHB55UTEULNun8eiPw= github.com/fortytw2/leaktest v1.3.0 h1:u8491cBMTQ8ft8aeV+adlcytMZylmA5nnwwkRZjI8vw= github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g= +github.com/franela/goblin v0.0.0-20200105215937-c9ffbefa60db/go.mod h1:7dvUGVsVBjqR7JHJk0brhHOZYGmfBYOrK0ZhYMEtBr4= +github.com/franela/goreq v0.0.0-20171204163338-bcd34c9993f8/go.mod h1:ZhphrRTfi2rbfLwlschooIH4+wKKDR4Pdxhh+TRoA20= github.com/frankban/quicktest v1.14.3 h1:FJKSZTDHjyhriyC81FLQ0LY93eSai0ZyR/ZIkd3ZUKE= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= @@ -160,11 +196,16 @@ github.com/gdamore/tcell v1.3.0/go.mod h1:Hjvr+Ofd+gLglo7RYKxxnzCBmev3BzsS67MebK github.com/getkin/kin-openapi v0.76.0/go.mod h1:660oXbgy5JFMKreazJaQTw7o+X00qeSyhcnluiMv+Xg= github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= +github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE= +github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= +github.com/gin-gonic/gin v1.6.3 h1:ahKqKTFpO5KTPHxWZjEdPScmYaGtLo8Y4DMHoEsnp14= +github.com/gin-gonic/gin v1.6.3/go.mod h1:75u5sXoLsGZoRN5Sgbi1eraJ4GU3++wFwWzhwvtwp4M= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= +github.com/go-kit/kit v0.10.0/go.mod h1:xUsJbQ/Fp4kEt7AFgCuvyX4a71u8h9jB8tj/ORgOZ7o= github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= github.com/go-kit/log v0.2.0/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0= github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= @@ -186,12 +227,29 @@ github.com/go-openapi/swag v0.0.0-20160704191624-1d0bd113de87/go.mod h1:DXUve3Dp github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= github.com/go-ozzo/ozzo-validation/v4 v4.3.0 h1:byhDUpfEwjsVQb1vBunvIjh2BHQ9ead57VkAEY4V+Es= github.com/go-ozzo/ozzo-validation/v4 v4.3.0/go.mod h1:2NKgrcHl3z6cJs+3Oo940FPRiTzuqKbvfrL2RxCj6Ew= +github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= +github.com/go-playground/locales v0.13.0 h1:HyWk6mgj5qFqCT5fjGBuRArbVDfE4hi8+e8ceBS/t7Q= +github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8= +github.com/go-playground/universal-translator v0.17.0 h1:icxd5fm+REJzpZx7ZfpaD876Lmtgy7VtROAbHHXk8no= +github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA= +github.com/go-playground/validator/v10 v10.2.0 h1:KgJ0snyC2R9VXYN2rneOtQcw5aHQB1Vv0sFl1UcHBOY= +github.com/go-playground/validator/v10 v10.2.0/go.mod h1:uOYAAleCW8F/7oMFd6aG0GOhaH6EGOAJShg8Id5JGkI= github.com/go-redis/redis/v8 v8.11.5 h1:AcZZR7igkdvfVmQTPnu9WE37LRrO/YrBH5zWyjDC0oI= github.com/go-redis/redis/v8 v8.11.5/go.mod h1:gREzHqY1hg6oD9ngVRbLStwAWKhA0FEgq8Jd4h5lpwo= +github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= +github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee h1:s+21KNqlpePfkah2I+gwHF8xmJWRjooY+5248k6m4A0= +github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee/go.mod h1:L0fX3K22YWvt/FAX9NnzrNzcI4wNYi9Yku4O0LKYflo= +github.com/gobwas/pool v0.2.0 h1:QEmUOlnSjWtnpRGHF3SauEiOsy82Cup83Vf2LcMlnc8= +github.com/gobwas/pool v0.2.0/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw= +github.com/gobwas/ws v1.0.2 h1:CoAavW/wd/kulfZmSIBt6p24n4j7tHgNVCjsfHVNUbo= +github.com/gobwas/ws v1.0.2/go.mod h1:szmBTxLgaFppYjEmNtny/v3w89xOydFnnZMcgRRu/EM= github.com/gofrs/uuid v4.3.1+incompatible h1:0/KbAdpx3UXAx1kEOWHJeOkpbgRFGHVgv+CFIY7dBJI= github.com/gofrs/uuid v4.3.1+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= +github.com/gogo/googleapis v1.1.0/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= +github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= +github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= github.com/gogo/protobuf v1.2.2-0.20190723190241-65acae22fc9d/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/gojuno/minimock/v3 v3.0.4/go.mod h1:HqeqnwV8mAABn3pO5hqF+RE7gjA0jsN8cbbSogoGrzI= @@ -232,6 +290,7 @@ github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= @@ -268,6 +327,7 @@ github.com/google/pprof v0.0.0-20211214055906-6f57359322fd h1:1FjCyPC+syAzJ5/2S8 github.com/google/pprof v0.0.0-20211214055906-6f57359322fd/go.mod h1:KgnwoLYCZ8IQu3XUZ8Nc/bM9CCZFOyjUNOSygVozoDg= github.com/google/readahead v0.0.0-20161222183148-eaceba169032/go.mod h1:qYysrqQXuV4tzsizt4oOQ6mrBZQ0xnQXP3ylXX8Jk5Y= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= +github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= @@ -284,23 +344,57 @@ github.com/googleapis/gnostic v0.5.5/go.mod h1:7+EbHbldMins07ALC74bsA81Ovc97Dwqy github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g= github.com/gophercloud/gophercloud v0.25.0 h1:C3Oae7y0fUVQGSsBrb3zliAjdX+riCSEh4lNMejFNI4= github.com/gophercloud/gophercloud v0.25.0/go.mod h1:Q8fZtyi5zZxPS/j9aj3sSxtvj41AdQMDwyo1myduD5c= +github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/gopherjs/gopherjs v0.0.0-20220410123724-9e86199038b0 h1:fWY+zXdWhvWndXqnMj4SyC/vi8sK508OjhGCtMzsA9M= +github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg= +github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= +github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= +github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= +github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc= github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= +github.com/grpc-ecosystem/go-grpc-middleware v1.2.2/go.mod h1:EaizFBKfUKtMIF5iaDEhniwNedqGo9FuLFzppDr3uwI= +github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= +github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= +github.com/hashicorp/consul/api v1.3.0/go.mod h1:MmDNSzIMUjNpY/mQ398R4bk2FnqQLoPndWW5VkKPlCE= +github.com/hashicorp/consul/sdk v0.3.0/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= +github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= +github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= +github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= +github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= +github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= +github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU= +github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU= +github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4= +github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= +github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= +github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= +github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ= +github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I= +github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= github.com/hexdigest/gowrap v1.1.7/go.mod h1:Z+nBFUDLa01iaNM+/jzoOA1JJ7sm51rnYFauKFUB5fs= github.com/hexdigest/gowrap v1.1.8/go.mod h1:H/JiFmQMp//tedlV8qt2xBdGzmne6bpbaSuiHmygnMw= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/huandu/xstrings v1.3.3 h1:/Gcsuc1x8JVbJ9/rlye4xZnVAbEkGauT8lbebqcQws4= github.com/huandu/xstrings v1.3.3/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= +github.com/hudl/fargo v1.3.0/go.mod h1:y3CKSmjA+wD2gak7sUSXTAoopbhU08POFhmITJgmKTg= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/ianlancetaylor/demangle v0.0.0-20210905161508-09a460cdf81d/go.mod h1:aYm2/VgdVmcIU8iMfdMvDMsRAQjcfZSKFby6HOFvi/w= github.com/imdario/mergo v0.3.11 h1:3tnifQM4i+fbajXKBHXWEH+KvNHqojZ778UH75j3bGA= github.com/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= +github.com/improbable-eng/grpc-web v0.15.0 h1:BN+7z6uNXZ1tQGcNAuaU1YjsLTApzkjt2tzCixLaUPQ= +github.com/improbable-eng/grpc-web v0.15.0/go.mod h1:1sy9HKV4Jt9aEs9JSnkWlRJPuPtwNr0l57L4f878wP8= +github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= +github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo= github.com/itchyny/gojq v0.12.9 h1:biKpbKwMxVYhCU1d6mR7qMr3f0Hn9F5k5YykCVb3gmM= github.com/itchyny/gojq v0.12.9/go.mod h1:T4Ip7AETUXeGpD+436m+UEl3m3tokRgajd5pRfsR5oE= github.com/itchyny/timefmt-go v0.1.4 h1:hFEfWVdwsEi+CY8xY2FtgWHGQaBaC3JeHd+cve0ynVM= @@ -310,10 +404,13 @@ github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9Y github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8= github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U= +github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= github.com/json-iterator/go v0.0.0-20180612202835-f2b4162afba3/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= +github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.8/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= @@ -321,14 +418,19 @@ github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHm github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo= +github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= github.com/k0kubun/go-ansi v0.0.0-20180517002512-3bf9e2903213/go.mod h1:vNUNkEQ1e29fT/6vq2aBdFsgNPmy8qMdSay1npru+Sw= github.com/keybase/go-ps v0.0.0-20190827175125-91aafc93ba19 h1:WjT3fLi9n8YWh/Ih8Q1LHAPsTqGddPcHqscN+PJ3i68= github.com/keybase/go-ps v0.0.0-20190827175125-91aafc93ba19/go.mod h1:hY+WOq6m2FpbvyrI93sMaypsttvaIL5nhVR92dTMUcQ= +github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/klauspost/compress v1.10.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= +github.com/klauspost/compress v1.11.7 h1:0hzRabrMN4tSTvMfnL3SCv1ZGeAP23ynzodBgaHeMeg= +github.com/klauspost/compress v1.11.7/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/fs v0.1.0 h1:Jskdu9ieNAYnjxsi0LbQp1ulIKZV1LAFgK1tWhpZgl8= @@ -343,13 +445,24 @@ github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= +github.com/leodido/go-urn v1.2.0 h1:hpXL4XnriNwQ/ABnpepYM/1vCLWNDfUNts8dX3xTG6Y= +github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII= +github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20190605223551-bc2310a04743/go.mod h1:qklhhLq1aX+mtWk9cPHPzaBjWImj5ULL6C7HFJtXQMM= +github.com/lightstep/lightstep-tracer-go v0.18.1/go.mod h1:jlF1pusYV4pidLvZ+XD0UBX0ZE6WURAspgAczcDHrL4= github.com/lucasb-eyer/go-colorful v1.0.2/go.mod h1:0MS4r+7BZKSJ5mw4/S5MPN+qHFF1fYclkSPilDOKW0s= +github.com/lyft/protoc-gen-validate v0.0.13/go.mod h1:XbGvPuh87YZc5TdIa2/I4pLk0QoUACkjt2znoq26NVQ= github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= github.com/mailru/easyjson v0.0.0-20160728113105-d5b7844b561a/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= +github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= +github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= +github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= +github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= +github.com/mattn/go-isatty v0.0.16 h1:bq3VjFmv/sOjHtdEhmkEV4x1AJtvUvOJ2PFAZ5+peKQ= +github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= @@ -357,10 +470,17 @@ github.com/mattn/go-runewidth v0.0.14 h1:+xnbZSEeDbOIg5/mE6JF0w6n9duR1l3/WmbinWV github.com/mattn/go-runewidth v0.0.14/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= +github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= +github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db h1:62I3jR2EmQ4l5rM/4FEfDWcRD+abF5XlKShorW5LRoQ= github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db/go.mod h1:l0dey0ia/Uv7NcFFVbCLtqEBQbrT4OCwCSKTEv6enCw= github.com/mitchellh/copystructure v1.0.0 h1:Laisrj+bAB6b/yJwB5Bt3ITZhGJdqmxquMKeZ+mmkFQ= github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw= +github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= +github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= +github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg= +github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY= +github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= @@ -378,28 +498,50 @@ github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjY github.com/mum4k/termdash v0.12.2/go.mod h1:haerPCSO0U8pehROAecmuOHDF+2UXw2KaCTxdWooDFE= github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= +github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f h1:KUppIJq7/+SVif2QVs3tOP0zanoHgBEVAwHxUSIzRqU= github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= +github.com/mwitkow/grpc-proxy v0.0.0-20181017164139-0f1106ef9c76/go.mod h1:x5OoJHDHqxHS801UIuhqGl6QdSAEJvtausosHSdazIo= github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw= github.com/nakabonne/gosivy v0.2.0 h1:Hlo0z3lzm/fOseUGn9jFNbUx5fJ3AqhkX37KBUxqXc8= github.com/nakabonne/gosivy v0.2.0/go.mod h1:qhCP4doWY7aiwwTgjJqU6JmIbF6JtntVPmHHF4ocaBc= +github.com/nats-io/jwt v0.3.0/go.mod h1:fRYCDE99xlTsqUzISS1Bi75UBJ6ljOJQOAAu5VglpSg= +github.com/nats-io/jwt v0.3.2/go.mod h1:/euKqTS1ZD+zzjYrY7pseZrTtWQSjujC7xjPc8wL6eU= +github.com/nats-io/nats-server/v2 v2.1.2/go.mod h1:Afk+wRZqkMQs/p45uXdrVLuab3gwv3Z8C4HTBu8GD/k= +github.com/nats-io/nats.go v1.9.1/go.mod h1:ZjDU1L/7fJ09jvUSRVBR2e7+RnLiiIQyqyzEE/Zbp4w= +github.com/nats-io/nkeys v0.1.0/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w= +github.com/nats-io/nkeys v0.1.3/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w= +github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c= github.com/ncw/swift v1.0.49 h1:eQaKIjSt/PXLKfYgzg01nevmO+CMXfXGRhB1gOhDs7E= github.com/ncw/swift v1.0.49/go.mod h1:23YIA4yWVnGwv2dQlN4bB7egfYX6YLn0Yo/S6zZO/ZM= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= github.com/nsf/termbox-go v0.0.0-20200204031403-4d2b513ad8be/go.mod h1:IuKpRQcYE1Tfu+oAQqaLisqDeXgjyyltCfsaoYN18NQ= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= +github.com/oklog/oklog v0.3.2/go.mod h1:FCV+B7mhrz4o+ueLpx+KqkyXRGMWOYEvfiXtdGtbWGs= +github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA= +github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.10.1/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= +github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= github.com/onsi/gomega v1.18.1 h1:M1GfJqGRrBrrGGsbxzV5dqM2U2ApXefZCQpkukxYRLE= +github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk= +github.com/opentracing-contrib/go-observer v0.0.0-20170622124052-a52f23424492/go.mod h1:Ngi6UdF0k5OKD5t5wlmGhe/EDKPoUM3BXZSSfIuJbis= +github.com/opentracing/basictracer-go v1.0.0/go.mod h1:QfBfYuafItcjQuMwinw9GhYKwFXS9KnPs5lxoYwgW74= github.com/opentracing/opentracing-go v1.0.2/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= +github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= +github.com/openzipkin-contrib/zipkin-go-opentracing v0.4.5/go.mod h1:/wsWhb9smxSfWAKL3wpBW7V8scJMt8N8gnaMCS9E/cA= +github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw= +github.com/openzipkin/zipkin-go v0.2.1/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4= +github.com/openzipkin/zipkin-go v0.2.2/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4= github.com/oscarpicas/covertool v0.4.1 h1:BvMC+hnaFMSeICIOpaJ2B9oskrGTkcRyZZWFnQ4IDTY= github.com/oscarpicas/covertool v0.4.1/go.mod h1:IfYhY3V3HmsXbncNU+AxbRx4rsLDqFgu86oOfNd93Q0= github.com/oscarpicas/go-dsp v0.1.0 h1:iOOUEVEWrBAljSZ0ZfqGcp5tsBvsEwvVvssa06ihC1E= @@ -410,63 +552,88 @@ github.com/oscarpicas/smetrics v0.1.0 h1:cZWNhs1ZZIUjTGLCEP+zMHDzvWQ4fzP2vNwYL1e github.com/oscarpicas/smetrics v0.1.0/go.mod h1:fuEa49km1JnuPsL9w257kBAYYzHSVcsauzFfVtrbhpQ= github.com/outscale/osc-sdk-go/osc v0.0.0-20200515123036-c82ce4912c6b h1:j7JX4xh1oxRvCeshZxwLvasEA0WED9g4FhVQnvq4iNY= github.com/outscale/osc-sdk-go/osc v0.0.0-20200515123036-c82ce4912c6b/go.mod h1:5AqqNH1X8zCHescKVlpSHRzrat1KCKDXqZoQPe8fY3A= +github.com/pact-foundation/pact-go v1.0.4/go.mod h1:uExwJY4kCzNPcHRj+hCR/HBbOOIwwtUjcrb0b5/5kLM= +github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/patrickmn/go-cache v2.1.0+incompatible h1:HRMgzkcYKYpi3C8ajMPV8OFXaaRUnok+kx1WdO15EQc= +github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k= github.com/pegasus-kv/thrift v0.13.0 h1:4ESwaNoHImfbHa9RUGJiJZ4hrxorihZHk5aarYwY8d4= github.com/pegasus-kv/thrift v0.13.0/go.mod h1:Gl9NT/WHG6ABm6NsrbfE8LiJN0sAyneCrvB4qN4NPqQ= github.com/pelletier/go-toml v1.9.4 h1:tjENF6MfZAg8e4ZmZTeWaWiT2vXtsoO6+iuOjFhECwM= github.com/pelletier/go-toml v1.9.4/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= github.com/pelletier/go-toml/v2 v2.0.6 h1:nrzqCb7j9cDFj2coyLNLaZuJTLjWjlaz6nvTvIwycIU= github.com/pelletier/go-toml/v2 v2.0.6/go.mod h1:eumQOmlWiOPt5WriQQqoM5y18pDHwha2N+QD+EUNTek= +github.com/performancecopilot/speed v3.0.0+incompatible/go.mod h1:/CLtqpZ5gBg1M9iaPbIdPPGyKcA8hKdoy6hAWba7Yac= +github.com/pierrec/lz4 v1.0.2-0.20190131084431-473cd7ce01a1/go.mod h1:3/3N9NVKO0jef7pBehbT1qWhCMrIgbYNnFAZCqQ5LRc= +github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/profile v1.2.1/go.mod h1:hJw3o1OdXxsrSjjVksARp5W95eeEaEfptyVZyv6JUPA= github.com/pkg/sftp v1.13.1/go.mod h1:3HaPG6Dq1ILlpPZRO0HVMrsydcdLt6HRDccSgb87qRg= github.com/pkg/sftp v1.13.5 h1:a3RLUqkyjYRtBTZJZ1VRrKbN3zhuPLlUc3sphVz81go= github.com/pkg/sftp v1.13.5/go.mod h1:wHDZ0IZX6JcBYRK1TH9bcVq8G7TLpVHYIGJRFnmPfxg= github.com/pmezard/go-difflib v0.0.0-20151028094244-d8ed2627bdf0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= github.com/pquerna/ffjson v0.0.0-20190930134022-aa0246cd15f7/go.mod h1:YARuvh7BUWHNhzDq2OM5tzR2RiCcN2D7sapiKyCel/M= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= +github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod h1:p2iRAGwDERtqlqzRXnrOVns+ignqQo//hLXqYxZYVNs= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= +github.com/prometheus/client_golang v1.3.0/go.mod h1:hJaj2vgQTGQmVCsAACORcieXFeDPbaTKGT+JTgUa3og= github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0= github.com/prometheus/client_golang v1.12.1/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY= github.com/prometheus/client_golang v1.12.2 h1:51L9cDoUHVrXx4zWYlcLQIZ+d+VXHgqnYKkIuq4g/34= github.com/prometheus/client_golang v1.12.2/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= +github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.1.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.2.0 h1:uq5h0d+GuxiXLJLNABMgp2qUWDPiLvgCzz2dUR+/W/M= github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= +github.com/prometheus/common v0.7.0/go.mod h1:DjGbpBbp5NYNiECxcL/VnbXCCaQpKd3tt26CguLLsqA= github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= +github.com/prometheus/common v0.15.0/go.mod h1:U+gB1OBLb1lF3O42bTCL+FK18tX9Oar16Clt/msog/s= github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc= github.com/prometheus/common v0.32.1/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= github.com/prometheus/common v0.33.0 h1:rHgav/0a6+uYgGdNt3jwz8FNSesO/Hsang3O0T9A5SE= github.com/prometheus/common v0.33.0/go.mod h1:gB3sOl7P0TvJabZpLY5uQMpUqRCPPCyRLCZYc7JZTNE= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= +github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= +github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= +github.com/prometheus/procfs v0.3.0/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= github.com/prometheus/procfs v0.7.3 h1:4jVXhlkAyzOScmCkXBTOLRLTz8EeU+eyjrwB/EPq0VU= github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= github.com/quasilyte/go-ruleguard/dsl v0.3.21 h1:vNkC6fC6qMLzCOGbnIHOd5ixUGgTbp3Z4fGnUgULlDA= github.com/quasilyte/go-ruleguard/dsl v0.3.21/go.mod h1:KeCP03KrjuSO0H1kTuZQCWlQPulDV6YMIXmpQss17rU= +github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/rivo/uniseg v0.4.3 h1:utMvzDsuh3suAEnhH0RdHmoPbU648o6CvXxTx4SBMOw= github.com/rivo/uniseg v0.4.3/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= +github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.6.1 h1:/FiVV8dS/e+YqF2JvO3yXRFbBLTIuSDkuC7aBOAvL+k= +github.com/rs/cors v1.7.0 h1:+88SsELBHx5r+hZ8TCkggzSstaWNbDvThkVK8H6f9ik= +github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= +github.com/samuel/go-zookeeper v0.0.0-20190923202752-2cc03de413da/go.mod h1:gi+0XIa01GRL2eRQVjQkKGqKF3SF9vZR/HnPullcV2E= github.com/sanity-io/litter v1.5.5 h1:iE+sBxPBzoK6uaEP5Lt3fHNgpKcHXc/A2HGETy0uJQo= github.com/sanity-io/litter v1.5.5/go.mod h1:9gzJgR2i4ZpjZHsKvUXIRQVk7P+yM3e+jAF7bU2UI5U= github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= github.com/schollz/progressbar/v3 v3.9.0 h1:k9SRNQ8KZyibz1UZOaKxnkUE3iGtmGSDt1YY9KlCYQk= github.com/schollz/progressbar/v3 v3.9.0/go.mod h1:W5IEwbJecncFGBvuEh4A7HT1nZZ6WNIL2i3qbnI0WKY= +github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= github.com/sethvargo/go-password v0.2.0 h1:BTDl4CC/gjf/axHMaDQtw507ogrXLci6XRiLc7i/UHI= github.com/sethvargo/go-password v0.2.0/go.mod h1:Ym4Mr9JXLBycr02MFuVQ/0JHidNetSgbzutTr3zsYXE= github.com/shirou/gopsutil v2.20.9+incompatible h1:msXs2frUV+O/JLva9EDLpuJ84PrFsdCTCQex8PUdtkQ= @@ -480,8 +647,12 @@ github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrf github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0= github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= +github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= github.com/smartystreets/assertions v1.13.0 h1:Dx1kYM01xsSqKPno3aqLnrwac2LetPvN23diwyr69Qs= +github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= github.com/smartystreets/goconvey v1.7.2 h1:9RBaZCeXEQ3UselpuwUQHltGVXvdwm6cv1hgR6gDIPg= +github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= +github.com/sony/gobreaker v0.4.1/go.mod h1:ZKptC7FHNvhBz7dN2LGjPVBz2sZJmc0/PkyDJOjmxWY= github.com/sony/gobreaker v0.5.0 h1:dRCvqm0P490vZPmy7ppEk2qCnCieBooFJ+YoXGYB+yg= github.com/sony/gobreaker v0.5.0/go.mod h1:ZKptC7FHNvhBz7dN2LGjPVBz2sZJmc0/PkyDJOjmxWY= github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk= @@ -490,14 +661,19 @@ github.com/spf13/afero v1.8.2/go.mod h1:CtAatgMJh6bJEIs48Ay/FOnkljP3WeGUG0MC1RfA github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= github.com/spf13/cast v1.5.0 h1:rj3WzYc11XZaIZMPKmwP96zkFEnnAmV8s6XbB2aY32w= github.com/spf13/cast v1.5.0/go.mod h1:SpXXQ5YoyJw6s3/6cMTQuxvgRl3PCJiyaX9p6b155UU= +github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk= github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= github.com/spf13/pflag v0.0.0-20170130214245-9ff6c6923cff/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/viper v1.11.0 h1:7OX/1FS6n7jHD1zGrZTM7WtY13ZELRyosK4k93oPr44= github.com/spf13/viper v1.11.0/go.mod h1:djo0X/bA5+tYVoCn+C7cAYJGcVn/qYLFTG8gdUsX7Zk= github.com/stoewer/go-strcase v1.2.0/go.mod h1:IBiWB2sKIp3wVVQ3Y035++gc+knqhUQag1KpM8ahLw8= +github.com/streadway/amqp v0.0.0-20190404075320-75d898a42a94/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= +github.com/streadway/amqp v0.0.0-20190827072141-edfb9018d271/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= +github.com/streadway/handy v0.0.0-20190108123426-d5acb3125c2a/go.mod h1:qNTQ5P5JnDBl6z3cMAg/SywNDC5ABu5ApDIw6lUbRmI= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= @@ -516,10 +692,18 @@ github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKs github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/subosito/gotenv v1.2.0 h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s= github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= +github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/twitchtv/twirp v5.8.0+incompatible/go.mod h1:RRJoFSAmTEh2weEqWtpPE3vFK5YBhA6bqp2l1kfCC5A= +github.com/ugorji/go v1.1.7 h1:/68gy2h+1mWMrwZFeD1kQialdSzAb432dtpeJ42ovdo= +github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw= +github.com/ugorji/go/codec v1.1.7 h1:2SvQaVZ1ouYrrKKwoSk2pzd4A9evlKJb9oTL+OaLUSs= +github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY= +github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= +github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= github.com/urfave/cli v1.22.10 h1:p8Fspmz3iTctJstry1PYS3HVdllxnEzTEsgIgtxTrCk= github.com/urfave/cli v1.22.10/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI= +github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= @@ -528,6 +712,10 @@ github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1 github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= github.com/zserge/metric v0.1.0 h1:IkYtSU/cSx7gnLZTJHrmblRtR3D4JVIvX7nnKELJT5U= github.com/zserge/metric v0.1.0/go.mod h1:SfdmUuuSJsSXW4W5sdU34LILvn+nHLufqIwNu22LW3c= +go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= +go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738/go.mod h1:dnLIgRNXwCJa5e+c6mIZCrds/GIG4ncV9HhK5PX7jPg= +go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= +go.opencensus.io v0.20.2/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= @@ -536,10 +724,20 @@ go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= +go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= +go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= +go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= +go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= +go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4= +go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA= +go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= +go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= @@ -561,6 +759,7 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0 golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= +golang.org/x/exp v0.0.0-20200331195152-e8c3332aa8e5/go.mod h1:4M0jN8W1tt0AVLNr8HDosyJCDCDuyL9N9+3m7wDWgKw= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= @@ -590,8 +789,12 @@ golang.org/x/net v0.0.0-20170114055629-f2499483f923/go.mod h1:mL1N/T3taQHkDXs73r golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190125091013-d26f9f9a57f3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= @@ -602,6 +805,7 @@ golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLL golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20191004110552-13f9640d40b9/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20191105084925-a882066a44e0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= @@ -612,6 +816,7 @@ golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLL golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200421231249-e086a090c8fd/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= @@ -628,6 +833,7 @@ golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211209124913-491a49abca63/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= @@ -665,10 +871,14 @@ golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20170830134202-bb24a47a89ea/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -687,9 +897,11 @@ golang.org/x/sys v0.0.0-20191010194322-b09406accb47/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191220142924-d4481acd189f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -697,6 +909,7 @@ golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200420163511-1957bb5e6d1f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -720,6 +933,7 @@ golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210831042530-f4d43177bf5e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -752,9 +966,12 @@ golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.6.0 h1:3XmdazWV+ubf7QgHSTWeykHOci5oeekaGJBLkrkaw4k= golang.org/x/text v0.6.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20181011042414-1f849cf54d09/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -763,6 +980,7 @@ golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3 golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= @@ -773,6 +991,8 @@ golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgw golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= @@ -780,6 +1000,7 @@ golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtn golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200103221440-774c71fcf114/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= @@ -817,6 +1038,7 @@ golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8T golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= gomodules.xyz/stow v0.2.4 h1:TwsLIE8OAN3hkUR45CJwbJEoqYzWv33yuuq++ZkYdyo= gomodules.xyz/stow v0.2.4/go.mod h1:aAgUEHyZ+4nKznyVupMMkP0JX9MXW1ZRrbRGaclp3E0= +google.golang.org/api v0.3.1/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk= google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= google.golang.org/api v0.6.1-0.20190607001116-5213b8090861/go.mod h1:btoxGiFvQNVUZQ8W08zLtrVS08CNpINPEfxXxgJL1Q4= google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= @@ -840,6 +1062,7 @@ google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjR google.golang.org/api v0.107.0 h1:I2SlFjD8ZWabaIFOfeEDg3pf0BHJDh6iYQ1ic3Yu/UU= google.golang.org/api v0.107.0/go.mod h1:2Ts0XTHNVWxypznxWOYUeI4g3WdP9Pk2Qk58+a/O9MY= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= +google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= @@ -852,6 +1075,7 @@ google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRn google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190530194941-fb225487d101/go.mod h1:z3L6/3dTEVtUr6QSP8miRzeRqwQOioJ9I66odjN4I7s= google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= @@ -868,6 +1092,7 @@ google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfG google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200423170343-7949de9c1215/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U= @@ -883,13 +1108,19 @@ google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6D google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210108203827-ffc7fda8c3d7/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210126160654-44e461bb6506/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210226172003-ab064af71705/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20221227171554-f9683d7f8bef h1:uQ2vjV/sHTsWSqdKeLqmwitzgvjMl7o4IdtHwUDXSJY= google.golang.org/genproto v0.0.0-20221227171554-f9683d7f8bef/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= +google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= +google.golang.org/grpc v1.20.0/go.mod h1:chYK+tFQF0nDUGJgXMSgLCQk3phJEuONr2DCgLDdAQM= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= +google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= +google.golang.org/grpc v1.22.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.23.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= @@ -899,6 +1130,7 @@ google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3Iji google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc v1.32.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8= google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= @@ -926,18 +1158,23 @@ gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8 gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= +gopkg.in/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= +gopkg.in/gcfg.v1 v1.2.3/go.mod h1:yesOnuUOFQAhST5vPY4nbZsb/huCgGGXlipJsBn0b3o= gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= gopkg.in/ini.v1 v1.66.4 h1:SsAcf+mM7mRZo2nJNGt8mZCjG8ZRaNGMURJw7BsIST4= gopkg.in/ini.v1 v1.66.4/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/kothar/go-backblaze.v0 v0.0.0-20190520213052-702d4e7eb465/go.mod h1:zJ2QpyDCYo1KvLXlmdnFlQAyF/Qfth0fB8239Qg7BIE= gopkg.in/natefinch/lumberjack.v2 v2.0.0 h1:1Lc07Kr7qY4U2YPouBjpCLxpiyxIVoxqXgkXLknAOE8= gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k= +gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= gopkg.in/tomb.v2 v2.0.0-20161208151619-d5d1b5820637 h1:yiW+nvdHb9LVqSHQBXfZCieqV4fzYhNBql77zY0ykqs= gopkg.in/tomb.v2 v2.0.0-20161208151619-d5d1b5820637/go.mod h1:BHsqpu/nsuzkT5BpiH1EMZPLyqSMM8JbIavyFACoFNk= +gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI= +gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= @@ -952,6 +1189,7 @@ gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= @@ -973,6 +1211,8 @@ k8s.io/kube-openapi v0.0.0-20191107075043-30be4d16710a/go.mod h1:1TqjTSzOxsLGIKf k8s.io/kube-openapi v0.0.0-20211115234752-e816edb12b65/go.mod h1:sX9MT8g7NVZM5lVL/j8QyCCJe8YSMW30QvGZWaCIDIk= k8s.io/utils v0.0.0-20210802155522-efc7438f0176/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= k8s.io/utils v0.0.0-20211116205334-6203023598ed/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= +nhooyr.io/websocket v1.8.6 h1:s+C3xAMLwGmlI31Nyn/eAehUlZPwfYZu2JXM621Q5/k= +nhooyr.io/websocket v1.8.6/go.mod h1:B70DZP8IakI65RVQ51MsWP/8jndNma26DVA/nFSCgW0= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= @@ -982,3 +1222,4 @@ sigs.k8s.io/structured-merge-diff/v4 v4.0.2/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK sigs.k8s.io/structured-merge-diff/v4 v4.2.1/go.mod h1:j/nl6xW8vLS49O8YvXW1ocPhZawJtm+Yrr7PPRQ0Vg4= sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc= +sourcegraph.com/sourcegraph/appdash v0.0.0-20190731080439-ebfcffb1b5c0/go.mod h1:hI742Nqp5OhwiqlzhgfbWU4mW4yO10fP+LoT9WOswdU= diff --git a/lib/utils/heartbeat/heartbeat.go b/lib/utils/heartbeat/heartbeat.go index dabce1ace..b0b82d3aa 100644 --- a/lib/utils/heartbeat/heartbeat.go +++ b/lib/utils/heartbeat/heartbeat.go @@ -18,6 +18,7 @@ package heartbeat import ( "encoding/json" + "github.com/CS-SI/SafeScale/v22/lib" "net/http" "time" @@ -40,10 +41,7 @@ func init() { } func handler(rw http.ResponseWriter, _ *http.Request) { - hash := commitHash - if hash == "" { - hash = notAvailableMessage - } + hash := lib.Revision uptime := time.Since(startTime).String() err := json.NewEncoder(rw).Encode(heartbeatMessage{"running", hash, uptime}) if err != nil { diff --git a/lib/utils/valid/consts.go b/lib/utils/valid/consts.go index d042537e7..5d30ff218 100644 --- a/lib/utils/valid/consts.go +++ b/lib/utils/valid/consts.go @@ -1,2 +1,3 @@ package valid + const EmbeddedErrorStructName = "errorCore" From a3017a4a7d5c0d8a4449aefeaa031e39c25667f0 Mon Sep 17 00:00:00 2001 From: oscar Date: Mon, 6 Feb 2023 11:43:22 +0100 Subject: [PATCH 14/43] feat: better logs --- lib/backend/job.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/backend/job.go b/lib/backend/job.go index bfdc5151c..79f02d067 100644 --- a/lib/backend/job.go +++ b/lib/backend/job.go @@ -92,10 +92,10 @@ func NewJob(ctx context.Context, cancel context.CancelFunc, svc iaas.Service, de } else { u := md.Get("uuid") if len(u) == 0 { - logrus.WithContext(ctx).Warnf(fail.InvalidParameterError("ctx", "does not contain a grpc uuid").Error()) + logrus.WithContext(ctx).Warnf("ctx does not contain a grpc uuid, it's probably a web request") } else { // nolint if id = u[0]; id == "" { - logrus.WithContext(ctx).Warnf(fail.InvalidParameterError("ctx", "does not contain a valid gRPC uuid").Error()) + logrus.WithContext(ctx).Warnf("ctx has an EMPTY grpc uuid, it's probably a bad web request") } } From 07fb9b1b5a9adeafb4da15146b79ff13ec8747a1 Mon Sep 17 00:00:00 2001 From: oscar Date: Mon, 6 Feb 2023 12:26:54 +0100 Subject: [PATCH 15/43] doc: added fixmes --- lib/backend/handlers/tenant.go | 2 +- lib/backend/listeners/tenant.go | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/lib/backend/handlers/tenant.go b/lib/backend/handlers/tenant.go index 4407ab2e5..05dbdb90a 100644 --- a/lib/backend/handlers/tenant.go +++ b/lib/backend/handlers/tenant.go @@ -182,7 +182,7 @@ func (handler *tenantHandler) Inspect(tenantName string) (_ *protocol.TenantInsp return nil, err } if tenantName != currentName { - return nil, fail.NewError("we only inspect current tenant right now") + return nil, fail.NewError("we only inspect current tenant right now") // FIXME: OPP It has to change now } ctx := handler.job.Context() diff --git a/lib/backend/listeners/tenant.go b/lib/backend/listeners/tenant.go index 358fdcd3c..8a80c31b0 100644 --- a/lib/backend/listeners/tenant.go +++ b/lib/backend/listeners/tenant.go @@ -109,9 +109,8 @@ func (s *TenantListener) Set(inctx context.Context, in *protocol.TenantName) (em if in == nil { return empty, fail.InvalidParameterError("in", "cannot be nil") } - defer fail.OnExitLogError(inctx, &err) - + // FIXME: OPP Cannot fucking believe it... xerr := operations.SetCurrentTenant(inctx, in.GetName()) if xerr != nil { return empty, xerr From 0aeca50155fb000e8fa8ef901825c40b16239714 Mon Sep 17 00:00:00 2001 From: oscar Date: Mon, 6 Feb 2023 12:27:52 +0100 Subject: [PATCH 16/43] bug: improper input validation --- lib/backend/listeners/bucket.go | 3 +++ lib/backend/listeners/cluster.go | 12 +++++++++--- lib/backend/listeners/host.go | 9 +++++++++ lib/backend/listeners/securitygroup.go | 3 +++ lib/backend/listeners/share.go | 3 +++ lib/backend/listeners/template.go | 6 ++++++ lib/backend/listeners/tenant.go | 9 +++++++++ 7 files changed, 42 insertions(+), 3 deletions(-) diff --git a/lib/backend/listeners/bucket.go b/lib/backend/listeners/bucket.go index 4dbedee67..85391a9a5 100644 --- a/lib/backend/listeners/bucket.go +++ b/lib/backend/listeners/bucket.go @@ -50,6 +50,9 @@ func (s *BucketListener) List(inctx context.Context, in *protocol.BucketListRequ if s == nil { return nil, fail.InvalidInstanceError() } + if in == nil { + return nil, fail.InvalidParameterCannotBeNilError("in") + } if inctx == nil { return nil, fail.InvalidParameterError("inctx", "cannot be nil") } diff --git a/lib/backend/listeners/cluster.go b/lib/backend/listeners/cluster.go index 4f5c44651..f1116d699 100644 --- a/lib/backend/listeners/cluster.go +++ b/lib/backend/listeners/cluster.go @@ -46,6 +46,9 @@ func (s *ClusterListener) List(inctx context.Context, in *protocol.Reference) (h if s == nil { return nil, fail.InvalidInstanceError() } + if in == nil { + return nil, fail.InvalidParameterCannotBeNilError("in") + } if inctx == nil { return nil, fail.InvalidParameterCannotBeNilError("inctx") } @@ -187,6 +190,9 @@ func (s *ClusterListener) Start(inctx context.Context, in *protocol.Reference) ( if s == nil { return empty, fail.InvalidInstanceError() } + if in == nil { + return empty, fail.InvalidParameterCannotBeNilError("in") + } ref, _ := srvutils.GetReference(in) if ref == "" { return empty, fail.InvalidParameterCannotBeEmptyStringError("ref") @@ -214,12 +220,12 @@ func (s *ClusterListener) Stop(inctx context.Context, in *protocol.Reference) (e if s == nil { return empty, fail.InvalidInstanceError() } - if inctx == nil { - return empty, fail.InvalidParameterCannotBeNilError("inctx") - } if in == nil { return empty, fail.InvalidParameterCannotBeNilError("in") } + if inctx == nil { + return empty, fail.InvalidParameterCannotBeNilError("inctx") + } ref, _ := srvutils.GetReference(in) if ref == "" { return empty, fail.InvalidRequestError("cluster name is missing") diff --git a/lib/backend/listeners/host.go b/lib/backend/listeners/host.go index c5fa090ea..838609e1f 100644 --- a/lib/backend/listeners/host.go +++ b/lib/backend/listeners/host.go @@ -78,6 +78,9 @@ func (s *HostListener) Start(inctx context.Context, in *protocol.Reference) (emp if s == nil { return empty, fail.InvalidInstanceError() } + if in == nil { + return nil, fail.InvalidParameterCannotBeNilError("in") + } ref, _ := srvutils.GetReference(in) if ref == "" { return empty, fail.InvalidParameterError("ref", "cannot be empty string") @@ -136,6 +139,9 @@ func (s *HostListener) Reboot(inctx context.Context, in *protocol.Reference) (em if s == nil { return empty, fail.InvalidInstanceError() } + if in == nil { + return nil, fail.InvalidParameterCannotBeNilError("in") + } if inctx == nil { return empty, fail.InvalidParameterCannotBeNilError("inctx") } @@ -163,6 +169,9 @@ func (s *HostListener) List(inctx context.Context, in *protocol.HostListRequest) if s == nil { return nil, fail.InvalidInstanceError() } + if in == nil { + return nil, fail.InvalidParameterCannotBeNilError("in") + } if inctx == nil { return nil, fail.InvalidParameterCannotBeNilError("inctx") } diff --git a/lib/backend/listeners/securitygroup.go b/lib/backend/listeners/securitygroup.go index 84c1b7e6d..e6a400ee5 100644 --- a/lib/backend/listeners/securitygroup.go +++ b/lib/backend/listeners/securitygroup.go @@ -47,6 +47,9 @@ func (s *SecurityGroupListener) List(inctx context.Context, in *protocol.Securit if s == nil { return nil, fail.InvalidInstanceError() } + if in == nil { + return nil, fail.InvalidParameterCannotBeNilError("in") + } if inctx == nil { return nil, fail.InvalidParameterCannotBeNilError("inctx") } diff --git a/lib/backend/listeners/share.go b/lib/backend/listeners/share.go index 4f4f501f7..f1b910081 100644 --- a/lib/backend/listeners/share.go +++ b/lib/backend/listeners/share.go @@ -124,6 +124,9 @@ func (s *ShareListener) List(inctx context.Context, in *protocol.Reference) (_ * if s == nil { return nil, fail.InvalidInstanceError() } + if in == nil { + return nil, fail.InvalidParameterCannotBeNilError("in") + } if inctx == nil { return nil, fail.InvalidParameterCannotBeNilError("inctx") } diff --git a/lib/backend/listeners/template.go b/lib/backend/listeners/template.go index 4acb24942..4c1f21208 100644 --- a/lib/backend/listeners/template.go +++ b/lib/backend/listeners/template.go @@ -47,6 +47,9 @@ func (s *TemplateListener) List(inctx context.Context, in *protocol.TemplateList if s == nil { return nil, fail.InvalidInstanceError() } + if in == nil { + return nil, fail.InvalidParameterCannotBeNilError("in") + } if inctx == nil { return nil, fail.InvalidParameterError("inctx", "cannot be nil") } @@ -83,6 +86,9 @@ func (s *TemplateListener) Match(inctx context.Context, in *protocol.TemplateMat if s == nil { return nil, fail.InvalidInstanceError() } + if in == nil { + return nil, fail.InvalidParameterCannotBeNilError("in") + } if inctx == nil { return nil, fail.InvalidParameterError("inctx", "cannot be nil") } diff --git a/lib/backend/listeners/tenant.go b/lib/backend/listeners/tenant.go index 8a80c31b0..edceda520 100644 --- a/lib/backend/listeners/tenant.go +++ b/lib/backend/listeners/tenant.go @@ -41,6 +41,9 @@ func (s *TenantListener) List(inctx context.Context, in *googleprotobuf.Empty) ( if s == nil { return nil, fail.InvalidInstanceError() } + if in == nil { + return nil, fail.InvalidParameterCannotBeNilError("in") + } if inctx == nil { return nil, fail.InvalidParameterError("inctx", "cannot be nil") } @@ -70,6 +73,9 @@ func (s *TenantListener) Get(inctx context.Context, in *googleprotobuf.Empty) (_ if s == nil { return nil, fail.InvalidInstanceError() } + if in == nil { + return nil, fail.InvalidParameterCannotBeNilError("in") + } if inctx == nil { return nil, fail.InvalidParameterError("inctx", "cannot be nil") } @@ -127,6 +133,9 @@ func (s *TenantListener) Scan(inctx context.Context, in *protocol.TenantScanRequ if inctx == nil { return nil, fail.InvalidParameterError("inctx", "cannot be nil") } + if in == nil { + return nil, fail.InvalidParameterCannotBeNilError("in") + } if in == nil { return nil, fail.InvalidParameterError("in", "cannot be nil") } From 33321276cf94aaeb475979b46758ba6f559d7999 Mon Sep 17 00:00:00 2001 From: oscar Date: Mon, 6 Feb 2023 15:40:50 +0100 Subject: [PATCH 17/43] wip: image tricks --- lib/backend/iaas/stacks/aws/compute.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/backend/iaas/stacks/aws/compute.go b/lib/backend/iaas/stacks/aws/compute.go index 760390cd2..2c147a446 100644 --- a/lib/backend/iaas/stacks/aws/compute.go +++ b/lib/backend/iaas/stacks/aws/compute.go @@ -19,6 +19,7 @@ package aws import ( "context" "fmt" + "github.com/sanity-io/litter" "reflect" "regexp" "sort" @@ -186,6 +187,8 @@ func (s stack) InspectImage(ctx context.Context, id string) (_ *abstract.Image, return nil, xerr } + logrus.WithContext(ctx).Warnf("Image full info: %s", litter.Sdump(resp)) // FIXME: OPP Remove this later + return toAbstractImage(*resp), nil } From d73952e863e4107687fea8326500becc8a454b72 Mon Sep 17 00:00:00 2001 From: oscar Date: Mon, 6 Feb 2023 16:25:14 +0100 Subject: [PATCH 18/43] chores: version bumps --- .github/workflows/go.yml | 2 +- Makefile | 4 ++-- common.mk | 2 +- go.mod | 8 ++++---- go.sum | 16 ++++++++-------- 5 files changed, 16 insertions(+), 16 deletions(-) diff --git a/.github/workflows/go.yml b/.github/workflows/go.yml index a1290823c..429fcf696 100644 --- a/.github/workflows/go.yml +++ b/.github/workflows/go.yml @@ -25,7 +25,7 @@ jobs: strategy: matrix: - go: [ 1.18.4 ] + go: [ 1.18.4, 1.19.5, 1.20 ] tags: [ releasetags, debug, tunnel ] runs-on: ubuntu-latest diff --git a/Makefile b/Makefile index d38517f5a..0e0c20941 100755 --- a/Makefile +++ b/Makefile @@ -171,7 +171,7 @@ common: begin ground getdevdeps mod sdk generate versioncut: @printf "%b" "$(OK_COLOR)$(INFO_STRING) Go version check$(NO_COLOR)\n"; - @(($(GO) version | grep go1.19) || ($(GO) version | grep go1.18)) || (printf "%b" "$(ERROR_COLOR)$(ERROR_STRING) Minimum go version is 1.18 ! $(NO_COLOR)\n" && false); + @(($(GO) version | grep go1.20) || ($(GO) version | grep go1.19) || ($(GO) version | grep go1.18)) || (printf "%b" "$(ERROR_COLOR)$(ERROR_STRING) Minimum go version is 1.18 ! $(NO_COLOR)\n" && false); begin: versioncut @printf "%b" "$(OK_COLOR)$(INFO_STRING) Build begins, branch $$(git rev-parse --abbrev-ref HEAD), commit $$(git log --format="%H" -n 1), go '$$($(GO) version)', protoc '$$(protoc --version)' ...$(NO_COLOR)\n"; @@ -235,7 +235,7 @@ ground: begin cideps: begin ground @$(WHICH) gojq > /dev/null; if [ $$? -ne 0 ]; then \ printf "%b" "$(OK_COLOR)$(INFO_STRING) Downloading gojq...$(NO_COLOR)\n"; \ - $(GO) install $(GOJQ)@v0.12.9 &>/dev/null || true; \ + $(GO) install $(GOJQ)@v0.12.11 &>/dev/null || true; \ fi @$(WHICH) gron > /dev/null; if [ $$? -ne 0 ]; then \ printf "%b" "$(OK_COLOR)$(INFO_STRING) Downloading gron...$(NO_COLOR)\n"; diff --git a/common.mk b/common.mk index f464d8fd0..5f0fcceaa 100755 --- a/common.mk +++ b/common.mk @@ -1,4 +1,4 @@ -VERSION=22.11.5 +VERSION=22.11.6 export VERSION ifeq ($(MAKE_LEVEL),) diff --git a/go.mod b/go.mod index 4e660c70f..ddc9bb3aa 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,7 @@ go 1.18 require ( github.com/Masterminds/sprig/v3 v3.2.3 github.com/antihax/optional v1.0.0 - github.com/aws/aws-sdk-go v1.44.176 + github.com/aws/aws-sdk-go v1.44.194 github.com/davecgh/go-spew v1.1.1 github.com/deckarep/golang-set v1.8.0 github.com/denisbrodbeck/machineid v1.0.1 @@ -13,13 +13,13 @@ require ( github.com/eko/gocache/v2 v2.3.1 github.com/felixge/fgprof v0.9.3 github.com/go-ozzo/ozzo-validation/v4 v4.3.0 - github.com/gofrs/uuid v4.3.1+incompatible + github.com/gofrs/uuid v4.4.0+incompatible github.com/gojuno/minimock/v3 v3.0.10 github.com/golang/protobuf v1.5.2 github.com/google/gofuzz v1.2.0 github.com/gophercloud/gophercloud v0.25.0 github.com/improbable-eng/grpc-web v0.15.0 - github.com/itchyny/gojq v0.12.9 + github.com/itchyny/gojq v0.12.11 github.com/json-iterator/go v1.1.12 github.com/magiconair/properties v1.8.7 github.com/mitchellh/mapstructure v1.5.0 @@ -83,7 +83,7 @@ require ( github.com/hashicorp/hcl v1.0.0 // indirect github.com/huandu/xstrings v1.3.3 // indirect github.com/imdario/mergo v0.3.11 // indirect - github.com/itchyny/timefmt-go v0.1.4 // indirect + github.com/itchyny/timefmt-go v0.1.5 // indirect github.com/jmespath/go-jmespath v0.4.0 // indirect github.com/keybase/go-ps v0.0.0-20190827175125-91aafc93ba19 // indirect github.com/klauspost/compress v1.11.7 // indirect diff --git a/go.sum b/go.sum index 60a57901a..17178e55e 100644 --- a/go.sum +++ b/go.sum @@ -96,8 +96,8 @@ github.com/aws/aws-lambda-go v1.13.3/go.mod h1:4UKl9IzQMoD+QF79YdCuzCwp8VbmG4VAQ github.com/aws/aws-sdk-go v1.20.20/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= github.com/aws/aws-sdk-go v1.26.3/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= github.com/aws/aws-sdk-go v1.27.0/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= -github.com/aws/aws-sdk-go v1.44.176 h1:mxcfI3IWHemX+5fEKt5uqIS/hdbaR7qzGfJYo5UyjJE= -github.com/aws/aws-sdk-go v1.44.176/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI= +github.com/aws/aws-sdk-go v1.44.194 h1:1ZDK+QDcc5oRbZGgRZSz561eR8XVizXCeGpoZKo33NU= +github.com/aws/aws-sdk-go v1.44.194/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI= github.com/aws/aws-sdk-go-v2 v0.18.0/go.mod h1:JWVYvqSMppoMJC0x5wdwiImzgXTI9FuZwxzkQq9wy+g= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= @@ -244,8 +244,8 @@ github.com/gobwas/pool v0.2.0 h1:QEmUOlnSjWtnpRGHF3SauEiOsy82Cup83Vf2LcMlnc8= github.com/gobwas/pool v0.2.0/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw= github.com/gobwas/ws v1.0.2 h1:CoAavW/wd/kulfZmSIBt6p24n4j7tHgNVCjsfHVNUbo= github.com/gobwas/ws v1.0.2/go.mod h1:szmBTxLgaFppYjEmNtny/v3w89xOydFnnZMcgRRu/EM= -github.com/gofrs/uuid v4.3.1+incompatible h1:0/KbAdpx3UXAx1kEOWHJeOkpbgRFGHVgv+CFIY7dBJI= -github.com/gofrs/uuid v4.3.1+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= +github.com/gofrs/uuid v4.4.0+incompatible h1:3qXRTX8/NbyulANqlc0lchS1gqAVxRgsuW1YrTJupqA= +github.com/gofrs/uuid v4.4.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= github.com/gogo/googleapis v1.1.0/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= @@ -395,10 +395,10 @@ github.com/improbable-eng/grpc-web v0.15.0 h1:BN+7z6uNXZ1tQGcNAuaU1YjsLTApzkjt2t github.com/improbable-eng/grpc-web v0.15.0/go.mod h1:1sy9HKV4Jt9aEs9JSnkWlRJPuPtwNr0l57L4f878wP8= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo= -github.com/itchyny/gojq v0.12.9 h1:biKpbKwMxVYhCU1d6mR7qMr3f0Hn9F5k5YykCVb3gmM= -github.com/itchyny/gojq v0.12.9/go.mod h1:T4Ip7AETUXeGpD+436m+UEl3m3tokRgajd5pRfsR5oE= -github.com/itchyny/timefmt-go v0.1.4 h1:hFEfWVdwsEi+CY8xY2FtgWHGQaBaC3JeHd+cve0ynVM= -github.com/itchyny/timefmt-go v0.1.4/go.mod h1:nEP7L+2YmAbT2kZ2HfSs1d8Xtw9LY8D2stDBckWakZ8= +github.com/itchyny/gojq v0.12.11 h1:YhLueoHhHiN4mkfM+3AyJV6EPcCxKZsOnYf+aVSwaQw= +github.com/itchyny/gojq v0.12.11/go.mod h1:o3FT8Gkbg/geT4pLI0tF3hvip5F3Y/uskjRz9OYa38g= +github.com/itchyny/timefmt-go v0.1.5 h1:G0INE2la8S6ru/ZI5JecgyzbbJNs5lG1RcBqa7Jm6GE= +github.com/itchyny/timefmt-go v0.1.5/go.mod h1:nEP7L+2YmAbT2kZ2HfSs1d8Xtw9LY8D2stDBckWakZ8= github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg= github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= From 520721d20f6a75b7704544ef78a566c98d523edc Mon Sep 17 00:00:00 2001 From: oscar Date: Mon, 6 Feb 2023 17:29:11 +0100 Subject: [PATCH 19/43] feat: docker legacy --- lib/backend/iaas/userdata/prepare_debug.go | 3 +- .../resources/operations/embeddedfeatures.go | 28 +- .../embeddedfeatures/docker-legacy.yml | 338 ++++++++++++++++++ 3 files changed, 353 insertions(+), 16 deletions(-) create mode 100644 lib/backend/resources/operations/embeddedfeatures/docker-legacy.yml diff --git a/lib/backend/iaas/userdata/prepare_debug.go b/lib/backend/iaas/userdata/prepare_debug.go index a34d5e000..58a32daeb 100644 --- a/lib/backend/iaas/userdata/prepare_debug.go +++ b/lib/backend/iaas/userdata/prepare_debug.go @@ -92,7 +92,7 @@ var ( } userdataScriptTemplatesLock sync.RWMutex userdataScriptProvider string - userdataScripts = map[Phase]string{ // FIXME: OPP Time to read this shit from a directory + userdataScripts = map[Phase]string{ PHASE1_INIT: "newscripts/userdata%s.init.sh", PHASE2_NETWORK_AND_SECURITY: "newscripts/userdata%s.netsec.sh", PHASE3_GATEWAY_HIGH_AVAILABILITY: "newscripts/userdata%s.gwha.sh", @@ -259,6 +259,7 @@ func (ud *Content) Generate(phase Phase) ([]byte, fail.Error) { return nil, fail.NewError("error loading template for phase '%s'", phase) } } else { + // FIXME: OPP If /tmp/+ userdataScripts[phase] exists, use the local file var tmplString []byte tmplString, err = scripts.ReadFile(fmt.Sprintf(userdataScripts[phase], userdataScriptProvider)) if err != nil { diff --git a/lib/backend/resources/operations/embeddedfeatures.go b/lib/backend/resources/operations/embeddedfeatures.go index 86fdce5c5..6ffb129f4 100755 --- a/lib/backend/resources/operations/embeddedfeatures.go +++ b/lib/backend/resources/operations/embeddedfeatures.go @@ -96,6 +96,18 @@ func dockerFeature() *FeatureFile { return newFeatureFile(filename, name, true, specs) } +// dockerFeature ... +func dockerLegacyFeature() *FeatureFile { + name := "docker-legacy" + filename, specs, err := loadSpecFile(name) + err = debug.InjectPlannedError(err) + if err != nil { + panic(err.Error()) + } + + return newFeatureFile(filename, name, true, specs) +} + // dockerSwarmFeature ... func dockerSwarmFeature() *FeatureFile { name := "docker-swarm" @@ -256,6 +268,7 @@ func init() { allEmbeddedFeatures = []*FeatureFile{ dockerFeature(), dockerSwarmFeature(), + dockerLegacyFeature(), ntpServerFeature(), ntpClientFeature(), ansibleFeature(), @@ -263,28 +276,13 @@ func init() { certificateAuthorityFeature(), // postgresql4platformFeature(), nVidiaDockerFeature(), - // mpichOsPkgFeature(), - // mpichBuildFeature(), - // ohpcSlurmMasterFeature(), - // ohpcSlurmNodeFeature(), remoteDesktopFeature(), postgres4gatewayFeature(), edgeproxy4subnetFeature(), // keycloak4platformFeature(), kubernetesFeature(), - // apacheIgniteFeature(), - // elasticsearchFeature(), - // logstashFeature(), - // metricbeatFeature(), - // filebeatFeature(), - // kibanaFeature(), helm2Feature(), helm3Feature(), - // sparkmaster4platformFeature(), - // elassandraFeature(), - // consul4platformFeature(), - // monitoring4platformFeature(), - // geoserverFeature(), } for _, item := range allEmbeddedFeatures { diff --git a/lib/backend/resources/operations/embeddedfeatures/docker-legacy.yml b/lib/backend/resources/operations/embeddedfeatures/docker-legacy.yml new file mode 100644 index 000000000..6727e2678 --- /dev/null +++ b/lib/backend/resources/operations/embeddedfeatures/docker-legacy.yml @@ -0,0 +1,338 @@ +# +# Copyright 2018-2023, CS Systemes d'Information, http://www.c-s.fr +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +--- +feature: + suitableFor: + host: all + cluster: all + + parameters: + - name: DockerComposeVersion + value: latest + description: |- + docker-compose version to install (default: latest) + control: | + VERSION="{{.ParameterValue}}" + if [[ "latest" = "${VERSION}" ]]; then + VERSION=$(sfRetry "curl -kSsL https://api.github.com/repos/docker/compose/releases/latest | jq -r .name") && op=$? || true + [ $op -ne 0 ] && sfFail 192 "error getting latest docker-compose version" + fi + echo $VERSION + sfExit 0 + - name: DockerHubUsername + value: '' + description: |- + Username to use to authenticate DockerHub (default: empty, disabling authentication) + - name: DockerHubPassword + value: '' + description: |- + Password to use to authenticate DockerHub (default: empty, useless if DockerHubUsername is empty) + install: + bash: + check: + pace: pkg + steps: + pkg: + targets: + hosts: all + gateways: all + masters: all + nodes: all + run: | + case $LINUX_KIND in + debian|ubuntu) + dpkg -l | grep docker-ce &>/dev/null || sfFail 194 "package docker-ce not found" + docker ps &>/dev/null || sfFail 1 "Docker daemon not running" + rm -f /tmp/docker-fail.txt || true + op=-1 + sfRetryEx 5m 5 docker pull hello-world 2>/tmp/docker-fail.txt && op=$? || op=$? + if [[ $op -ne 0 ]]; then + sfFail $op "$(cat /tmp/docker-fail.txt)" + fi + rm -f /tmp/docker-fail.txt || true + docker run hello-world | grep "working correctly" || sfFail 211 "failure running hello-world docker image" + ;; + centos|redhat|rhel) + rpm -qa | grep docker-ce &>/dev/null || sfFail 194 "package docker-ce not found" + docker ps &>/dev/null || sfFail 1 "Docker daemon not running" + rm -f /tmp/docker-fail.txt || true + op=-1 + sfRetryEx 5m 5 docker pull hello-world 2>/tmp/docker-fail.txt && op=$? || op=$? + if [[ $op -ne 0 ]]; then + sfFail $op "$(cat /tmp/docker-fail.txt)" + fi + rm -f /tmp/docker-fail.txt || true + docker run hello-world | grep "working correctly" || sfFail 211 "failure running hello-world docker image" + ;; + fedora) + rpm -qa | grep docker-ce &>/dev/null || sfFail 194 "package docker-ce not found" + docker ps &>/dev/null || sfFail 1 "Docker daemon not running" + rm -f /tmp/docker-fail.txt || true + op=-1 + sfRetryEx 5m 5 docker pull hello-world 2>/tmp/docker-fail.txt && op=$? || op=$? + if [[ $op -ne 0 ]]; then + sfFail $op "$(cat /tmp/docker-fail.txt)" + fi + rm -f /tmp/docker-fail.txt || true + docker run hello-world | grep "working correctly" || sfFail 211 "failure running hello-world docker image" + ;; + *) + echo "Unsupported operating system '$LINUX_KIND'" + sfFail 195 "Unsupported operating system '$LINUX_KIND'" + ;; + esac + sfExit + add: + pace: cleanup,docker-ce,docker-compose,config,firewall,enable,verify,docker-login + steps: + cleanup: + targets: + hosts: all + gateways: all + masters: all + nodes: all + run: | + case $LINUX_KIND in + debian|ubuntu) + export DEBIAN_FRONTEND=noninteractive + sfRetry "sfApt update" + sfRetry "dpkg --remove --force-remove-reinstreq docker docker-engine docker.io containerd runc" + ;; + centos|redhat) + sfRetry "yum remove -y docker docker-client docker-client-latest \ + docker-common docker-latest docker-latest-logrotate \ + docker-logrotate docker-engine" + ;; + fedora) + sfRetry "dnf remove -y docker docker-client docker-client-latest docker-common \ + docker-latest docker-latest-logrotate docker-logrotate \ + docker-selinux docker-engine-selinux docker-engine" + ;; + *) + echo "Unsupported operating system '$LINUX_KIND'" + sfFail 192 "Unsupported operating system '$LINUX_KIND'" + ;; + esac + sfExit + docker-ce: + targets: + hosts: all + gateways: all + masters: all + nodes: all + run: | + case $LINUX_KIND in + debian) + export DEBIAN_FRONTEND=noninteractive + sfFail 192 "Enjoy the silence" + ;; + ubuntu) + export DEBIAN_FRONTEND=noninteractive + sfFail 192 "Enjoy the silence" + ;; + centos|redhat|rhel|fedora) + wget https://download.docker.com/linux/centos/7/x86_64/stable/Packages/docker-ce-17.09.0.ce-1.el7.centos.x86_64.rpm + sudo yum install -y ./docker-ce-17.09.0.ce-1.el7.centos.x86_64.rpm + ;; + *) + echo "Unsupported operating system '$LINUX_KIND'" + sfFail 205 "Unsupported operating system '$LINUX_KIND'" + ;; + esac + sfExit + docker-compose: + targets: + hosts: all + gateways: all + masters: all + nodes: all + run: | + op=-1 + VERSION="{{.DockerComposeVersion}}" + if [[ "latest" = "${VERSION}" ]]; then + VERSION=$(curl -kSsL https://api.github.com/repos/docker/compose/releases/latest | jq -r .name) && op=$? || true + [ $op -ne 0 ] && sfFail 206 "error getting latest docker-compose version" + fi + echo "docker-compose version=$VERSION" + URL="https://github.com/docker/compose/releases/download/${VERSION}/docker-compose-$(uname -s)-$(uname -m)" + sfDownload "$URL" docker-compose 3m 5 || sfFail 207 "error downloading last docker-compose ${VERSION}" + chmod +x docker-compose && mv docker-compose /usr/bin + sfExit + config: + targets: + hosts: all + gateways: all + masters: all + nodes: all + run: | + mkdir -p /etc/docker + if [ "$(sfGetFact use_systemd)" = "1" ]; then + DRIVER=systemd + else + DRIVER=cgroupfs + fi + if [ "$(sfGetFact redhat_like)" = "1" ]; then + cat > /etc/docker/daemon.json <<-EOF + { + "iptables": false, + "exec-opts": [ + "native.cgroupdriver=${DRIVER}" + ], + "no-new-privileges": false, + "log-driver": "json-file", + "log-level":"info", + "log-opts": { + "max-size": "100m" + }, + "experimental": true, + "metrics-addr": "0.0.0.0:9323", + "storage-driver": "overlay2", + "userland-proxy": false, + "storage-opts": [ + "overlay2.override_kernel_check=true" + ] + } + EOF + else + # VPL: these options seems to trouble docker in some cases. Need further analysis. + # "exec-opts": [ + # "native.cgroupdriver=${DRIVER}" + # ], + cat > /etc/docker/daemon.json <<-EOF + { + "no-new-privileges": false, + "log-driver": "json-file", + "log-level":"info", + "log-opts": { + "max-size": "100m" + }, + "experimental": true, + "metrics-addr": "0.0.0.0:9323", + "storage-driver": "overlay2" + } + EOF + fi + sfExit + firewall: + targets: + gateways: all + hosts: all + masters: all + nodes: all + run: | + # First once dockerd, allowing it to create needed firewalld zone docker... + sfFirewallReload || sfFail 208 "failed to reload firewalld, ensuring it works correctly" + sfService restart docker || sfFail 209 "failed to restart dockerd for the first time" + # ... and if no such zone is created, create needed firewalld rules + # FIXME: it should be better to create a configuration identical to the one created by docker 20.10+... + sfFirewall --info-zone=docker 2>&1 >/dev/null || { + sfFirewallAdd --zone=trusted --add-interface=docker0 + sfFirewallAdd --zone=trusted --add-masquerade + sfFirewallReload || sfFail 210 "Firewall problem" + } + + sfExit + enable: + targets: + gateways: all + hosts: all + masters: all + nodes: all + run: | + sfService enable docker || sfFail 211 + sfService restart docker || sfFail 212 + sleep {{ or .reserved_DefaultDelay 10 }} + op=-1 + sfService status docker &>/dev/null && op=$? || true + [ $op -ne 0 ] && sfFail 213 + sfExit + verify: + targets: + gateways: all + hosts: all + masters: all + nodes: all + run: | + sleep {{ or .reserved_DefaultDelay 10 }} + rm -f /tmp/docker-fail.txt || true + op=-1 + sfRetryEx 5m 5 "docker pull hello-world 2>>/tmp/docker-fail.txt 7>>/tmp/docker-fail.txt" && op=$? || op=$? + if [[ $op -ne 0 ]]; then + sfFail 214 "$(cat /tmp/docker-fail.txt)\nexit code $op" + fi + rm -f /tmp/docker-fail.txt || true + docker run hello-world | grep "working correctly" || sfFail 215 "failure running hello-world docker image" + sfExit + docker-login: + targets: + gateways: all + hosts: all + masters: all + nodes: all + run: | + rm -f /tmp/docker-fail.txt || true + if [[ "{{.DockerHubUsername}}" != "" ]]; then + docker login --username="{{.DockerHubUsername}}" --password-stdin <<< "{{.DockerHubPassword}}" > /tmp/docker-fail.txt + if [[ "$(cat /tmp/docker-fail.txt)" != "Login Succeeded" ]]; then + sfFail 216 "$(cat /tmp/docker-fail.txt)" + fi + fi + rm -f /tmp/docker-fail.txt || true + sfExit + remove: + pace: docker-logout,cleanup + steps: + docker-logout: + targets: + gateways: all + hosts: all + masters: all + nodes: all + run: | + if [[ "{{.DockerHubUsername}}" != "" ]]; then + docker logout + fi + sfExit + cleanup: + targets: + gateways: all + hosts: all + masters: all + nodes: all + run: | + sfService disable docker + sfService stop docker + sfFirewallAdd --zone=trusted --remove-interface=docker0 --remove-interface=docker_gwbridge + sfFirewallReload || sfFail 192 "Firewall problem" + case $LINUX_KIND in + debian|ubuntu) + dpkg --purge --force-remove-reinstreq docker-ce docker-ce-cli docker-ce-rootless-extras + ;; + centos|redhat|rhel) + yum remove -y docker-ce* + ;; + fedora) + dnf remove -y docker-ce* + ;; + *) + echo "Unsupported operating system '$LINUX_KIND'" + sfFail 193 "Unsupported operating system '$LINUX_KIND'" + ;; + esac + rm -f /usr/bin/docker-compose || true + sfExit +... From ce8a179f09818706490055b7f2e5e955abdc7884 Mon Sep 17 00:00:00 2001 From: oscar Date: Tue, 7 Feb 2023 15:40:03 +0100 Subject: [PATCH 20/43] feat: tenant inspect now works on all tenants and without setting a tenant first --- cli/safescaled/main.go | 2 +- lib/backend/handlers/securitygroup.go | 1 - lib/backend/handlers/tenant.go | 22 +++++++++----- lib/backend/iaas/service.go | 11 ------- lib/backend/iaas/stacks/gcp/securitygroup.go | 2 +- lib/backend/listeners/jobmanager.go | 17 +++++++++++ lib/backend/listeners/securitygroup.go | 30 ------------------- lib/backend/listeners/tenant.go | 4 +-- .../resources/operations/feature_test.go | 4 +-- lib/backend/resources/operations/tenant.go | 23 ++++++++++++-- lib/system/scripts/bash_library.sh | 10 ------- 11 files changed, 58 insertions(+), 68 deletions(-) diff --git a/cli/safescaled/main.go b/cli/safescaled/main.go index a05e2b857..86c8fc12e 100644 --- a/cli/safescaled/main.go +++ b/cli/safescaled/main.go @@ -114,7 +114,7 @@ func work(c *cli.Context) { s := createGrpcServer() ns, xerr := buildGRPCWebServer(s) if xerr != nil { - logrus.Fatalf("failed to build grpcwebshit: %v", xerr) + logrus.Fatalf("failed to build grpcweb server: %v", xerr) } go func() { diff --git a/lib/backend/handlers/securitygroup.go b/lib/backend/handlers/securitygroup.go index 5f43ea1cb..1554dd533 100644 --- a/lib/backend/handlers/securitygroup.go +++ b/lib/backend/handlers/securitygroup.go @@ -41,7 +41,6 @@ type SecurityGroupHandler interface { Inspect(sgRef string) (resources.SecurityGroup, fail.Error) List(all bool) ([]*abstract.SecurityGroup, fail.Error) Reset(sgRef string) fail.Error - // Sanitize(sgRef string) (ferr fail.Error) } type securityGroupHandler struct { diff --git a/lib/backend/handlers/tenant.go b/lib/backend/handlers/tenant.go index 05dbdb90a..fb959f3c5 100644 --- a/lib/backend/handlers/tenant.go +++ b/lib/backend/handlers/tenant.go @@ -19,6 +19,7 @@ package handlers import ( "context" "fmt" + "github.com/CS-SI/SafeScale/v22/lib/backend/resources/operations" "math" "os" "reflect" @@ -144,6 +145,7 @@ var cmd = fmt.Sprintf("export LANG=C;echo $(%s)î$(%s)î$(%s)î$(%s)î$(%s)î$(% type TenantHandler interface { Scan(string, bool, []string) (*protocol.ScanResultList, fail.Error) Inspect(string) (*protocol.TenantInspectResponse, fail.Error) + SetCurrentTenant(context.Context, string) fail.Error } // tenantHandler service @@ -158,6 +160,15 @@ func NewTenantHandler(job backend.Job) TenantHandler { return &tenantHandler{job: job} } +func (handler *tenantHandler) SetCurrentTenant(inctx context.Context, name string) fail.Error { + xerr := operations.SetCurrentTenant(inctx, name) + if xerr != nil { + return fail.ConvertError(xerr) + } + + return nil +} + // Inspect displays tenant configuration func (handler *tenantHandler) Inspect(tenantName string) (_ *protocol.TenantInspectResponse, ferr fail.Error) { defer func() { @@ -176,15 +187,12 @@ func (handler *tenantHandler) Inspect(tenantName string) (_ *protocol.TenantInsp return nil, fail.InvalidParameterError("tenant name", "cannot be empty string") } - svc := handler.job.Service() - currentName, err := svc.GetName() - if err != nil { - return nil, err - } - if tenantName != currentName { - return nil, fail.NewError("we only inspect current tenant right now") // FIXME: OPP It has to change now + xpc, aerr := operations.LoadTenant(handler.job.Context(), tenantName) + if aerr != nil { + return nil, fail.ConvertError(aerr) } + svc := xpc.Service ctx := handler.job.Context() fromParams := func(in map[string]interface{}, key1 string, key2 string) string { diff --git a/lib/backend/iaas/service.go b/lib/backend/iaas/service.go index cdc992e6d..feb43c978 100644 --- a/lib/backend/iaas/service.go +++ b/lib/backend/iaas/service.go @@ -1044,17 +1044,6 @@ func (instance service) ListHostsWithTags(inctx context.Context, labels []string } -// TenantCleanup removes everything related to SafeScale from tenant (mainly metadata) -// if force equals false and there is metadata, returns an error -// WARNING: !!! this will make SafeScale unable to handle the resources !!! -func (instance service) TenantCleanup(ctx context.Context, force bool) fail.Error { - if valid.IsNil(instance) { - return fail.InvalidInstanceError() - } - - return fail.NotImplementedError("service.TenantCleanup() not yet implemented") // FIXME: Technical debt -} - // LookupRuleInSecurityGroup checks if a rule is already in Security Group rules func (instance service) LookupRuleInSecurityGroup( inctx context.Context, asg *abstract.SecurityGroup, rule *abstract.SecurityGroupRule, diff --git a/lib/backend/iaas/stacks/gcp/securitygroup.go b/lib/backend/iaas/stacks/gcp/securitygroup.go index f4a07194b..a3cd57895 100644 --- a/lib/backend/iaas/stacks/gcp/securitygroup.go +++ b/lib/backend/iaas/stacks/gcp/securitygroup.go @@ -212,7 +212,7 @@ func (s stack) InspectSecurityGroup(ctx context.Context, sgParam stacks.Security } // FIXME: This is a mistake - return asg, fail.NotImplementedError("no real Security Group resource proposed by gcp") // FIXME: Technical debt + return asg, fail.NewError("no real Security Group resource proposed by gcp") // FIXME: Technical debt } // ClearSecurityGroup removes all rules but keep group diff --git a/lib/backend/listeners/jobmanager.go b/lib/backend/listeners/jobmanager.go index d37f752c9..a32f26828 100644 --- a/lib/backend/listeners/jobmanager.go +++ b/lib/backend/listeners/jobmanager.go @@ -55,6 +55,7 @@ func PrepareJob(ctx context.Context, tenantID string, jobDescription string) (_ return nil, fail.NotFoundError("no tenant set") } } + newctx, cancel := context.WithCancel(ctx) job, xerr := backend.NewJob(newctx, cancel, tenant.Service, jobDescription) if xerr != nil { @@ -64,6 +65,22 @@ func PrepareJob(ctx context.Context, tenantID string, jobDescription string) (_ return job, nil } +func PrepareInspectionJob(ctx context.Context, tenantID string, jobDescription string) (_ backend.Job, ferr fail.Error) { + defer fail.OnPanic(&ferr) + + if ctx == nil { + return nil, fail.InvalidParameterCannotBeNilError("ctx") + } + + newctx, cancel := context.WithCancel(ctx) + job, xerr := backend.NewJob(newctx, cancel, nil, jobDescription) + if xerr != nil { + return nil, xerr + } + + return job, nil +} + // JobManagerListener service server gRPC type JobManagerListener struct { protocol.UnimplementedJobServiceServer diff --git a/lib/backend/listeners/securitygroup.go b/lib/backend/listeners/securitygroup.go index e6a400ee5..c37dfd279 100644 --- a/lib/backend/listeners/securitygroup.go +++ b/lib/backend/listeners/securitygroup.go @@ -359,36 +359,6 @@ func (s *SecurityGroupListener) DeleteRule(inctx context.Context, in *protocol.S return sgInstance.ToProtocol(ctx) } -// Sanitize checks if provider-side rules are coherent with registered ones in metadata -func (s *SecurityGroupListener) Sanitize(inctx context.Context, in *protocol.Reference) (empty *googleprotobuf.Empty, err error) { // FIXME: Remove this - defer fail.OnExitConvertToGRPCStatus(inctx, &err) - defer fail.OnExitWrapError(inctx, &err, "cannot sanitize security group") - - empty = &googleprotobuf.Empty{} - if s == nil { - return empty, fail.InvalidInstanceError() - } - if in == nil { - return empty, fail.InvalidParameterCannotBeNilError("in") - } - if inctx == nil { - return empty, fail.InvalidParameterCannotBeNilError("inctx") - } - - ref, _ := srvutils.GetReference(in) - if ref == "" { - return nil, fail.InvalidRequestError("neither name nor id given as reference") - } - - job, err := PrepareJob(inctx, in.GetTenantId(), fmt.Sprintf("/securitygroup/%s/sanitize", ref)) - if err != nil { - return nil, err - } - defer job.Close() - - return empty, fail.NotImplementedError("not yet implemented") // FIXME: Technical debt -} - // Bonds lists the resources bound to the Security Group func (s *SecurityGroupListener) Bonds(inctx context.Context, in *protocol.SecurityGroupBondsRequest) (_ *protocol.SecurityGroupBondsResponse, err error) { defer fail.OnExitConvertToGRPCStatus(inctx, &err) diff --git a/lib/backend/listeners/tenant.go b/lib/backend/listeners/tenant.go index edceda520..0d6f96e79 100644 --- a/lib/backend/listeners/tenant.go +++ b/lib/backend/listeners/tenant.go @@ -116,7 +116,7 @@ func (s *TenantListener) Set(inctx context.Context, in *protocol.TenantName) (em return empty, fail.InvalidParameterError("in", "cannot be nil") } defer fail.OnExitLogError(inctx, &err) - // FIXME: OPP Cannot fucking believe it... + // FIXME: OPP This is a very bad practice xerr := operations.SetCurrentTenant(inctx, in.GetName()) if xerr != nil { return empty, xerr @@ -170,7 +170,7 @@ func (s *TenantListener) Inspect(inctx context.Context, in *protocol.TenantName) } name := in.GetName() - job, xerr := PrepareJob(inctx, "", fmt.Sprintf("/tenant/%s/inspect", name)) + job, xerr := PrepareInspectionJob(inctx, "", fmt.Sprintf("/tenant/%s/inspect", name)) if xerr != nil { return nil, xerr } diff --git a/lib/backend/resources/operations/feature_test.go b/lib/backend/resources/operations/feature_test.go index 6aa8ac858..07c14a257 100644 --- a/lib/backend/resources/operations/feature_test.go +++ b/lib/backend/resources/operations/feature_test.go @@ -101,9 +101,9 @@ func TestNewEmbeddedFeature(t *testing.T) { require.Nil(t, err) require.NotNil(t, efe) - shit, err := efe.PrepareParameters(context.Background(), map[string]interface{}{}, nil) + thing, err := efe.PrepareParameters(context.Background(), map[string]interface{}{}, nil) require.Nil(t, err) - require.NotNil(t, shit) + require.NotNil(t, thing) boo := efe.Specs().GetString("feature.install.bash.add.pace") require.NotEmpty(t, boo) diff --git a/lib/backend/resources/operations/tenant.go b/lib/backend/resources/operations/tenant.go index fa40814ec..89e743fb8 100755 --- a/lib/backend/resources/operations/tenant.go +++ b/lib/backend/resources/operations/tenant.go @@ -55,7 +55,7 @@ func CurrentTenant(ctx context.Context) *Tenant { continue } - service, xerr := loadTenant(ctx, name) + service, xerr := loadService(ctx, name) xerr = debug.InjectPlannedFail(xerr) if xerr != nil { debug.IgnoreError2(ctx, xerr) @@ -83,7 +83,7 @@ func SetCurrentTenant(ctx context.Context, tenantName string) error { return nil } - service, xerr := loadTenant(ctx, tenantName) + service, xerr := loadService(ctx, tenantName) xerr = debug.InjectPlannedFail(xerr) if xerr != nil { return xerr @@ -99,7 +99,24 @@ func SetCurrentTenant(ctx context.Context, tenantName string) error { return nil } -func loadTenant(ctx context.Context, tenantName string) (iaas.Service, fail.Error) { +// LoadTenant sets the tenant to use for upcoming commands +func LoadTenant(ctx context.Context, tenantName string) (*Tenant, error) { + service, xerr := loadService(ctx, tenantName) + xerr = debug.InjectPlannedFail(xerr) + if xerr != nil { + return nil, xerr + } + + bucket, xerr := service.GetMetadataBucket(ctx) + if xerr != nil { + return nil, xerr + } + + tenant := &Tenant{Name: tenantName, BucketName: bucket.GetName(), Service: service} + return tenant, nil +} + +func loadService(ctx context.Context, tenantName string) (iaas.Service, fail.Error) { service, xerr := iaas.UseService(ctx, tenantName, MinimumMetadataVersion) xerr = debug.InjectPlannedFail(xerr) if xerr != nil { diff --git a/lib/system/scripts/bash_library.sh b/lib/system/scripts/bash_library.sh index e57cd601f..e90722f9e 100644 --- a/lib/system/scripts/bash_library.sh +++ b/lib/system/scripts/bash_library.sh @@ -1025,16 +1025,6 @@ function sfDetectFacts() { [ -z "$id" ] && id=$(docker ps --filter "name=kong4gateway_proxy_1" {{ "--format '{{.ID}}'" }} 2> /dev/null || true) [ -z "$id" ] && id=$(docker ps --filter "name=kong_proxy_1" {{ "--format '{{.ID}}'" }} 2> /dev/null || true) FACTS["edgeproxy4subnet_docker_id"]=$id - - # VPL: not used anymore - # id=$(docker ps --filter "name=ingress4platform_server_1" {{ "--format '{{.ID}}'" }} 2>/dev/null || true) - # FACTS["ingress4platform_docker_id"]=$id - # - # id=$(docker ps {{ "--format '{{.Names}}:{{.ID}}'" }} 2>/dev/null | grep postgresql4platform_db | cut -d: -f2 || true) - # FACTS["postgresql4platform_docker_id"]=$id - # - # id=$(docker ps {{ "--format '{{.Names}}:{{.ID}}'" }} 2>/dev/null | grep keycloak4platform_server | cut -d: -f2 || true) - # FACTS["keycloak4platform_docker_id"]=$id fi # "Serialize" facts to file From 6057ee8d0ea37d87d0f99dc952aa21a3617af18b Mon Sep 17 00:00:00 2001 From: oscar Date: Tue, 7 Feb 2023 16:08:28 +0100 Subject: [PATCH 21/43] feat: filter marketplace images --- .github/workflows/go-generics.yml | 2 +- .github/workflows/go.yml | 2 +- lib/backend/iaas/providers/aws/aws.go | 4 +--- lib/backend/iaas/stacks/aws/compute.go | 8 +++++++- lib/backend/listeners/tenant.go | 3 --- 5 files changed, 10 insertions(+), 9 deletions(-) diff --git a/.github/workflows/go-generics.yml b/.github/workflows/go-generics.yml index 5a53acd01..369eb2543 100644 --- a/.github/workflows/go-generics.yml +++ b/.github/workflows/go-generics.yml @@ -24,7 +24,7 @@ jobs: strategy: matrix: - go: [ 1.18.4, 1.19, 1.20 ] + go: [ 1.18.4, 1.19 ] tags: [ releasetags, debug, tunnel, generics ] runs-on: ubuntu-latest diff --git a/.github/workflows/go.yml b/.github/workflows/go.yml index 429fcf696..3a14ad8eb 100644 --- a/.github/workflows/go.yml +++ b/.github/workflows/go.yml @@ -25,7 +25,7 @@ jobs: strategy: matrix: - go: [ 1.18.4, 1.19.5, 1.20 ] + go: [ 1.18.4, 1.19.5 ] tags: [ releasetags, debug, tunnel ] runs-on: ubuntu-latest diff --git a/lib/backend/iaas/providers/aws/aws.go b/lib/backend/iaas/providers/aws/aws.go index d0ee79e41..048f3d807 100644 --- a/lib/backend/iaas/providers/aws/aws.go +++ b/lib/backend/iaas/providers/aws/aws.go @@ -86,8 +86,6 @@ func New() providers.Provider { // Build builds a new Client from configuration parameter func (p *provider) Build(params map[string]interface{}) (providers.Provider, fail.Error) { - // tenantName, _ := params["name"].(string) - identityCfg, ok := params["identity"].(map[string]interface{}) if !ok { return &provider{}, fail.SyntaxError("section 'identity' not found in tenants.toml") @@ -117,7 +115,7 @@ func (p *provider) Build(params map[string]interface{}) (providers.Provider, fai } var owners []string - if _, ok = computeCfg["Owners"]; ok { + if _, ok = computeCfg["Owners"]; ok { // FIXME: OPP, undocumented.... ownerList, ok := computeCfg["Owners"].(string) if !ok { logrus.WithContext(context.Background()).Debugf("error reading owners: %v", computeCfg["Owners"]) diff --git a/lib/backend/iaas/stacks/aws/compute.go b/lib/backend/iaas/stacks/aws/compute.go index 2c147a446..2fa0aad07 100644 --- a/lib/backend/iaas/stacks/aws/compute.go +++ b/lib/backend/iaas/stacks/aws/compute.go @@ -23,6 +23,7 @@ import ( "reflect" "regexp" "sort" + "strings" "time" "github.com/CS-SI/SafeScale/v22/lib/utils/valid" @@ -299,7 +300,12 @@ func (s stack) ListImages(ctx context.Context, all bool) (_ []*abstract.Image, f for _, image := range resp { if image != nil { if !aws.BoolValue(image.EnaSupport) { - logrus.Debug("ENA filtering does NOT actually work!") + logrus.WithContext(ctx).Debugf("ENA not enabled: %s", aws.StringValue(image.ImageId)) + continue + } + + if strings.Contains(aws.StringValue(image.ImageOwnerAlias), "aws-marketplace") { + logrus.WithContext(ctx).Debugf("We don't return marketplace images: %s", aws.StringValue(image.ImageId)) continue } diff --git a/lib/backend/listeners/tenant.go b/lib/backend/listeners/tenant.go index 0d6f96e79..a43abeedd 100644 --- a/lib/backend/listeners/tenant.go +++ b/lib/backend/listeners/tenant.go @@ -136,9 +136,6 @@ func (s *TenantListener) Scan(inctx context.Context, in *protocol.TenantScanRequ if in == nil { return nil, fail.InvalidParameterCannotBeNilError("in") } - if in == nil { - return nil, fail.InvalidParameterError("in", "cannot be nil") - } name := in.GetName() job, xerr := PrepareJob(inctx, "", fmt.Sprintf("/tenant/%s/scan", name)) From 04ac730627f916ed84874d3e7fca8d570a910a5c Mon Sep 17 00:00:00 2001 From: oscar Date: Thu, 9 Feb 2023 18:35:30 +0100 Subject: [PATCH 22/43] chore: missing proto files in docker builds --- Dockerfile.current | 1 + Dockerfile.local | 1 + build-safescale-cover-local.sh | 1 + build-safescale-local.sh | 1 + build/Dockerfile | 1 + build/Dockerfile2 | 1 + build/build-safescale.sh | 1 + build/build-safescale2.sh | 1 + 8 files changed, 8 insertions(+) diff --git a/Dockerfile.current b/Dockerfile.current index 23c4f637d..bb215e2f6 100644 --- a/Dockerfile.current +++ b/Dockerfile.current @@ -112,5 +112,6 @@ COPY --from=builder /exported/safescaled /exported/safescaled COPY --from=builder /exported/safescale /exported/safescale COPY --from=builder /exported/go.mod /exported/go.mod COPY --from=builder /exported/go.sum /exported/go.sum +COPY --from=builder /exported/safescale.proto /exported/safescale.proto COPY --from=builder /exported/safescale_pb.js /exported/safescale_pb.js COPY --from=builder /exported/safescale_grpc_web_pb.js /exported/safescale_grpc_web_pb.js diff --git a/Dockerfile.local b/Dockerfile.local index 2c53fbcdd..1ecbc5a84 100644 --- a/Dockerfile.local +++ b/Dockerfile.local @@ -114,5 +114,6 @@ COPY --from=builder /exported/safescaled /exported/safescaled COPY --from=builder /exported/safescale /exported/safescale COPY --from=builder /exported/go.mod /exported/go.mod COPY --from=builder /exported/go.sum /exported/go.sum +COPY --from=builder /exported/safescale.proto /exported/safescale.proto COPY --from=builder /exported/safescale_pb.js /exported/safescale_pb.js COPY --from=builder /exported/safescale_grpc_web_pb.js /exported/safescale_grpc_web_pb.js diff --git a/build-safescale-cover-local.sh b/build-safescale-cover-local.sh index 1f363412a..741e02cf8 100755 --- a/build-safescale-cover-local.sh +++ b/build-safescale-cover-local.sh @@ -64,6 +64,7 @@ CIBIN=/exported make installci force_sdk_python force_sdk_js cp ${WRKDIR}/SafeScale/go.mod /exported cp ${WRKDIR}/SafeScale/go.sum /exported +cp ${WRKDIR}/SafeScale/lib/protocol/safescale.proto /exported cp ${WRKDIR}/SafeScale/lib/protocol/javascript/* /exported cp ${WRKDIR}/SafeScale/lib/protocol/python3/* /exported diff --git a/build-safescale-local.sh b/build-safescale-local.sh index ff1af2dfb..59caefaa3 100755 --- a/build-safescale-local.sh +++ b/build-safescale-local.sh @@ -64,6 +64,7 @@ CIBIN=/exported make installci force_sdk_js force_sdk_python cp ${WRKDIR}/SafeScale/go.mod /exported cp ${WRKDIR}/SafeScale/go.sum /exported +cp ${WRKDIR}/SafeScale/lib/protocol/safescale.proto /exported cp ${WRKDIR}/SafeScale/lib/protocol/javascript/* /exported cp ${WRKDIR}/SafeScale/lib/protocol/python3/* /exported diff --git a/build/Dockerfile b/build/Dockerfile index ca1f139d8..dc880fe24 100644 --- a/build/Dockerfile +++ b/build/Dockerfile @@ -113,5 +113,6 @@ COPY --from=builder /exported/safescaled /exported/safescaled COPY --from=builder /exported/safescale /exported/safescale COPY --from=builder /exported/go.mod /exported/go.mod COPY --from=builder /exported/go.sum /exported/go.sum +COPY --from=builder /exported/safescale.proto /exported/safescale.proto COPY --from=builder /exported/safescale_pb.js /exported/safescale_pb.js COPY --from=builder /exported/safescale_grpc_web_pb.js /exported/safescale_grpc_web_pb.js diff --git a/build/Dockerfile2 b/build/Dockerfile2 index b24c8eb23..29f4929b9 100644 --- a/build/Dockerfile2 +++ b/build/Dockerfile2 @@ -115,5 +115,6 @@ COPY --from=builder /exported-$GOOSX-$GOARCHX/safescaled /exported-$GOOSX-$GOARC COPY --from=builder /exported-$GOOSX-$GOARCHX/safescale /exported-$GOOSX-$GOARCHX/safescale COPY --from=builder /exported-$GOOSX-$GOARCHX/go.mod /exported-$GOOSX-$GOARCHX/go.mod COPY --from=builder /exported-$GOOSX-$GOARCHX/go.sum /exported-$GOOSX-$GOARCHX/go.sum +COPY --from=builder /exported-$GOOSX-$GOARCHX/safescale.proto /exported-$GOOSX-$GOARCHX/safescale.proto COPY --from=builder /exported-$GOOSX-$GOARCHX/safescale_pb.js /exported-$GOOSX-$GOARCHX/safescale_pb.js COPY --from=builder /exported-$GOOSX-$GOARCHX/safescale_grpc_web_pb.js /exported-$GOOSX-$GOARCHX/safescale_grpc_web_pb.js diff --git a/build/build-safescale.sh b/build/build-safescale.sh index a367325ad..cd98347e1 100755 --- a/build/build-safescale.sh +++ b/build/build-safescale.sh @@ -90,6 +90,7 @@ CIBIN=/exported make installci force_sdk_js force_sdk_python cp ${WRKDIR}/SafeScale/go.mod /exported cp ${WRKDIR}/SafeScale/go.sum /exported +cp ${WRKDIR}/SafeScale/lib/protocol/safescale.proto /exported cp ${WRKDIR}/SafeScale/lib/protocol/javascript/* /exported cp ${WRKDIR}/SafeScale/lib/protocol/python3/* /exported diff --git a/build/build-safescale2.sh b/build/build-safescale2.sh index a11f3e120..6bb8ba41c 100755 --- a/build/build-safescale2.sh +++ b/build/build-safescale2.sh @@ -93,6 +93,7 @@ CIBIN=/exported-$GOOS-$GOARCH make installci force_sdk_js force_sdk_python cp ${WRKDIR}/SafeScale/go.mod /exported-$GOOS-$GOARCH cp ${WRKDIR}/SafeScale/go.sum /exported-$GOOS-$GOARCH +cp ${WRKDIR}/SafeScale/lib/protocol/safescale.proto /exported-$GOOS-$GOARCH cp ${WRKDIR}/SafeScale/lib/protocol/javascript/* /exported-$GOOS-$GOARCH cp ${WRKDIR}/SafeScale/lib/protocol/python3/* /exported-$GOOS-$GOARCH From 402bdd0de63c6e11e5a921c09ce7c2b5f3ad11e2 Mon Sep 17 00:00:00 2001 From: oscar Date: Thu, 9 Feb 2023 18:47:10 +0100 Subject: [PATCH 23/43] less retries --- .../iaas/userdata/newscripts/userdata.netsec.sh | 10 +++++----- lib/backend/iaas/userdata/scripts/userdata.netsec.sh | 10 +++++----- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/lib/backend/iaas/userdata/newscripts/userdata.netsec.sh b/lib/backend/iaas/userdata/newscripts/userdata.netsec.sh index 8ec2064f4..99c0b452e 100644 --- a/lib/backend/iaas/userdata/newscripts/userdata.netsec.sh +++ b/lib/backend/iaas/userdata/newscripts/userdata.netsec.sh @@ -105,7 +105,7 @@ function reset_fw() { case $LINUX_KIND in debian) echo "Reset firewall" - sfRetry4 "sfApt update" || failure 207 "reset_fw(): failure running apt update" + sfApt update || failure 207 "reset_fw(): failure running apt update" sfRetry4 "sfApt -y autoclean autoremove" || failure 210 "reset_fw(): failure running cleanup" sfRetry4 "sfApt install -q -y --no-install-recommends iptables" || failure 210 "reset_fw(): failure installing iptables" sfRetry4 "sfApt install -q -y --no-install-recommends firewalld python3" || failure 211 "reset_fw(): failure installing firewalld" @@ -122,7 +122,7 @@ function reset_fw() { ubuntu) echo "Reset firewall" - sfRetry4 "sfApt update" || failure 213 "reset_fw(): failure running apt update" + sfApt update || failure 213 "reset_fw(): failure running apt update" sfRetry4 "sfApt -y autoclean autoremove" || failure 213 "reset_fw(): failure running cleanup" sfRetry4 "sfApt install -q -y --no-install-recommends iptables" || failure 214 "reset_fw(): failure installing iptables" sfRetry4 "sfApt install -q -y --no-install-recommends firewalld python3" || failure 215 "reset_fw(): failure installing firewalld" @@ -1310,7 +1310,7 @@ function install_drivers_nvidia() { ubuntu) sfFinishPreviousInstall add-apt-repository -y ppa:graphics-drivers &> /dev/null - sfRetry4 "sfApt update" || failure 201 "apt update failed" + sfApt update || failure 201 "apt update failed" sfRetry4 "sfApt -y install nvidia-410 &>/dev/null" || { sfRetry4 "sfApt -y install nvidia-driver-410 &>/dev/null" || failure 201 "failed nvidia driver install" } @@ -1321,10 +1321,10 @@ function install_drivers_nvidia() { echo -e "blacklist nouveau\nblacklist lbm-nouveau\noptions nouveau modeset=0\nalias nouveau off\nalias lbm-nouveau off" >> /etc/modprobe.d/blacklist-nouveau.conf rmmod nouveau fi - sfRetry4 "sfApt update" + sfApt update sfRetry4 "sfApt install -y --no-install-recommends dkms build-essential linux-headers-$(uname -r) gcc make &>/dev/null" || failure 202 "failure installing nvdiia requirements" dpkg --add-architecture i386 &> /dev/null - sfRetry4 "sfApt update" + sfApt update sfRetry4 "sfApt install -y --no-install-recommends lib32z1 lib32ncurses5 &>/dev/null" || failure 203 "failure installing nvidia requirements" wget http://us.download.nvidia.com/XFree86/Linux-x86_64/410.78/NVIDIA-Linux-x86_64-410.78.run &> /dev/null || failure 204 "failure downloading nvidia installer" bash NVIDIA-Linux-x86_64-410.78.run -s || failure 205 "failure running nvidia installer" diff --git a/lib/backend/iaas/userdata/scripts/userdata.netsec.sh b/lib/backend/iaas/userdata/scripts/userdata.netsec.sh index 8ec2064f4..99c0b452e 100644 --- a/lib/backend/iaas/userdata/scripts/userdata.netsec.sh +++ b/lib/backend/iaas/userdata/scripts/userdata.netsec.sh @@ -105,7 +105,7 @@ function reset_fw() { case $LINUX_KIND in debian) echo "Reset firewall" - sfRetry4 "sfApt update" || failure 207 "reset_fw(): failure running apt update" + sfApt update || failure 207 "reset_fw(): failure running apt update" sfRetry4 "sfApt -y autoclean autoremove" || failure 210 "reset_fw(): failure running cleanup" sfRetry4 "sfApt install -q -y --no-install-recommends iptables" || failure 210 "reset_fw(): failure installing iptables" sfRetry4 "sfApt install -q -y --no-install-recommends firewalld python3" || failure 211 "reset_fw(): failure installing firewalld" @@ -122,7 +122,7 @@ function reset_fw() { ubuntu) echo "Reset firewall" - sfRetry4 "sfApt update" || failure 213 "reset_fw(): failure running apt update" + sfApt update || failure 213 "reset_fw(): failure running apt update" sfRetry4 "sfApt -y autoclean autoremove" || failure 213 "reset_fw(): failure running cleanup" sfRetry4 "sfApt install -q -y --no-install-recommends iptables" || failure 214 "reset_fw(): failure installing iptables" sfRetry4 "sfApt install -q -y --no-install-recommends firewalld python3" || failure 215 "reset_fw(): failure installing firewalld" @@ -1310,7 +1310,7 @@ function install_drivers_nvidia() { ubuntu) sfFinishPreviousInstall add-apt-repository -y ppa:graphics-drivers &> /dev/null - sfRetry4 "sfApt update" || failure 201 "apt update failed" + sfApt update || failure 201 "apt update failed" sfRetry4 "sfApt -y install nvidia-410 &>/dev/null" || { sfRetry4 "sfApt -y install nvidia-driver-410 &>/dev/null" || failure 201 "failed nvidia driver install" } @@ -1321,10 +1321,10 @@ function install_drivers_nvidia() { echo -e "blacklist nouveau\nblacklist lbm-nouveau\noptions nouveau modeset=0\nalias nouveau off\nalias lbm-nouveau off" >> /etc/modprobe.d/blacklist-nouveau.conf rmmod nouveau fi - sfRetry4 "sfApt update" + sfApt update sfRetry4 "sfApt install -y --no-install-recommends dkms build-essential linux-headers-$(uname -r) gcc make &>/dev/null" || failure 202 "failure installing nvdiia requirements" dpkg --add-architecture i386 &> /dev/null - sfRetry4 "sfApt update" + sfApt update sfRetry4 "sfApt install -y --no-install-recommends lib32z1 lib32ncurses5 &>/dev/null" || failure 203 "failure installing nvidia requirements" wget http://us.download.nvidia.com/XFree86/Linux-x86_64/410.78/NVIDIA-Linux-x86_64-410.78.run &> /dev/null || failure 204 "failure downloading nvidia installer" bash NVIDIA-Linux-x86_64-410.78.run -s || failure 205 "failure running nvidia installer" From 452b767264699189f418069f42feec161a1eafeb Mon Sep 17 00:00:00 2001 From: oscar Date: Thu, 9 Feb 2023 18:50:11 +0100 Subject: [PATCH 24/43] more time to reboot --- lib/backend/resources/operations/host.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/backend/resources/operations/host.go b/lib/backend/resources/operations/host.go index 293210998..5e9406b46 100644 --- a/lib/backend/resources/operations/host.go +++ b/lib/backend/resources/operations/host.go @@ -2176,7 +2176,7 @@ func (instance *Host) finalizeProvisioning(ctx context.Context, hr abstract.Host time.Sleep(timings.RebootTimeout()) } - _, xerr = instance.waitInstallPhase(ctx, userdata.PHASE2_NETWORK_AND_SECURITY, 90*time.Second) // FIXME: It should be 1:30 min tops, 2*reboot time + _, xerr = instance.waitInstallPhase(ctx, userdata.PHASE2_NETWORK_AND_SECURITY, 120*time.Second) // 1:30 was not enough xerr = debug.InjectPlannedFail(xerr) if xerr != nil { return xerr From 88980472eccd8fc6f2603da8906ca0046cfa5ab4 Mon Sep 17 00:00:00 2001 From: oscar Date: Thu, 9 Feb 2023 18:51:05 +0100 Subject: [PATCH 25/43] bug: this assertion was always wrong, so this function was never tested --- lib/backend/resources/operations/securitygroup.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/backend/resources/operations/securitygroup.go b/lib/backend/resources/operations/securitygroup.go index 179e2d47e..c6266501a 100755 --- a/lib/backend/resources/operations/securitygroup.go +++ b/lib/backend/resources/operations/securitygroup.go @@ -543,9 +543,9 @@ func (instance *SecurityGroup) unbindFromSubnets( return fail.InconsistentError("failed to cast value to '*abstract.Subnet'") } } - value = ctx.Value(currentSubnetPropertiesContextKey) - if value != nil { - currentSubnetAbstract, ok = value.(*abstract.Subnet) + vpro := ctx.Value(currentSubnetPropertiesContextKey) + if vpro != nil { + currentSubnetProps, ok = vpro.(*serialize.JSONProperties) if !ok { return fail.InconsistentError("failed to cast value to '*unsafeSerialize.JSONProperties'") } From 6735278d098f1365400b6b09313a8c9e25f44b49 Mon Sep 17 00:00:00 2001 From: oscar Date: Fri, 10 Feb 2023 15:50:38 +0100 Subject: [PATCH 26/43] bug: reintroducing problem in order to keep working as usual --- lib/backend/iaas/stacks/gcp/securitygroup.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/backend/iaas/stacks/gcp/securitygroup.go b/lib/backend/iaas/stacks/gcp/securitygroup.go index a3cd57895..478051cdc 100644 --- a/lib/backend/iaas/stacks/gcp/securitygroup.go +++ b/lib/backend/iaas/stacks/gcp/securitygroup.go @@ -211,8 +211,8 @@ func (s stack) InspectSecurityGroup(ctx context.Context, sgParam stacks.Security return asg, fail.InvalidParameterError("sgParam", "must be consistent") } - // FIXME: This is a mistake - return asg, fail.NewError("no real Security Group resource proposed by gcp") // FIXME: Technical debt + // FIXME: OPP, good behaviour DEPENDS on this + return asg, fail.NotImplementedError("no real Security Group resource proposed by gcp") // FIXME: Technical debt } // ClearSecurityGroup removes all rules but keep group From 0f8dde686c75564f398c34e9ca33376da8e192cf Mon Sep 17 00:00:00 2001 From: oscar Date: Fri, 10 Feb 2023 15:51:57 +0100 Subject: [PATCH 27/43] bug: without this WebUI does NOT work --- lib/backend/iaas/userdata/prepare.go | 3 +++ lib/backend/iaas/userdata/prepare_debug.go | 3 +++ 2 files changed, 6 insertions(+) diff --git a/lib/backend/iaas/userdata/prepare.go b/lib/backend/iaas/userdata/prepare.go index c66ffb1c8..00e3b4a85 100644 --- a/lib/backend/iaas/userdata/prepare.go +++ b/lib/backend/iaas/userdata/prepare.go @@ -195,6 +195,9 @@ func (ud *Content) Prepare( ud.AddGateway = !request.IsGateway && !request.PublicIP && !useLayer3Networking && ip != "" && !useNATService ud.DNSServers = dnsList ud.SSHPort = strconv.Itoa(int(request.SSHPort)) + if request.SSHPort <= 0 { + ud.SSHPort = "22" + } ud.CIDR = cidr ud.DefaultRouteIP = ip ud.Password = request.Password diff --git a/lib/backend/iaas/userdata/prepare_debug.go b/lib/backend/iaas/userdata/prepare_debug.go index 58a32daeb..9b74c4510 100644 --- a/lib/backend/iaas/userdata/prepare_debug.go +++ b/lib/backend/iaas/userdata/prepare_debug.go @@ -195,6 +195,9 @@ func (ud *Content) Prepare( ud.AddGateway = !request.IsGateway && !request.PublicIP && !useLayer3Networking && ip != "" && !useNATService ud.DNSServers = dnsList ud.SSHPort = strconv.Itoa(int(request.SSHPort)) + if request.SSHPort <= 0 { + ud.SSHPort = "22" + } ud.CIDR = cidr ud.DefaultRouteIP = ip ud.Password = request.Password From 04210ce969597b7531657b147495f62b2cb6911b Mon Sep 17 00:00:00 2001 From: oscar Date: Fri, 10 Feb 2023 15:53:11 +0100 Subject: [PATCH 28/43] bug: fixed several script problems in ubuntu OS --- .../userdata/newscripts/userdata.final.sh | 2 +- .../iaas/userdata/newscripts/userdata.init.sh | 4 +- .../userdata/newscripts/userdata.netsec.sh | 48 +++++++++++-------- .../iaas/userdata/scripts/userdata.final.sh | 2 +- .../iaas/userdata/scripts/userdata.init.sh | 4 +- .../iaas/userdata/scripts/userdata.netsec.sh | 48 +++++++++++-------- .../scripts/master_install_ansible.sh | 6 +-- .../scripts/master_install_only_ansible.sh | 6 +-- .../scripts/node_install_docker.sh | 10 ++-- .../operations/embeddedfeatures/ansible.yml | 8 ++-- .../embeddedfeatures/docker-legacy.yml | 2 +- .../operations/embeddedfeatures/docker.yml | 10 ++-- .../embeddedfeatures/kubernetes.yml | 8 ++-- .../operations/embeddedfeatures/ntpclient.yml | 2 +- .../operations/embeddedfeatures/ntpserver.yml | 2 +- .../embeddedfeatures/nvidiadocker.yml | 2 +- .../embeddedfeatures/remotedesktop.yml | 2 +- lib/system/nfs/scripts/nfs_server_install.sh | 2 +- lib/system/scripts/bash_library.sh | 4 +- .../ssh/bycli/command_line_based_ssh.go | 2 - 20 files changed, 94 insertions(+), 80 deletions(-) diff --git a/lib/backend/iaas/userdata/newscripts/userdata.final.sh b/lib/backend/iaas/userdata/newscripts/userdata.final.sh index e94ccaaaa..a00391154 100644 --- a/lib/backend/iaas/userdata/newscripts/userdata.final.sh +++ b/lib/backend/iaas/userdata/newscripts/userdata.final.sh @@ -94,7 +94,7 @@ function install_drivers_nvidia() { ubuntu) sfFinishPreviousInstall add-apt-repository -y ppa:graphics-drivers &> /dev/null - sfApt update || fail 201 "failure running apt update" + sfApt update --allow-insecure-repositories || fail 201 "failure running apt update" sfApt -y install nvidia-410 &> /dev/null || { sfApt -y install nvidia-driver-410 &> /dev/null || fail 201 "failure installing nvidia" } diff --git a/lib/backend/iaas/userdata/newscripts/userdata.init.sh b/lib/backend/iaas/userdata/newscripts/userdata.init.sh index 6039218bf..c2458360a 100644 --- a/lib/backend/iaas/userdata/newscripts/userdata.init.sh +++ b/lib/backend/iaas/userdata/newscripts/userdata.init.sh @@ -270,8 +270,8 @@ function remove_setuptools() { debian | ubuntu) # If it's not there, nothing to do sudo dpkg -l python3-setuptools || true - sudo dpkg -l python3-setuptools | grep ii && echo "python3-setuptools already there" - sudo dpkg -l python3-setuptools | grep ii && sudo apt-get remove -y python3-setuptools + sudo dpkg -l python3-setuptools | grep -E '^hi|^ii' && echo "python3-setuptools already there" + sudo dpkg -l python3-setuptools | grep -E '^hi|^ii' && sudo apt-get remove -y python3-setuptools ;; redhat | fedora | centos) sfYum remove -y python3-setuptools || true diff --git a/lib/backend/iaas/userdata/newscripts/userdata.netsec.sh b/lib/backend/iaas/userdata/newscripts/userdata.netsec.sh index 99c0b452e..fb7c71363 100644 --- a/lib/backend/iaas/userdata/newscripts/userdata.netsec.sh +++ b/lib/backend/iaas/userdata/newscripts/userdata.netsec.sh @@ -105,8 +105,7 @@ function reset_fw() { case $LINUX_KIND in debian) echo "Reset firewall" - sfApt update || failure 207 "reset_fw(): failure running apt update" - sfRetry4 "sfApt -y autoclean autoremove" || failure 210 "reset_fw(): failure running cleanup" + sfApt update --allow-insecure-repositories sfRetry4 "sfApt install -q -y --no-install-recommends iptables" || failure 210 "reset_fw(): failure installing iptables" sfRetry4 "sfApt install -q -y --no-install-recommends firewalld python3" || failure 211 "reset_fw(): failure installing firewalld" @@ -122,8 +121,7 @@ function reset_fw() { ubuntu) echo "Reset firewall" - sfApt update || failure 213 "reset_fw(): failure running apt update" - sfRetry4 "sfApt -y autoclean autoremove" || failure 213 "reset_fw(): failure running cleanup" + sfApt update --allow-insecure-repositories sfRetry4 "sfApt install -q -y --no-install-recommends iptables" || failure 214 "reset_fw(): failure installing iptables" sfRetry4 "sfApt install -q -y --no-install-recommends firewalld python3" || failure 215 "reset_fw(): failure installing firewalld" @@ -1310,7 +1308,7 @@ function install_drivers_nvidia() { ubuntu) sfFinishPreviousInstall add-apt-repository -y ppa:graphics-drivers &> /dev/null - sfApt update || failure 201 "apt update failed" + sfApt update --allow-insecure-repositories || failure 201 "apt update failed" sfRetry4 "sfApt -y install nvidia-410 &>/dev/null" || { sfRetry4 "sfApt -y install nvidia-driver-410 &>/dev/null" || failure 201 "failed nvidia driver install" } @@ -1321,10 +1319,10 @@ function install_drivers_nvidia() { echo -e "blacklist nouveau\nblacklist lbm-nouveau\noptions nouveau modeset=0\nalias nouveau off\nalias lbm-nouveau off" >> /etc/modprobe.d/blacklist-nouveau.conf rmmod nouveau fi - sfApt update + sfApt update --allow-insecure-repositories sfRetry4 "sfApt install -y --no-install-recommends dkms build-essential linux-headers-$(uname -r) gcc make &>/dev/null" || failure 202 "failure installing nvdiia requirements" dpkg --add-architecture i386 &> /dev/null - sfApt update + sfApt update --allow-insecure-repositories sfRetry4 "sfApt install -y --no-install-recommends lib32z1 lib32ncurses5 &>/dev/null" || failure 203 "failure installing nvidia requirements" wget http://us.download.nvidia.com/XFree86/Linux-x86_64/410.78/NVIDIA-Linux-x86_64-410.78.run &> /dev/null || failure 204 "failure downloading nvidia installer" bash NVIDIA-Linux-x86_64-410.78.run -s || failure 205 "failure running nvidia installer" @@ -1367,7 +1365,7 @@ EOF # # Force use of IPv4 addresses when installing packages # echo 'Acquire::ForceIPv4 "true";' >/etc/apt/apt.conf.d/99force-ipv4 - sfApt update || { + sfApt update --allow-insecure-repositories || { echo "problem updating package repos" return 209 } @@ -1387,7 +1385,7 @@ EOF # # Force use of IPv4 addresses when installing packages # echo 'Acquire::ForceIPv4 "true";' >/etc/apt/apt.conf.d/99force-ipv4 - sfApt update || { + sfApt update --allow-insecure-repositories || { echo "problem updating package repos" return 210 } @@ -1413,37 +1411,47 @@ EOF fi # netplan.io may break networking... So ensure networking is working as expected ensure_network_connectivity - sfApt install -y --no-install-recommends sudo || { + sfApt install -y --no-install-recommends --allow-change-held-packages sudo || { echo "problem installing sudo" return 210 } else - sfApt install -y --no-install-recommends systemd pciutils sudo || { + sfApt install -y --no-install-recommends pciutils sudo || { echo "problem installing pciutils and sudo" return 211 } + dpkg -l systemd | tail -n 1 | grep -E '^hi|^ii' || { + sfApt install -y --no-install-recommends systemd || { + echo "problem installing systemd" + return 210 + } + } fi if dpkg --compare-versions $(sfGetFact "linux_version") ge 20.04; then if [ "{{.ProviderName}}" == "aws" ]; then : # do nothing else + dpkg -l systemd | tail -n 1 | grep -E '^hi|^ii' || { + sfApt install -y --no-install-recommends systemd || { + echo "problem installing systemd" + return 210 + } + } + fi + else + dpkg -l systemd | tail -n 1 | grep -E '^hi|^ii' || { sfApt install -y --no-install-recommends systemd || { echo "problem installing systemd" return 210 } - fi - else - sfApt install -y --no-install-recommends systemd || { - echo "problem installing systemd" - return 210 } # systemd, if updated, is restarted, so we may need to ensure again network connectivity ensure_network_connectivity fi # # Security updates ... - # sfApt update &>/dev/null && sfApt install -qy unattended-upgrades && unattended-upgrades -v + # sfApt update --allow-insecure-repositories &>/dev/null && sfApt install -qy unattended-upgrades && unattended-upgrades -v ;; redhat | centos) @@ -1468,13 +1476,13 @@ EOF function install_packages() { case $LINUX_KIND in ubuntu | debian) - sfApt install -y -qq --no-install-recommends wget curl jq zip unzip time at sshpass &> /dev/null || failure 213 "failure installing utility packages: jq zip time at" + sfApt install -y -qq --no-install-recommends wget jq zip unzip time at sshpass &> /dev/null || failure 213 "failure installing utility packages: jq zip time at" ;; redhat | centos) if [ $(versionchk ${VERSION_ID}) -ge $(versionchk "8.0") ]; then - sfYum install -y -q wget curl jq zip unzip time at sshpass &> /dev/null || failure 214 "failure installing utility packages: jq zip time at" + sfYum install -y -q wget jq zip unzip time at sshpass &> /dev/null || failure 214 "failure installing utility packages: jq zip time at" else - sfYum install --enablerepo=epel -y -q wget curl jq zip unzip time at sshpass &> /dev/null || failure 214 "failure installing utility packages: jq zip time at" + sfYum install --enablerepo=epel -y -q wget jq zip unzip time at sshpass &> /dev/null || failure 214 "failure installing utility packages: jq zip time at" fi ;; *) diff --git a/lib/backend/iaas/userdata/scripts/userdata.final.sh b/lib/backend/iaas/userdata/scripts/userdata.final.sh index e94ccaaaa..a00391154 100644 --- a/lib/backend/iaas/userdata/scripts/userdata.final.sh +++ b/lib/backend/iaas/userdata/scripts/userdata.final.sh @@ -94,7 +94,7 @@ function install_drivers_nvidia() { ubuntu) sfFinishPreviousInstall add-apt-repository -y ppa:graphics-drivers &> /dev/null - sfApt update || fail 201 "failure running apt update" + sfApt update --allow-insecure-repositories || fail 201 "failure running apt update" sfApt -y install nvidia-410 &> /dev/null || { sfApt -y install nvidia-driver-410 &> /dev/null || fail 201 "failure installing nvidia" } diff --git a/lib/backend/iaas/userdata/scripts/userdata.init.sh b/lib/backend/iaas/userdata/scripts/userdata.init.sh index 6039218bf..c2458360a 100644 --- a/lib/backend/iaas/userdata/scripts/userdata.init.sh +++ b/lib/backend/iaas/userdata/scripts/userdata.init.sh @@ -270,8 +270,8 @@ function remove_setuptools() { debian | ubuntu) # If it's not there, nothing to do sudo dpkg -l python3-setuptools || true - sudo dpkg -l python3-setuptools | grep ii && echo "python3-setuptools already there" - sudo dpkg -l python3-setuptools | grep ii && sudo apt-get remove -y python3-setuptools + sudo dpkg -l python3-setuptools | grep -E '^hi|^ii' && echo "python3-setuptools already there" + sudo dpkg -l python3-setuptools | grep -E '^hi|^ii' && sudo apt-get remove -y python3-setuptools ;; redhat | fedora | centos) sfYum remove -y python3-setuptools || true diff --git a/lib/backend/iaas/userdata/scripts/userdata.netsec.sh b/lib/backend/iaas/userdata/scripts/userdata.netsec.sh index 99c0b452e..fb7c71363 100644 --- a/lib/backend/iaas/userdata/scripts/userdata.netsec.sh +++ b/lib/backend/iaas/userdata/scripts/userdata.netsec.sh @@ -105,8 +105,7 @@ function reset_fw() { case $LINUX_KIND in debian) echo "Reset firewall" - sfApt update || failure 207 "reset_fw(): failure running apt update" - sfRetry4 "sfApt -y autoclean autoremove" || failure 210 "reset_fw(): failure running cleanup" + sfApt update --allow-insecure-repositories sfRetry4 "sfApt install -q -y --no-install-recommends iptables" || failure 210 "reset_fw(): failure installing iptables" sfRetry4 "sfApt install -q -y --no-install-recommends firewalld python3" || failure 211 "reset_fw(): failure installing firewalld" @@ -122,8 +121,7 @@ function reset_fw() { ubuntu) echo "Reset firewall" - sfApt update || failure 213 "reset_fw(): failure running apt update" - sfRetry4 "sfApt -y autoclean autoremove" || failure 213 "reset_fw(): failure running cleanup" + sfApt update --allow-insecure-repositories sfRetry4 "sfApt install -q -y --no-install-recommends iptables" || failure 214 "reset_fw(): failure installing iptables" sfRetry4 "sfApt install -q -y --no-install-recommends firewalld python3" || failure 215 "reset_fw(): failure installing firewalld" @@ -1310,7 +1308,7 @@ function install_drivers_nvidia() { ubuntu) sfFinishPreviousInstall add-apt-repository -y ppa:graphics-drivers &> /dev/null - sfApt update || failure 201 "apt update failed" + sfApt update --allow-insecure-repositories || failure 201 "apt update failed" sfRetry4 "sfApt -y install nvidia-410 &>/dev/null" || { sfRetry4 "sfApt -y install nvidia-driver-410 &>/dev/null" || failure 201 "failed nvidia driver install" } @@ -1321,10 +1319,10 @@ function install_drivers_nvidia() { echo -e "blacklist nouveau\nblacklist lbm-nouveau\noptions nouveau modeset=0\nalias nouveau off\nalias lbm-nouveau off" >> /etc/modprobe.d/blacklist-nouveau.conf rmmod nouveau fi - sfApt update + sfApt update --allow-insecure-repositories sfRetry4 "sfApt install -y --no-install-recommends dkms build-essential linux-headers-$(uname -r) gcc make &>/dev/null" || failure 202 "failure installing nvdiia requirements" dpkg --add-architecture i386 &> /dev/null - sfApt update + sfApt update --allow-insecure-repositories sfRetry4 "sfApt install -y --no-install-recommends lib32z1 lib32ncurses5 &>/dev/null" || failure 203 "failure installing nvidia requirements" wget http://us.download.nvidia.com/XFree86/Linux-x86_64/410.78/NVIDIA-Linux-x86_64-410.78.run &> /dev/null || failure 204 "failure downloading nvidia installer" bash NVIDIA-Linux-x86_64-410.78.run -s || failure 205 "failure running nvidia installer" @@ -1367,7 +1365,7 @@ EOF # # Force use of IPv4 addresses when installing packages # echo 'Acquire::ForceIPv4 "true";' >/etc/apt/apt.conf.d/99force-ipv4 - sfApt update || { + sfApt update --allow-insecure-repositories || { echo "problem updating package repos" return 209 } @@ -1387,7 +1385,7 @@ EOF # # Force use of IPv4 addresses when installing packages # echo 'Acquire::ForceIPv4 "true";' >/etc/apt/apt.conf.d/99force-ipv4 - sfApt update || { + sfApt update --allow-insecure-repositories || { echo "problem updating package repos" return 210 } @@ -1413,37 +1411,47 @@ EOF fi # netplan.io may break networking... So ensure networking is working as expected ensure_network_connectivity - sfApt install -y --no-install-recommends sudo || { + sfApt install -y --no-install-recommends --allow-change-held-packages sudo || { echo "problem installing sudo" return 210 } else - sfApt install -y --no-install-recommends systemd pciutils sudo || { + sfApt install -y --no-install-recommends pciutils sudo || { echo "problem installing pciutils and sudo" return 211 } + dpkg -l systemd | tail -n 1 | grep -E '^hi|^ii' || { + sfApt install -y --no-install-recommends systemd || { + echo "problem installing systemd" + return 210 + } + } fi if dpkg --compare-versions $(sfGetFact "linux_version") ge 20.04; then if [ "{{.ProviderName}}" == "aws" ]; then : # do nothing else + dpkg -l systemd | tail -n 1 | grep -E '^hi|^ii' || { + sfApt install -y --no-install-recommends systemd || { + echo "problem installing systemd" + return 210 + } + } + fi + else + dpkg -l systemd | tail -n 1 | grep -E '^hi|^ii' || { sfApt install -y --no-install-recommends systemd || { echo "problem installing systemd" return 210 } - fi - else - sfApt install -y --no-install-recommends systemd || { - echo "problem installing systemd" - return 210 } # systemd, if updated, is restarted, so we may need to ensure again network connectivity ensure_network_connectivity fi # # Security updates ... - # sfApt update &>/dev/null && sfApt install -qy unattended-upgrades && unattended-upgrades -v + # sfApt update --allow-insecure-repositories &>/dev/null && sfApt install -qy unattended-upgrades && unattended-upgrades -v ;; redhat | centos) @@ -1468,13 +1476,13 @@ EOF function install_packages() { case $LINUX_KIND in ubuntu | debian) - sfApt install -y -qq --no-install-recommends wget curl jq zip unzip time at sshpass &> /dev/null || failure 213 "failure installing utility packages: jq zip time at" + sfApt install -y -qq --no-install-recommends wget jq zip unzip time at sshpass &> /dev/null || failure 213 "failure installing utility packages: jq zip time at" ;; redhat | centos) if [ $(versionchk ${VERSION_ID}) -ge $(versionchk "8.0") ]; then - sfYum install -y -q wget curl jq zip unzip time at sshpass &> /dev/null || failure 214 "failure installing utility packages: jq zip time at" + sfYum install -y -q wget jq zip unzip time at sshpass &> /dev/null || failure 214 "failure installing utility packages: jq zip time at" else - sfYum install --enablerepo=epel -y -q wget curl jq zip unzip time at sshpass &> /dev/null || failure 214 "failure installing utility packages: jq zip time at" + sfYum install --enablerepo=epel -y -q wget jq zip unzip time at sshpass &> /dev/null || failure 214 "failure installing utility packages: jq zip time at" fi ;; *) diff --git a/lib/backend/resources/operations/clusterflavors/scripts/master_install_ansible.sh b/lib/backend/resources/operations/clusterflavors/scripts/master_install_ansible.sh index 18511e297..cd06fc519 100755 --- a/lib/backend/resources/operations/clusterflavors/scripts/master_install_ansible.sh +++ b/lib/backend/resources/operations/clusterflavors/scripts/master_install_ansible.sh @@ -32,7 +32,7 @@ install_ansible() { case $LINUX_KIND in ubuntu) export DEBIAN_FRONTEND=noninteractive - sfApt update + sfApt update --allow-insecure-repositories apt-add-repository --yes --update ppa:ansible/ansible fApt update sfApt install -y ansible @@ -40,10 +40,10 @@ case $LINUX_KIND in ;; debian) export DEBIAN_FRONTEND=noninteractive - sfApt update + sfApt update --allow-insecure-repositories echo "deb http://ppa.launchpad.net/ansible/ansible/ubuntu trusty main" >> /etc/apt/sources.list sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 93C4A3FD7BB9C367 -y - sfApt update + sfApt update --allow-insecure-repositories sfApt install -y ansible sfApt install -y git ;; diff --git a/lib/backend/resources/operations/clusterflavors/scripts/master_install_only_ansible.sh b/lib/backend/resources/operations/clusterflavors/scripts/master_install_only_ansible.sh index 8d0c31a4d..5dc619774 100644 --- a/lib/backend/resources/operations/clusterflavors/scripts/master_install_only_ansible.sh +++ b/lib/backend/resources/operations/clusterflavors/scripts/master_install_only_ansible.sh @@ -32,7 +32,7 @@ install_ansible() { case $LINUX_KIND in ubuntu) export DEBIAN_FRONTEND=noninteractive - sfApt update + sfApt update --allow-insecure-repositories apt-add-repository --yes --update ppa:ansible/ansible fApt update sfApt install -y ansible @@ -40,10 +40,10 @@ case $LINUX_KIND in ;; debian) export DEBIAN_FRONTEND=noninteractive - sfApt update + sfApt update --allow-insecure-repositories echo "deb http://ppa.launchpad.net/ansible/ansible/ubuntu trusty main" >> /etc/apt/sources.list sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 93C4A3FD7BB9C367 -y - sfApt update + sfApt update --allow-insecure-repositories sfApt install -y ansible sfApt install -y git ;; diff --git a/lib/backend/resources/operations/clusterflavors/scripts/node_install_docker.sh b/lib/backend/resources/operations/clusterflavors/scripts/node_install_docker.sh index aaad7bbe4..cdc130520 100755 --- a/lib/backend/resources/operations/clusterflavors/scripts/node_install_docker.sh +++ b/lib/backend/resources/operations/clusterflavors/scripts/node_install_docker.sh @@ -33,7 +33,7 @@ install_docker() { case $LINUX_KIND in debian|ubuntu) export DEBIAN_FRONTEND=noninteractive - sfRetry "sfApt update" + sfRetry "sfApt update --allow-insecure-repositories" sfRetry "dpkg --remove --force-remove-reinstreq docker docker-engine docker.io containerd runc" ;; centos|redhat) @@ -54,21 +54,21 @@ install_docker() { case $LINUX_KIND in debian) export DEBIAN_FRONTEND=noninteractive - sfRetryEx 14m 4 "sfApt update" || sfFail 192 "error updating" + sfRetryEx 14m 4 "sfApt update --allow-insecure-repositories" || sfFail 192 "error updating" sfRetryEx 14m 4 "sfApt install -qqy apt-transport-https ca-certificates curl" || sfFail 193 "error installing apt tools (exit code $?)" sfRetryEx 14m 4 "(apt-cache show gnupg2 && apt install -qqy gnupg2) || (apt-cache show gnupg && apt install -qqy gnupg)" sfRetryEx 14m 4 "curl -fsSL https://download.docker.com/linux/$LINUX_KIND/gpg | apt-key add -" || sfFail 194 "error updating gpg keys" echo "deb [arch=amd64] https://download.docker.com/linux/$LINUX_KIND $(lsb_release -cs) stable" >/etc/apt/sources.list.d/docker.list - sfRetryEx 14m 4 "sfApt update" || sfFail 192 "error updating" + sfRetryEx 14m 4 "sfApt update --allow-insecure-repositories" || sfFail 192 "error updating" sfRetryEx 14m 4 "sfApt install -qqy docker-ce" || sfFail 195 "error installing docker-ce (exit code $?)" ;; ubuntu) export DEBIAN_FRONTEND=noninteractive - sfRetryEx 14m 4 "sfApt update" || sfFail 192 "error updating" + sfRetryEx 14m 4 "sfApt update --allow-insecure-repositories" || sfFail 192 "error updating" sfRetryEx 14m 4 "sfApt install -qqy apt-transport-https ca-certificates curl" || sfFail 193 "error installing apt tools (exit code $?)" sfRetryEx 14m 4 "curl -fsSL https://download.docker.com/linux/$LINUX_KIND/gpg | apt-key add -" || sfFail 194 "error updating gpg keys" echo "deb [arch=amd64] https://download.docker.com/linux/$LINUX_KIND $(lsb_release -cs) stable" >/etc/apt/sources.list.d/docker.list - sfRetryEx 14m 4 "sfApt update" || sfFail 192 "error updating" + sfRetryEx 14m 4 "sfApt update --allow-insecure-repositories" || sfFail 192 "error updating" sfRetryEx 14m 4 "sfApt install -qqy docker-ce" || sfFail 195 "error installing docker-ce (exit code $?)" ;; centos|redhat|rhel) diff --git a/lib/backend/resources/operations/embeddedfeatures/ansible.yml b/lib/backend/resources/operations/embeddedfeatures/ansible.yml index edfb9266f..bc1b5e674 100644 --- a/lib/backend/resources/operations/embeddedfeatures/ansible.yml +++ b/lib/backend/resources/operations/embeddedfeatures/ansible.yml @@ -70,18 +70,18 @@ feature: case $LINUX_KIND in ubuntu) export DEBIAN_FRONTEND=noninteractive - sfRetry "sfApt update" + sfRetry "sfApt update --allow-insecure-repositories" apt-add-repository --yes --update ppa:ansible/ansible - sfRetry "sfApt update" || sfFail 192 + sfRetry "sfApt update --allow-insecure-repositories" || sfFail 192 sfRetry "sfApt install -y ansible" || sfFail 192 sfRetry "sfApt install -y git" || sfFail 192 ;; debian) export DEBIAN_FRONTEND=noninteractive - sfRetry "sfApt update" + sfRetry "sfApt update --allow-insecure-repositories" echo "deb http://ppa.launchpad.net/ansible/ansible/ubuntu trusty main" >> /etc/apt/sources.list sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 93C4A3FD7BB9C367 -y - sfRetry "sfApt update" || sfFail 192 + sfRetry "sfApt update --allow-insecure-repositories" || sfFail 192 sfRetry "sfApt install -y ansible" || sfFail 192 sfRetry "sfApt install -y git" || sfFail 192 ;; diff --git a/lib/backend/resources/operations/embeddedfeatures/docker-legacy.yml b/lib/backend/resources/operations/embeddedfeatures/docker-legacy.yml index 6727e2678..aac05c1cb 100644 --- a/lib/backend/resources/operations/embeddedfeatures/docker-legacy.yml +++ b/lib/backend/resources/operations/embeddedfeatures/docker-legacy.yml @@ -109,7 +109,7 @@ feature: case $LINUX_KIND in debian|ubuntu) export DEBIAN_FRONTEND=noninteractive - sfRetry "sfApt update" + sfRetry "sfApt update --allow-insecure-repositories" sfRetry "dpkg --remove --force-remove-reinstreq docker docker-engine docker.io containerd runc" ;; centos|redhat) diff --git a/lib/backend/resources/operations/embeddedfeatures/docker.yml b/lib/backend/resources/operations/embeddedfeatures/docker.yml index 056d98dc3..cda6af77e 100644 --- a/lib/backend/resources/operations/embeddedfeatures/docker.yml +++ b/lib/backend/resources/operations/embeddedfeatures/docker.yml @@ -109,7 +109,7 @@ feature: case $LINUX_KIND in debian|ubuntu) export DEBIAN_FRONTEND=noninteractive - sfRetry "sfApt update" + sfRetry "sfApt update --allow-insecure-repositories" sfRetry "dpkg --remove --force-remove-reinstreq docker docker-engine docker.io containerd runc" ;; centos|redhat) @@ -138,21 +138,21 @@ feature: case $LINUX_KIND in debian) export DEBIAN_FRONTEND=noninteractive - sfRetryEx {{ or .reserved_LongTimeout "6m" }} {{ or .reserved_DefaultDelay 10 }} "sfApt update" || sfFail 192 "error updating" + sfRetryEx {{ or .reserved_LongTimeout "6m" }} {{ or .reserved_DefaultDelay 10 }} "sfApt update --allow-insecure-repositories" || sfFail 192 "error updating" sfRetryEx {{ or .reserved_LongTimeout "6m" }} {{ or .reserved_DefaultDelay 10 }} "sfApt install -qqy apt-transport-https ca-certificates curl" || sfFail 193 "error installing apt tools (exit code $?)" sfRetryEx {{ or .reserved_LongTimeout "6m" }} {{ or .reserved_DefaultDelay 10 }} "(apt-cache show gnupg2 && apt install -qqy gnupg2) || (apt-cache show gnupg && apt install -qqy gnupg)" sfRetryEx {{ or .reserved_LongTimeout "6m" }} {{ or .reserved_DefaultDelay 10 }} "curl -fsSL https://download.docker.com/linux/$LINUX_KIND/gpg | apt-key add -" || sfFail 194 "error updating gpg keys" echo "deb [arch=amd64] https://download.docker.com/linux/$LINUX_KIND $(lsb_release -cs) stable" >/etc/apt/sources.list.d/docker.list - sfRetryEx {{ or .reserved_LongTimeout "6m" }} {{ or .reserved_DefaultDelay 10 }} "sfApt update" || sfFail 192 "error updating" + sfRetryEx {{ or .reserved_LongTimeout "6m" }} {{ or .reserved_DefaultDelay 10 }} "sfApt update --allow-insecure-repositories" || sfFail 192 "error updating" sfRetryEx {{ or .reserved_LongTimeout "6m" }} {{ or .reserved_DefaultDelay 10 }} "sfApt install -qqy docker-ce" || sfFail 195 "error installing docker-ce (exit code $?)" ;; ubuntu) export DEBIAN_FRONTEND=noninteractive - sfRetryEx {{ or .reserved_LongTimeout "6m" }} {{ or .reserved_DefaultDelay 10 }} "sfApt update" || sfFail 192 "error updating" + sfRetryEx {{ or .reserved_LongTimeout "6m" }} {{ or .reserved_DefaultDelay 10 }} "sfApt update --allow-insecure-repositories" || sfFail 192 "error updating" sfRetryEx {{ or .reserved_LongTimeout "6m" }} {{ or .reserved_DefaultDelay 10 }} "sfApt install -qqy apt-transport-https ca-certificates curl" || sfFail 193 "error installing apt tools (exit code $?)" sfRetryEx {{ or .reserved_LongTimeout "6m" }} {{ or .reserved_DefaultDelay 10 }} "curl -fsSL https://download.docker.com/linux/$LINUX_KIND/gpg | apt-key add -" || sfFail 194 "error updating gpg keys" echo "deb [arch=amd64] https://download.docker.com/linux/$LINUX_KIND $(lsb_release -cs) stable" >/etc/apt/sources.list.d/docker.list - sfRetryEx {{ or .reserved_LongTimeout "6m" }} {{ or .reserved_DefaultDelay 10 }} "sfApt update" || sfFail 192 "error updating" + sfRetryEx {{ or .reserved_LongTimeout "6m" }} {{ or .reserved_DefaultDelay 10 }} "sfApt update --allow-insecure-repositories" || sfFail 192 "error updating" sfRetryEx {{ or .reserved_LongTimeout "6m" }} {{ or .reserved_DefaultDelay 10 }} "sfApt install -qqy docker-ce" || sfFail 195 "error installing docker-ce (exit code $?)" ;; centos|redhat|rhel) diff --git a/lib/backend/resources/operations/embeddedfeatures/kubernetes.yml b/lib/backend/resources/operations/embeddedfeatures/kubernetes.yml index 63d777412..7069793cd 100644 --- a/lib/backend/resources/operations/embeddedfeatures/kubernetes.yml +++ b/lib/backend/resources/operations/embeddedfeatures/kubernetes.yml @@ -236,7 +236,7 @@ feature: {{ if eq .EnableAudit "true" }} case $(sfGetFact "linux_kind") in debian|ubuntu) - sfApt update + sfApt update --allow-insecure-repositories sfRetry sfApt install -y auditd quota quotatool || sfFail 196 "Error installing auditd quota quotatool" ;; @@ -320,9 +320,9 @@ feature: deb https://apt.kubernetes.io/ kubernetes-xenial main EOF if [ ! -x ${KUBE_VERSION} ]; then - sfApt update && sfApt install -y kubelet=${KUBE_VERSION}-00 kubeadm=${KUBE_VERSION}-00 kubectl=${KUBE_VERSION}-00 || sfFail 203 "Error installing kubelet kubadm kubectl" + sfApt update --allow-insecure-repositories && sfApt install -y kubelet=${KUBE_VERSION}-00 kubeadm=${KUBE_VERSION}-00 kubectl=${KUBE_VERSION}-00 || sfFail 203 "Error installing kubelet kubadm kubectl" else - sfApt update && sfApt install -y kubelet kubeadm kubectl || sfFail 203 "Error installing kubelet kubeadm kubectl" + sfApt update --allow-insecure-repositories && sfApt install -y kubelet kubeadm kubectl || sfFail 203 "Error installing kubelet kubeadm kubectl" fi apt-mark hold kubelet kubeadm kubectl ;; @@ -362,7 +362,7 @@ feature: {{ if .ClusterControlplaneUsesVIP }} case $(sfGetFact "linux_kind") in ubuntu|debian) - sfApt update && sfApt -y install keepalived haproxy || sfFail 205 "Error installing keepalived haproxy" + sfApt update --allow-insecure-repositories && sfApt -y install keepalived haproxy || sfFail 205 "Error installing keepalived haproxy" ;; redhat|rhel|centos|fedora) yum install -q -y keepalived haproxy || sfFail 205 "Error installing keepalived haproxy" diff --git a/lib/backend/resources/operations/embeddedfeatures/ntpclient.yml b/lib/backend/resources/operations/embeddedfeatures/ntpclient.yml index ed7e75153..42ea109f3 100644 --- a/lib/backend/resources/operations/embeddedfeatures/ntpclient.yml +++ b/lib/backend/resources/operations/embeddedfeatures/ntpclient.yml @@ -65,7 +65,7 @@ feature: case $LINUX_KIND in debian|ubuntu) export DEBIAN_FRONTEND=noninteractive - sfRetry "sfApt update" + sfRetry "sfApt update --allow-insecure-repositories" sfRetry "sfApt install -y ntpdate" || sfFail 192 ;; centos|fedora|redhat|rhel) diff --git a/lib/backend/resources/operations/embeddedfeatures/ntpserver.yml b/lib/backend/resources/operations/embeddedfeatures/ntpserver.yml index d68497a08..1973f5f21 100644 --- a/lib/backend/resources/operations/embeddedfeatures/ntpserver.yml +++ b/lib/backend/resources/operations/embeddedfeatures/ntpserver.yml @@ -62,7 +62,7 @@ feature: case $LINUX_KIND in debian|ubuntu) export DEBIAN_FRONTEND=noninteractive - sfRetry "sfApt update && sfApt install -y ntp" || sfFail 192 + sfRetry "sfApt update --allow-insecure-repositories && sfApt install -y ntp" || sfFail 192 ;; centos|fedora|redhat|rhel) if [[ -n $(which dnf) ]]; then diff --git a/lib/backend/resources/operations/embeddedfeatures/nvidiadocker.yml b/lib/backend/resources/operations/embeddedfeatures/nvidiadocker.yml index fe7268be1..070f2d8a8 100644 --- a/lib/backend/resources/operations/embeddedfeatures/nvidiadocker.yml +++ b/lib/backend/resources/operations/embeddedfeatures/nvidiadocker.yml @@ -89,7 +89,7 @@ feature: # Second install nvidia-docker curl -s -L ${NVIDIA_DOCKER_URL}/gpgkey | apt-key add - curl -s -L ${NVIDIA_DOCKER_URL}/${DIST}/nvidia-docker.list | tee /etc/apt/sources.list.d/nvidia-docker.list - sfApt update + sfApt update --allow-insecure-repositories sfApt install -y nvidia-container-toolkit systemctl restart docker else diff --git a/lib/backend/resources/operations/embeddedfeatures/remotedesktop.yml b/lib/backend/resources/operations/embeddedfeatures/remotedesktop.yml index 06ac207b2..46b094c84 100644 --- a/lib/backend/resources/operations/embeddedfeatures/remotedesktop.yml +++ b/lib/backend/resources/operations/embeddedfeatures/remotedesktop.yml @@ -100,7 +100,7 @@ feature: dnf install -y --skip-broken xorg-x11-fonts-Type1 urw-fonts wget firefox perl || sfFail 192 ;; debian|ubuntu) - sfApt update && apt-mark hold xscreensaver + sfApt update --allow-insecure-repositories && apt-mark hold xscreensaver sfApt install -y perl xfce4 firefox ;; *) diff --git a/lib/system/nfs/scripts/nfs_server_install.sh b/lib/system/nfs/scripts/nfs_server_install.sh index 91f596e31..bedc4c491 100644 --- a/lib/system/nfs/scripts/nfs_server_install.sh +++ b/lib/system/nfs/scripts/nfs_server_install.sh @@ -52,7 +52,7 @@ debian | ubuntu) touch /var/log/lastlog chgrp utmp /var/log/lastlog chmod 664 /var/log/lastlog - sfApt update + sfApt update --allow-insecure-repositories sfApt install -qqy nfs-common nfs-kernel-server ;; diff --git a/lib/system/scripts/bash_library.sh b/lib/system/scripts/bash_library.sh index e90722f9e..3b970757d 100644 --- a/lib/system/scripts/bash_library.sh +++ b/lib/system/scripts/bash_library.sh @@ -102,7 +102,7 @@ function sfApt() { [ $? -ne 0 ] && return $? echo "running apt " "$@" rc=-1 - DEBIAN_FRONTEND=noninteractive UCF_FORCE_CONFFNEW=1 apt -o Dpkg::Options::=--force-confnew "$@" && rc=$? + DEBIAN_FRONTEND=noninteractive UCF_FORCE_CONFFNEW=1 apt --ignore-missing --allow-unauthenticated -o Dpkg::Options::=--force-confnew "$@" && rc=$? [ $rc -eq -1 ] && return 1 return $rc } @@ -434,7 +434,7 @@ function sfInstall() { debian | ubuntu) export DEBIAN_FRONTEND=noninteractive export UCF_FORCE_CONFFNEW=1 - sfRetry4 "sfApt update" + sfApt update --allow-insecure-repositories sfApt install $1 -y || return 194 command -v $1 || return 194 ;; diff --git a/lib/system/ssh/bycli/command_line_based_ssh.go b/lib/system/ssh/bycli/command_line_based_ssh.go index 5609edb7b..2bc2bfe51 100644 --- a/lib/system/ssh/bycli/command_line_based_ssh.go +++ b/lib/system/ssh/bycli/command_line_based_ssh.go @@ -1093,8 +1093,6 @@ func createSSHCommand( sshCmdString += fmt.Sprintf(" <<'ENDSSH'\n%s\nENDSSH", cmdString) } - // logrus.WithContext(context.Background()).Debugf("Created SSH command '%s'", strings.Replace(sshCmdString, "\n", "\t", -1)) - return sshCmdString, f, nil } From 4122ff8eef7788d0571ba143ee2675b0490827ac Mon Sep 17 00:00:00 2001 From: oscar Date: Fri, 10 Feb 2023 16:04:52 +0100 Subject: [PATCH 29/43] bug: fixed problems reading cluster information --- lib/backend/resources/operations/cluster.go | 25 +++++++++++++++- .../resources/operations/metadatacore.go | 29 ++++++++++++++++++- .../operations/metadatacore_debug.go | 29 ++++++++++++++++++- 3 files changed, 80 insertions(+), 3 deletions(-) diff --git a/lib/backend/resources/operations/cluster.go b/lib/backend/resources/operations/cluster.go index 474c9510e..1229a3882 100755 --- a/lib/backend/resources/operations/cluster.go +++ b/lib/backend/resources/operations/cluster.go @@ -321,6 +321,29 @@ func onClusterCacheMiss(inctx context.Context, svc iaas.Service, name string) (d return nil, xerr } + if val, ok := aclupro[clusterproperty.NetworkV3]; !ok { + return nil, fail.NewError("corrupted metadata") + } else { + if val == nil { + return nil, fail.NewError("corrupted metadata") + } + } + + nev, err := aclupro[clusterproperty.NetworkV3].UnWrap() + if err != nil { + return nil, fail.ConvertError(err) + } + + gottanev, ok := nev.(*propertiesv3.ClusterNetwork) + if !ok { + return nil, fail.NewError("bad cast") + } + + clusterInstance.gateways = append(clusterInstance.gateways, gottanev.GatewayID) + if gottanev.SecondaryGatewayID != "" { + clusterInstance.gateways = append(clusterInstance.gateways, gottanev.SecondaryGatewayID) + } + if val, ok := aclupro[clusterproperty.NodesV3]; !ok { return nil, fail.NewError("corrupted metadata") } else { @@ -825,7 +848,7 @@ func (instance *Cluster) Start(ctx context.Context) (ferr fail.Error) { ) } - gatewayID = networkV3.GatewayID + gatewayID = networkV3.GatewayID // FIXME: OPP I came here for secondaryGatewayID = networkV3.SecondaryGatewayID return nil }) diff --git a/lib/backend/resources/operations/metadatacore.go b/lib/backend/resources/operations/metadatacore.go index c91c8f5e8..6faf42314 100755 --- a/lib/backend/resources/operations/metadatacore.go +++ b/lib/backend/resources/operations/metadatacore.go @@ -171,6 +171,31 @@ func (myself *MetadataCore) getName() (string, fail.Error) { return name, nil } +func (myself *MetadataCore) isAlmostValid() (bool, fail.Error) { + if myself == nil { + return false, fail.InvalidInstanceError() + } + + name, xerr := myself.getName() + if xerr != nil { + return false, nil + } + + if name == "" { + return false, nil + } + + if !myself.loaded && !myself.committed { + return false, nil + } + + if myself.deleted { + return false, nil + } + + return true, nil +} + func (myself *MetadataCore) IsValid() (bool, fail.Error) { if myself == nil { return false, fail.InvalidInstanceError() @@ -225,7 +250,9 @@ func (myself *MetadataCore) Inspect(inctx context.Context, callback resources.Ca } if itis, xerr := myself.IsValid(); xerr == nil && !itis { - return fail.InconsistentError("the instance is not valid") + if almost, xerr := myself.isAlmostValid(); xerr == nil && !almost { // metadata from old clusters is INVALID + return fail.InconsistentError("the instance is not valid") + } } ctx, cancel := context.WithCancel(inctx) diff --git a/lib/backend/resources/operations/metadatacore_debug.go b/lib/backend/resources/operations/metadatacore_debug.go index 9536901fd..329174bda 100644 --- a/lib/backend/resources/operations/metadatacore_debug.go +++ b/lib/backend/resources/operations/metadatacore_debug.go @@ -172,6 +172,31 @@ func (myself *MetadataCore) getName() (string, fail.Error) { return name, nil } +func (myself *MetadataCore) isAlmostValid() (bool, fail.Error) { + if myself == nil { + return false, fail.InvalidInstanceError() + } + + name, xerr := myself.getName() + if xerr != nil { + return false, nil + } + + if name == "" { + return false, nil + } + + if !myself.loaded && !myself.committed { + return false, nil + } + + if myself.deleted { + return false, nil + } + + return true, nil +} + func (myself *MetadataCore) IsValid() (bool, fail.Error) { if myself == nil { return false, fail.InvalidInstanceError() @@ -233,7 +258,9 @@ func (myself *MetadataCore) Inspect(inctx context.Context, callback resources.Ca } if itis, xerr := myself.IsValid(); xerr == nil && !itis { - return fail.InconsistentError("the instance is not valid") + if almost, xerr := myself.isAlmostValid(); xerr == nil && !almost { // metadata from old clusters is INVALID + return fail.InconsistentError("the instance is not valid") + } } ctx, cancel := context.WithCancel(inctx) From 17a967b39b12555a225958a1fc0b24d89cbe1060 Mon Sep 17 00:00:00 2001 From: oscar Date: Mon, 13 Feb 2023 09:25:17 +0100 Subject: [PATCH 30/43] bug: listing corrupted volumes --- lib/backend/resources/operations/volume.go | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/lib/backend/resources/operations/volume.go b/lib/backend/resources/operations/volume.go index ed6c9d0fa..b0c7aec32 100755 --- a/lib/backend/resources/operations/volume.go +++ b/lib/backend/resources/operations/volume.go @@ -1060,6 +1060,9 @@ func (instance *volume) ToProtocol(ctx context.Context) (*protocol.VolumeInspect if valid.IsNil(instance) { return nil, fail.InvalidInstanceError() } + // HUGE design mistakes in all ToProtocol functions + // a ToProtocol function should just transform data, ALL the data should be ready BEFORE calling ToProtocol... + // but as we see here, there is a min of 3 remote queries here... // instance.lock.RLock() // defer instance.lock.RUnlock() @@ -1077,7 +1080,7 @@ func (instance *volume) ToProtocol(ctx context.Context) (*protocol.VolumeInspect Attachments: []*protocol.VolumeAttachmentResponse{}, } - attachments, xerr := instance.GetAttachments(ctx) + attachments, xerr := instance.GetAttachments(ctx) // remote query xerr = debug.InjectPlannedFail(xerr) if xerr != nil { return nil, xerr @@ -1085,19 +1088,24 @@ func (instance *volume) ToProtocol(ctx context.Context) (*protocol.VolumeInspect svc := instance.Service() for k := range attachments.Hosts { - hostInstance, xerr := LoadHost(ctx, svc, k) + hostInstance, xerr := LoadHost(ctx, svc, k) // a few more remote queries for each attachment xerr = debug.InjectPlannedFail(xerr) if xerr != nil { - return nil, xerr + switch xerr.(type) { + case *fail.ErrNotFound: + default: + return nil, xerr + } + continue } - vols, _ := hostInstance.(*Host).unsafeGetVolumes(ctx) + vols, _ := hostInstance.(*Host).unsafeGetVolumes(ctx) // remote query device, ok := vols.DevicesByID[volumeID] if !ok { return nil, fail.InconsistentError("failed to find a device corresponding to the attached volume '%s' on host '%s'", volumeName, k) } - mnts, _ := hostInstance.(*Host).unsafeGetMounts(ctx) + mnts, _ := hostInstance.(*Host).unsafeGetMounts(ctx) // remote query if mnts != nil { path, ok := mnts.LocalMountsByDevice[device] if !ok { From c1b2d963d896178f6c995e2ab454e038eaa67199 Mon Sep 17 00:00:00 2001 From: oscar Date: Mon, 13 Feb 2023 09:26:06 +0100 Subject: [PATCH 31/43] chores: cleaning --- lib/backend/listeners/bucket.go | 2 +- lib/backend/resources/operations/subnet.go | 13 +++++-------- lib/system/ssh/bylib/library_based_ssh.go | 2 +- 3 files changed, 7 insertions(+), 10 deletions(-) diff --git a/lib/backend/listeners/bucket.go b/lib/backend/listeners/bucket.go index 85391a9a5..a0299afb6 100644 --- a/lib/backend/listeners/bucket.go +++ b/lib/backend/listeners/bucket.go @@ -241,7 +241,7 @@ func (s *BucketListener) Inspect(inctx context.Context, in *protocol.BucketReque return nil, xerr } - // DEFENSIVE CODING: this _must not_ happen, but InspectHost has different implementations for each stack, and sometimes mistakes happens, so the test is necessary + // returning nil, nil IS a mistake if resp == nil { return nil, fail.NotFoundError("bucket '%s' not found", bucketName) } diff --git a/lib/backend/resources/operations/subnet.go b/lib/backend/resources/operations/subnet.go index ad4457501..134246dc6 100755 --- a/lib/backend/resources/operations/subnet.go +++ b/lib/backend/resources/operations/subnet.go @@ -1271,15 +1271,12 @@ func (instance *Subnet) onRemovalUnbindSecurityGroups(ctx context.Context, subne default: return xerr } - } else { - xerr = sgInstance.unbindFromSubnetHosts(ctx, unbindParams) - if xerr != nil { - return xerr - } + continue + } - // VPL: no need to update SubnetSecurityGroups property, the Subnet is being removed - // delete(sgs.ByID, v) - // delete(sgs.ByName, k) + xerr = sgInstance.unbindFromSubnetHosts(ctx, unbindParams) + if xerr != nil { + return xerr } } return nil diff --git a/lib/system/ssh/bylib/library_based_ssh.go b/lib/system/ssh/bylib/library_based_ssh.go index 2bd2a75bb..143a894c9 100644 --- a/lib/system/ssh/bylib/library_based_ssh.go +++ b/lib/system/ssh/bylib/library_based_ssh.go @@ -1,5 +1,5 @@ /* - * Copyright 2018-2021, CS Systemes d'Information, http://csgroup.eu + * Copyright 2018-2023, CS Systemes d'Information, http://csgroup.eu * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. From 7f45864132c33f5f9272f7285310d4afb0ab3baf Mon Sep 17 00:00:00 2001 From: oscar Date: Mon, 13 Feb 2023 12:17:45 +0100 Subject: [PATCH 32/43] doc: updated client examples --- doc/client/AWS.md | 30 ++++++++++++++++++---------- doc/client/CLOUDFERRO.md | 27 +++++++++++++++---------- doc/client/FLEXIBLEENGINE.md | 34 +++++++++++++++++++++----------- doc/client/GCP.md | 30 ++++++++++++++++++++++------ doc/client/OUTSCALE.md | 38 +++++++++++++++++++++++++++--------- doc/client/OVH.md | 25 ++++++++++++++++-------- 6 files changed, 130 insertions(+), 54 deletions(-) diff --git a/doc/client/AWS.md b/doc/client/AWS.md index efb58ecbf..82c869b2f 100644 --- a/doc/client/AWS.md +++ b/doc/client/AWS.md @@ -1,14 +1,24 @@ ``` [[tenants]] - name = "TenantName" - client = "aws" - - # This part defines how to authenticate with the provider + client = "aws" + name = "myAws" + [tenants.identity] - IdentityEndpoint = "" - Username = "" - Password = "" - TenantName = "" - - Region = "" + AccessKeyID = "ABCDEFGHIJK........." + SecretAccessKey = "12345678abcdef.........................." + auth_uri = "https://iam.amazonaws.com" + + [tenants.compute] + S3 = "https://s3.eu-central-1.amazonaws.com" + EC2 = "https://ec2.eu-central-1.amazonaws.com" + SSM = "https://ssm.eu-central-1.amazonaws.com" + + Region = "eu-central-1" + Zone = "eu-central-1a" + + [tenants.objectstorage] + Type = "s3" + AccessKey = "ABCDEFGHIJK........." + SecretKey = "12345678abcdef.........................." + Region = "eu-central-1" ``` diff --git a/doc/client/CLOUDFERRO.md b/doc/client/CLOUDFERRO.md index f4aed8132..04f7eb52b 100644 --- a/doc/client/CLOUDFERRO.md +++ b/doc/client/CLOUDFERRO.md @@ -1,14 +1,21 @@ -``` [[tenants]] - name = "TenantName" + name = "myCloudFerro" client = "cloudferro" - # This part defines how to authenticate with the provider [tenants.identity] - IdentityEndpoint = "" - Username = "" - Password = "" - DomainName = "" - TenantName = "" - AllowReauth = "" -``` + ProjectID = "abcdefgh........................" + Username = "user@somewhere" + Password = "ABCDEF.............." + DomainName = "dom_12345" + + [tenants.compute] + Region = "RegionOne" + AvailabilityZone = "nova" + ProjectName = "my project name" + + [tenants.network] + ProviderNetwork = "external2" + + [tenants.objectstorage] + Type = "swift" + AuthURL = "https://cf2.cloudferro.com:5000/v3" diff --git a/doc/client/FLEXIBLEENGINE.md b/doc/client/FLEXIBLEENGINE.md index cdc484ab5..8fbf54441 100644 --- a/doc/client/FLEXIBLEENGINE.md +++ b/doc/client/FLEXIBLEENGINE.md @@ -1,14 +1,26 @@ ``` [[tenants]] - name = "TenantName" - client = "flexibleengine" - - # This part defines how to authenticate with the provider - [tenants.identity] - IdentityEndpoint = "" - Username = "" - Password = "" - DomainName = "" - TenantName = "" - AllowReauth = "" + name = "myFlexibleTenant" + client = "flexibleengine" + + [tenants.identity] + Username = "myUser" + Password = "abcdef............" + DomainName = "ABC0123456" + + [tenants.compute] + ProjectID= "123456abcdef...................." + Region= "eu-west-0" + AvailabilityZone= "eu-west-0b" + DefaultImage = "Ubuntu 20.04" + + [tenants.network] + VPCName = "myVPCName + VPCCIDR = "192.168.0.0/16" + + [tenants.objectstorage] + Type = "s3" + Endpoint = "https://oss.eu-west-0.prod-cloud-ocb.orange-business.com" + AccessKey = "ABCDEF.............." + SecretKey = "HIJK1234................................" ``` diff --git a/doc/client/GCP.md b/doc/client/GCP.md index 6f0ee27fb..6b35e75be 100644 --- a/doc/client/GCP.md +++ b/doc/client/GCP.md @@ -1,12 +1,30 @@ ``` [[tenants]] - name = "TenantName" client = "gcp" + name = "myGoogleTenant - # This part defines how to authenticate with the provider [tenants.identity] - IdentityEndpoint = "" - Username = "" - Password = "" - TenantName = "" + User = "user@somewhere" + Password = "ABCDEF..............." + ProjectNumber = "012345678901" + project_id = "my-project-id" + private_key_id = "123456789abcdef........................." + private_key = "-----BEGIN PRIVATE KEY-----\n........\n-----END PRIVATE KEY-----\n" + client_email = "there@developer.gserviceaccount.com" + client_id = "123456..............." + auth_uri = "https://accounts.google.com/o/oauth2/auth" + token_uri = "https://oauth2.googleapis.com/token" + auth_provider_x509_cert_url = "https://www.googleapis.com/oauth2/v1/certs" + client_x509_cert_url = "https://www.googleapis.com/robot/v1/metadata/x509/there%40developer.gserviceaccount.com" + + [tenants.compute] + Region = "europe-west1" + Zone = "europe-west1-b" + + [tenants.objectstorage] + Type = "google" + Region = "europe-west1-b" + + [tenants.network] + ProviderNetwork = "myVPCName" ``` diff --git a/doc/client/OUTSCALE.md b/doc/client/OUTSCALE.md index bf9e30209..6d3ad287e 100644 --- a/doc/client/OUTSCALE.md +++ b/doc/client/OUTSCALE.md @@ -1,12 +1,32 @@ ``` [[tenants]] - name = "TenantName" - client = "outscale" - - # This part defines how to authenticate with the provider - [tenants.identity] - Username = "" - UserID = "" - Password = "" - TenantName = "" + client = "outscale" + name = "myOutscale" + + [tenants.identity] + AccessKey="ABCDEF123..........." + SecretKey="1234567................................." + UserID="0123455432112345...." + + [tenants.compute] + Region="eu-west-2" + Subregion="eu-west-2a" + Service="api" + DefaultVolumeSpeed="HDD" + + [tenants.network] + VPCName = "my-vpc" + VPCCIDR = "192.168.0.0/16" + + [tenants.objectstorage] + Type = "s3" + Endpoint = "https://oos.eu-west-2.outscale.com" + AccessKey="ABCDEF123..........." + SecretKey="1234567................................." + + [tenants.metadata] + Type = "s3" + Endpoint = "https://oos.eu-west-2.outscale.com" + AccessKey="ABCDEF123..........." + SecretKey="1234567................................." ``` diff --git a/doc/client/OVH.md b/doc/client/OVH.md index 821676a77..6547f889e 100644 --- a/doc/client/OVH.md +++ b/doc/client/OVH.md @@ -1,14 +1,23 @@ ``` [[tenants]] - name = "TenantName" + name = "TestOVHGra" client = "ovh" - # This part defines how to authenticate with the provider [tenants.identity] - Username = "" - Password = "" - DomainName = "" - TenantID = "" - TenantName = "" - AllowReauth = "" + ApplicationKey = "123456.........................." + OpenstackID = "ABCDE......." + OpenstackPassword = "abcdefgh123....................." + + [tenants.compute] + Region = "SBG5" + ProjectName = "987654.........." + DefaultImage = "Ubuntu 18.04" + + [tenants.network] + ProviderNetwork = "Ext-Net" + + [tenants.objectstorage] + Type = "swift" + Region = "SBG" + AuthURL = "https://auth.cloud.ovh.net/v3" ``` From 85906066010e620fce8e06a9de6a96aa5e8e11ea Mon Sep 17 00:00:00 2001 From: oscar Date: Mon, 13 Feb 2023 14:37:18 +0100 Subject: [PATCH 33/43] feat: handle suffix in tenants configuration file --- lib/backend/iaas/factory.go | 9 +++++++- lib/backend/iaas/objectstorage/bucketnames.go | 15 +++++++++---- lib/backend/iaas/objectstorage/location.go | 1 + lib/backend/iaas/providers/aws/aws.go | 21 +++++++++++++++++- .../iaas/providers/cloudferro/cloudferro.go | 21 +++++++++++++++++- .../flexibleengine/flexibleengine.go | 21 +++++++++++++++++- lib/backend/iaas/providers/gcp/gcp.go | 22 ++++++++++++++++++- .../iaas/providers/openstack/openstack.go | 22 ++++++++++++++++++- .../iaas/providers/opentelekom/opentelekom.go | 22 ++++++++++++++++++- .../iaas/providers/outscale/outscale.go | 19 +++++++++++++++- lib/backend/iaas/providers/ovh/ovh.go | 22 ++++++++++++++++++- 11 files changed, 182 insertions(+), 13 deletions(-) diff --git a/lib/backend/iaas/factory.go b/lib/backend/iaas/factory.go index 96ddabf5d..57f9412b3 100644 --- a/lib/backend/iaas/factory.go +++ b/lib/backend/iaas/factory.go @@ -705,7 +705,14 @@ func initMetadataLocationConfig(authOpts providers.Config, tenant map[string]int config.Credentials = string(d1) } - config.BucketName, _ = metadata["MetadataBucketName"].(string) // nolint + if config.BucketName, ok = metadata["MetadataBucketName"].(string); !ok { + config.BucketName, _ = ostorage["MetadataBucketName"].(string) // nolint + } + + if config.Suffix, ok = metadata["Suffix"].(string); !ok { + config.Suffix, _ = ostorage["Suffix"].(string) // nolint + } + return config, nil } diff --git a/lib/backend/iaas/objectstorage/bucketnames.go b/lib/backend/iaas/objectstorage/bucketnames.go index ab4cca0bb..483220fd6 100644 --- a/lib/backend/iaas/objectstorage/bucketnames.go +++ b/lib/backend/iaas/objectstorage/bucketnames.go @@ -37,7 +37,7 @@ const ( ) // BuildMetadataBucketName builds the name of the bucket/stowContainer that will store metadata -func BuildMetadataBucketName(driver, region, domain, project string) (name string, ferr fail.Error) { +func BuildMetadataBucketName(driver, region, domain, project string, suffixFromCfg string) (name string, ferr fail.Error) { hash := fnv.New128a() sig := strings.ToLower(fmt.Sprintf("%s-%s-%s-%s", driver, region, domain, project)) _, herr := hash.Write([]byte(sig)) @@ -48,10 +48,17 @@ func BuildMetadataBucketName(driver, region, domain, project string) (name strin name = BucketNamePrefix + "-" + hashed nameLen := len(name) - if suffix, ok := os.LookupEnv(suffixEnvName); ok && suffix != "" { - name += "." + suffix + if suffixFromCfg == "" { + if suffix, ok := os.LookupEnv(suffixEnvName); ok && suffix != "" { + name += "." + suffix + if len(name) > maxBucketNameLength { + return "", fail.OverflowError(nil, maxBucketNameLength, "suffix '%s' is too long, max allowed: %d characters", suffix, maxBucketNameLength-nameLen-1) + } + } + } else { + name += "." + suffixFromCfg if len(name) > maxBucketNameLength { - return "", fail.OverflowError(nil, maxBucketNameLength, "suffix '%s' is too long, max allowed: %d characters", suffix, maxBucketNameLength-nameLen-1) + return "", fail.OverflowError(nil, maxBucketNameLength, "suffix '%s' is too long, max allowed: %d characters", suffixFromCfg, maxBucketNameLength-nameLen-1) } } if len(name) > maxBucketNameLength { diff --git a/lib/backend/iaas/objectstorage/location.go b/lib/backend/iaas/objectstorage/location.go index 54da40f41..4257315e2 100644 --- a/lib/backend/iaas/objectstorage/location.go +++ b/lib/backend/iaas/objectstorage/location.go @@ -65,6 +65,7 @@ type Config struct { BucketName string DNS string Direct bool // if true, no stow cache is used + Suffix string } // Location ... diff --git a/lib/backend/iaas/providers/aws/aws.go b/lib/backend/iaas/providers/aws/aws.go index 048f3d807..b3a91c453 100644 --- a/lib/backend/iaas/providers/aws/aws.go +++ b/lib/backend/iaas/providers/aws/aws.go @@ -202,7 +202,8 @@ func (p *provider) Build(params map[string]interface{}) (providers.Provider, fai providerName := "aws" - metadataBucketName, xerr := objectstorage.BuildMetadataBucketName(providerName, region, "", projectID) + suffix := getSuffix(params) + metadataBucketName, xerr := objectstorage.BuildMetadataBucketName(providerName, region, "", projectID, suffix) if xerr != nil { return nil, xerr } @@ -284,6 +285,24 @@ next: return wp, nil } +func getSuffix(params map[string]interface{}) string { + suffix := "" + if osto, ok := params["objectstorage"].(map[string]interface{}); ok { + if val, ok := osto["Suffix"].(string); ok { + suffix = val + if suffix != "" { + return suffix + } + } + } + if meta, ok := params["metadata"].(map[string]interface{}); ok { + if val, ok := meta["Suffix"].(string); ok { + suffix = val + } + } + return suffix +} + // GetAuthenticationOptions returns the auth options func (p provider) GetAuthenticationOptions(ctx context.Context) (providers.Config, fail.Error) { cfg := providers.ConfigMap{} diff --git a/lib/backend/iaas/providers/cloudferro/cloudferro.go b/lib/backend/iaas/providers/cloudferro/cloudferro.go index 1fa7a2c70..43fec3700 100644 --- a/lib/backend/iaas/providers/cloudferro/cloudferro.go +++ b/lib/backend/iaas/providers/cloudferro/cloudferro.go @@ -139,8 +139,9 @@ func (p *provider) Build(params map[string]interface{}) (providers.Provider, fai return nil, fail.NewError("Structure validation failure: %v", err) } + suffix := getSuffix(params) providerName := "openstack" - metadataBucketName, xerr := objectstorage.BuildMetadataBucketName(providerName, region, domainName, projectName) + metadataBucketName, xerr := objectstorage.BuildMetadataBucketName(providerName, region, domainName, projectName, suffix) if xerr != nil { return nil, xerr } @@ -220,6 +221,24 @@ next: return wp, nil } +func getSuffix(params map[string]interface{}) string { + suffix := "" + if osto, ok := params["objectstorage"].(map[string]interface{}); ok { + if val, ok := osto["Suffix"].(string); ok { + suffix = val + if suffix != "" { + return suffix + } + } + } + if meta, ok := params["metadata"].(map[string]interface{}); ok { + if val, ok := meta["Suffix"].(string); ok { + suffix = val + } + } + return suffix +} + // GetAuthenticationOptions returns the auth options func (p provider) GetAuthenticationOptions(ctx context.Context) (providers.Config, fail.Error) { cfg := providers.ConfigMap{} diff --git a/lib/backend/iaas/providers/flexibleengine/flexibleengine.go b/lib/backend/iaas/providers/flexibleengine/flexibleengine.go index 528b34c53..2836c6c7a 100644 --- a/lib/backend/iaas/providers/flexibleengine/flexibleengine.go +++ b/lib/backend/iaas/providers/flexibleengine/flexibleengine.go @@ -166,8 +166,9 @@ func (p *provider) Build(params map[string]interface{}) (providers.Provider, fai return nil, fail.NewError("Structure validation failure: %v", err) } + suffix := getSuffix(params) providerName := "huaweicloud" - metadataBucketName, xerr := objectstorage.BuildMetadataBucketName(providerName, region, domainName, projectID) + metadataBucketName, xerr := objectstorage.BuildMetadataBucketName(providerName, region, domainName, projectID, suffix) if xerr != nil { return nil, xerr } @@ -247,6 +248,24 @@ next: return wp, nil } +func getSuffix(params map[string]interface{}) string { + suffix := "" + if osto, ok := params["objectstorage"].(map[string]interface{}); ok { + if val, ok := osto["Suffix"].(string); ok { + suffix = val + if suffix != "" { + return suffix + } + } + } + if meta, ok := params["metadata"].(map[string]interface{}); ok { + if val, ok := meta["Suffix"].(string); ok { + suffix = val + } + } + return suffix +} + func addGPUCfg(tpl *abstract.HostTemplate) { if cfg, ok := gpuMap[tpl.Name]; ok { tpl.GPUNumber = cfg.GPUNumber diff --git a/lib/backend/iaas/providers/gcp/gcp.go b/lib/backend/iaas/providers/gcp/gcp.go index 761c03528..26902eeab 100644 --- a/lib/backend/iaas/providers/gcp/gcp.go +++ b/lib/backend/iaas/providers/gcp/gcp.go @@ -179,8 +179,10 @@ func (p *provider) Build(params map[string]interface{}) (providers.Provider, fai } } + suffix := getSuffix(params) + providerName := "gcp" - metadataBucketName, err := objectstorage.BuildMetadataBucketName(providerName, region, "", projectID) + metadataBucketName, err := objectstorage.BuildMetadataBucketName(providerName, region, "", projectID, suffix) if err != nil { return nil, err } @@ -242,6 +244,24 @@ next: return wp, nil } +func getSuffix(params map[string]interface{}) string { + suffix := "" + if osto, ok := params["objectstorage"].(map[string]interface{}); ok { + if val, ok := osto["Suffix"].(string); ok { + suffix = val + if suffix != "" { + return suffix + } + } + } + if meta, ok := params["metadata"].(map[string]interface{}); ok { + if val, ok := meta["Suffix"].(string); ok { + suffix = val + } + } + return suffix +} + // GetAuthenticationOptions returns the auth options func (p provider) GetAuthenticationOptions(ctx context.Context) (providers.Config, fail.Error) { cfg := providers.ConfigMap{} diff --git a/lib/backend/iaas/providers/openstack/openstack.go b/lib/backend/iaas/providers/openstack/openstack.go index 373fafed2..935421693 100644 --- a/lib/backend/iaas/providers/openstack/openstack.go +++ b/lib/backend/iaas/providers/openstack/openstack.go @@ -156,8 +156,10 @@ func (p *provider) Build(params map[string]interface{}) (providers.Provider, fai FloatingIPPool: floatingIPPool, } + suffix := getSuffix(params) + providerName := "openstack" - metadataBucketName, xerr := objectstorage.BuildMetadataBucketName(providerName, region, tenantID, "0") + metadataBucketName, xerr := objectstorage.BuildMetadataBucketName(providerName, region, tenantID, "0", suffix) if xerr != nil { return nil, xerr } @@ -219,6 +221,24 @@ next: return wp, nil } +func getSuffix(params map[string]interface{}) string { + suffix := "" + if osto, ok := params["objectstorage"].(map[string]interface{}); ok { + if val, ok := osto["Suffix"].(string); ok { + suffix = val + if suffix != "" { + return suffix + } + } + } + if meta, ok := params["metadata"].(map[string]interface{}); ok { + if val, ok := meta["Suffix"].(string); ok { + suffix = val + } + } + return suffix +} + // GetAuthenticationOptions returns the auth options func (p *provider) GetAuthenticationOptions(ctx context.Context) (providers.Config, fail.Error) { opts, err := p.Stack.(api.ReservedForProviderUse).GetRawAuthenticationOptions(ctx) diff --git a/lib/backend/iaas/providers/opentelekom/opentelekom.go b/lib/backend/iaas/providers/opentelekom/opentelekom.go index e45f7e744..613a24799 100644 --- a/lib/backend/iaas/providers/opentelekom/opentelekom.go +++ b/lib/backend/iaas/providers/opentelekom/opentelekom.go @@ -141,8 +141,10 @@ func (p *provider) Build(params map[string]interface{}) (providers.Provider, fai return nil, fail.NewError("Structure validation failure: %v", err) } + suffix := getSuffix(params) + providerName := "huaweicloud" - metadataBucketName, xerr := objectstorage.BuildMetadataBucketName(providerName, region, domainName, projectID) + metadataBucketName, xerr := objectstorage.BuildMetadataBucketName(providerName, region, domainName, projectID, suffix) if xerr != nil { return nil, xerr } @@ -221,6 +223,24 @@ next: return wp, nil } +func getSuffix(params map[string]interface{}) string { + suffix := "" + if osto, ok := params["objectstorage"].(map[string]interface{}); ok { + if val, ok := osto["Suffix"].(string); ok { + suffix = val + if suffix != "" { + return suffix + } + } + } + if meta, ok := params["metadata"].(map[string]interface{}); ok { + if val, ok := meta["Suffix"].(string); ok { + suffix = val + } + } + return suffix +} + // ListTemplates ... ; overloads stack.ListTemplates() to allow to filter templates to show // Value of all has no impact on the result func (p provider) ListTemplates(ctx context.Context, all bool) ([]*abstract.HostTemplate, fail.Error) { diff --git a/lib/backend/iaas/providers/outscale/outscale.go b/lib/backend/iaas/providers/outscale/outscale.go index 41da78d5d..25f72e723 100644 --- a/lib/backend/iaas/providers/outscale/outscale.go +++ b/lib/backend/iaas/providers/outscale/outscale.go @@ -115,6 +115,8 @@ func (p *provider) Build(opt map[string]interface{}) (_ providers.Provider, ferr objstorage := remap(opt["objectstorage"]) tc := remap(opt["timings"]) + suffix := getSuffix(metadata, objstorage) + region := get(compute, "Region") if region == "" { return nil, fail.SyntaxError("keyword 'Region' in section 'compute' not found in tenant file", nil, nil) @@ -127,7 +129,7 @@ func (p *provider) Build(opt map[string]interface{}) (_ providers.Provider, ferr } var xerr fail.Error - metadata["Bucket"], xerr = objectstorage.BuildMetadataBucketName(stackName, region, "", userID) + metadata["Bucket"], xerr = objectstorage.BuildMetadataBucketName(stackName, region, "", userID, suffix) if xerr != nil { return nil, xerr } @@ -229,6 +231,21 @@ next: return wp, nil } +func getSuffix(metadata map[string]interface{}, objstorage map[string]interface{}) string { + suffix := "" + if val, ok := objstorage["Suffix"].(string); ok { + suffix = val + if suffix != "" { + return suffix + } + } + if val, ok := metadata["Suffix"].(string); ok { + suffix = val + } + + return suffix +} + // GetAuthenticationOptions returns authentication parameters func (p provider) GetAuthenticationOptions(ctx context.Context) (providers.Config, fail.Error) { if valid.IsNil(p) { diff --git a/lib/backend/iaas/providers/ovh/ovh.go b/lib/backend/iaas/providers/ovh/ovh.go index ea63a056d..0660cd248 100644 --- a/lib/backend/iaas/providers/ovh/ovh.go +++ b/lib/backend/iaas/providers/ovh/ovh.go @@ -207,8 +207,10 @@ func (p *provider) Build(params map[string]interface{}) (providers.Provider, fai return nil, fail.NewError("Structure validation failure: %v", err) } + suffix := getSuffix(params) + providerName := "openstack" - metadataBucketName, xerr := objectstorage.BuildMetadataBucketName(providerName, region, applicationKey, projectName) + metadataBucketName, xerr := objectstorage.BuildMetadataBucketName(providerName, region, applicationKey, projectName, suffix) if xerr != nil { return nil, xerr } @@ -272,6 +274,24 @@ next: return wp, nil } +func getSuffix(params map[string]interface{}) string { + suffix := "" + if osto, ok := params["objectstorage"].(map[string]interface{}); ok { + if val, ok := osto["Suffix"].(string); ok { + suffix = val + if suffix != "" { + return suffix + } + } + } + if meta, ok := params["metadata"].(map[string]interface{}); ok { + if val, ok := meta["Suffix"].(string); ok { + suffix = val + } + } + return suffix +} + // GetAuthenticationOptions returns the auth options func (p provider) GetAuthenticationOptions(ctx context.Context) (providers.Config, fail.Error) { cfg := providers.ConfigMap{} From 28ea451845b4f376f61bd8e45a376b50a51591fb Mon Sep 17 00:00:00 2001 From: oscar Date: Mon, 13 Feb 2023 22:08:56 +0100 Subject: [PATCH 34/43] clean: curl already there --- .../operations/clusterflavors/scripts/node_install_docker.sh | 4 ++-- lib/backend/resources/operations/embeddedfeatures/docker.yml | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/backend/resources/operations/clusterflavors/scripts/node_install_docker.sh b/lib/backend/resources/operations/clusterflavors/scripts/node_install_docker.sh index cdc130520..64b54b7f8 100755 --- a/lib/backend/resources/operations/clusterflavors/scripts/node_install_docker.sh +++ b/lib/backend/resources/operations/clusterflavors/scripts/node_install_docker.sh @@ -55,7 +55,7 @@ install_docker() { debian) export DEBIAN_FRONTEND=noninteractive sfRetryEx 14m 4 "sfApt update --allow-insecure-repositories" || sfFail 192 "error updating" - sfRetryEx 14m 4 "sfApt install -qqy apt-transport-https ca-certificates curl" || sfFail 193 "error installing apt tools (exit code $?)" + sfRetryEx 14m 4 "sfApt install -qqy apt-transport-https ca-certificates" || sfFail 193 "error installing apt tools (exit code $?)" sfRetryEx 14m 4 "(apt-cache show gnupg2 && apt install -qqy gnupg2) || (apt-cache show gnupg && apt install -qqy gnupg)" sfRetryEx 14m 4 "curl -fsSL https://download.docker.com/linux/$LINUX_KIND/gpg | apt-key add -" || sfFail 194 "error updating gpg keys" echo "deb [arch=amd64] https://download.docker.com/linux/$LINUX_KIND $(lsb_release -cs) stable" >/etc/apt/sources.list.d/docker.list @@ -65,7 +65,7 @@ install_docker() { ubuntu) export DEBIAN_FRONTEND=noninteractive sfRetryEx 14m 4 "sfApt update --allow-insecure-repositories" || sfFail 192 "error updating" - sfRetryEx 14m 4 "sfApt install -qqy apt-transport-https ca-certificates curl" || sfFail 193 "error installing apt tools (exit code $?)" + sfRetryEx 14m 4 "sfApt install -qqy apt-transport-https ca-certificates" || sfFail 193 "error installing apt tools (exit code $?)" sfRetryEx 14m 4 "curl -fsSL https://download.docker.com/linux/$LINUX_KIND/gpg | apt-key add -" || sfFail 194 "error updating gpg keys" echo "deb [arch=amd64] https://download.docker.com/linux/$LINUX_KIND $(lsb_release -cs) stable" >/etc/apt/sources.list.d/docker.list sfRetryEx 14m 4 "sfApt update --allow-insecure-repositories" || sfFail 192 "error updating" diff --git a/lib/backend/resources/operations/embeddedfeatures/docker.yml b/lib/backend/resources/operations/embeddedfeatures/docker.yml index cda6af77e..730a34e74 100644 --- a/lib/backend/resources/operations/embeddedfeatures/docker.yml +++ b/lib/backend/resources/operations/embeddedfeatures/docker.yml @@ -139,7 +139,7 @@ feature: debian) export DEBIAN_FRONTEND=noninteractive sfRetryEx {{ or .reserved_LongTimeout "6m" }} {{ or .reserved_DefaultDelay 10 }} "sfApt update --allow-insecure-repositories" || sfFail 192 "error updating" - sfRetryEx {{ or .reserved_LongTimeout "6m" }} {{ or .reserved_DefaultDelay 10 }} "sfApt install -qqy apt-transport-https ca-certificates curl" || sfFail 193 "error installing apt tools (exit code $?)" + sfRetryEx {{ or .reserved_LongTimeout "6m" }} {{ or .reserved_DefaultDelay 10 }} "sfApt install -qqy apt-transport-https ca-certificates" || sfFail 193 "error installing apt tools (exit code $?)" sfRetryEx {{ or .reserved_LongTimeout "6m" }} {{ or .reserved_DefaultDelay 10 }} "(apt-cache show gnupg2 && apt install -qqy gnupg2) || (apt-cache show gnupg && apt install -qqy gnupg)" sfRetryEx {{ or .reserved_LongTimeout "6m" }} {{ or .reserved_DefaultDelay 10 }} "curl -fsSL https://download.docker.com/linux/$LINUX_KIND/gpg | apt-key add -" || sfFail 194 "error updating gpg keys" echo "deb [arch=amd64] https://download.docker.com/linux/$LINUX_KIND $(lsb_release -cs) stable" >/etc/apt/sources.list.d/docker.list @@ -149,7 +149,7 @@ feature: ubuntu) export DEBIAN_FRONTEND=noninteractive sfRetryEx {{ or .reserved_LongTimeout "6m" }} {{ or .reserved_DefaultDelay 10 }} "sfApt update --allow-insecure-repositories" || sfFail 192 "error updating" - sfRetryEx {{ or .reserved_LongTimeout "6m" }} {{ or .reserved_DefaultDelay 10 }} "sfApt install -qqy apt-transport-https ca-certificates curl" || sfFail 193 "error installing apt tools (exit code $?)" + sfRetryEx {{ or .reserved_LongTimeout "6m" }} {{ or .reserved_DefaultDelay 10 }} "sfApt install -qqy apt-transport-https ca-certificates" || sfFail 193 "error installing apt tools (exit code $?)" sfRetryEx {{ or .reserved_LongTimeout "6m" }} {{ or .reserved_DefaultDelay 10 }} "curl -fsSL https://download.docker.com/linux/$LINUX_KIND/gpg | apt-key add -" || sfFail 194 "error updating gpg keys" echo "deb [arch=amd64] https://download.docker.com/linux/$LINUX_KIND $(lsb_release -cs) stable" >/etc/apt/sources.list.d/docker.list sfRetryEx {{ or .reserved_LongTimeout "6m" }} {{ or .reserved_DefaultDelay 10 }} "sfApt update --allow-insecure-repositories" || sfFail 192 "error updating" From 40b8987670d3473cca1ecd43cc23f0be1d424177 Mon Sep 17 00:00:00 2001 From: oscar Date: Mon, 13 Feb 2023 22:53:24 +0100 Subject: [PATCH 35/43] clean: more tolerance installing --- .../clusterflavors/scripts/node_install_docker.sh | 6 +++--- .../resources/operations/embeddedfeatures/docker.yml | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/lib/backend/resources/operations/clusterflavors/scripts/node_install_docker.sh b/lib/backend/resources/operations/clusterflavors/scripts/node_install_docker.sh index 64b54b7f8..98206ae78 100755 --- a/lib/backend/resources/operations/clusterflavors/scripts/node_install_docker.sh +++ b/lib/backend/resources/operations/clusterflavors/scripts/node_install_docker.sh @@ -55,8 +55,8 @@ install_docker() { debian) export DEBIAN_FRONTEND=noninteractive sfRetryEx 14m 4 "sfApt update --allow-insecure-repositories" || sfFail 192 "error updating" - sfRetryEx 14m 4 "sfApt install -qqy apt-transport-https ca-certificates" || sfFail 193 "error installing apt tools (exit code $?)" - sfRetryEx 14m 4 "(apt-cache show gnupg2 && apt install -qqy gnupg2) || (apt-cache show gnupg && apt install -qqy gnupg)" + sfRetryEx 14m 4 "sfApt install --allow-change-held-packages -qqy apt-transport-https ca-certificates" || sfFail 193 "error installing apt tools (exit code $?)" + sfRetryEx 14m 4 "(apt-cache show gnupg2 && apt install -qqy --allow-change-held-packages gnupg2) || (apt-cache show gnupg && apt install -qqy --allow-change-held-packages gnupg)" sfRetryEx 14m 4 "curl -fsSL https://download.docker.com/linux/$LINUX_KIND/gpg | apt-key add -" || sfFail 194 "error updating gpg keys" echo "deb [arch=amd64] https://download.docker.com/linux/$LINUX_KIND $(lsb_release -cs) stable" >/etc/apt/sources.list.d/docker.list sfRetryEx 14m 4 "sfApt update --allow-insecure-repositories" || sfFail 192 "error updating" @@ -65,7 +65,7 @@ install_docker() { ubuntu) export DEBIAN_FRONTEND=noninteractive sfRetryEx 14m 4 "sfApt update --allow-insecure-repositories" || sfFail 192 "error updating" - sfRetryEx 14m 4 "sfApt install -qqy apt-transport-https ca-certificates" || sfFail 193 "error installing apt tools (exit code $?)" + sfRetryEx 14m 4 "sfApt install -qqy --allow-change-held-packages apt-transport-https ca-certificates" || sfFail 193 "error installing apt tools (exit code $?)" sfRetryEx 14m 4 "curl -fsSL https://download.docker.com/linux/$LINUX_KIND/gpg | apt-key add -" || sfFail 194 "error updating gpg keys" echo "deb [arch=amd64] https://download.docker.com/linux/$LINUX_KIND $(lsb_release -cs) stable" >/etc/apt/sources.list.d/docker.list sfRetryEx 14m 4 "sfApt update --allow-insecure-repositories" || sfFail 192 "error updating" diff --git a/lib/backend/resources/operations/embeddedfeatures/docker.yml b/lib/backend/resources/operations/embeddedfeatures/docker.yml index 730a34e74..756eceac3 100644 --- a/lib/backend/resources/operations/embeddedfeatures/docker.yml +++ b/lib/backend/resources/operations/embeddedfeatures/docker.yml @@ -139,7 +139,7 @@ feature: debian) export DEBIAN_FRONTEND=noninteractive sfRetryEx {{ or .reserved_LongTimeout "6m" }} {{ or .reserved_DefaultDelay 10 }} "sfApt update --allow-insecure-repositories" || sfFail 192 "error updating" - sfRetryEx {{ or .reserved_LongTimeout "6m" }} {{ or .reserved_DefaultDelay 10 }} "sfApt install -qqy apt-transport-https ca-certificates" || sfFail 193 "error installing apt tools (exit code $?)" + sfRetryEx {{ or .reserved_LongTimeout "6m" }} {{ or .reserved_DefaultDelay 10 }} "sfApt install -qqy --allow-change-held-packages apt-transport-https ca-certificates" || sfFail 193 "error installing apt tools (exit code $?)" sfRetryEx {{ or .reserved_LongTimeout "6m" }} {{ or .reserved_DefaultDelay 10 }} "(apt-cache show gnupg2 && apt install -qqy gnupg2) || (apt-cache show gnupg && apt install -qqy gnupg)" sfRetryEx {{ or .reserved_LongTimeout "6m" }} {{ or .reserved_DefaultDelay 10 }} "curl -fsSL https://download.docker.com/linux/$LINUX_KIND/gpg | apt-key add -" || sfFail 194 "error updating gpg keys" echo "deb [arch=amd64] https://download.docker.com/linux/$LINUX_KIND $(lsb_release -cs) stable" >/etc/apt/sources.list.d/docker.list @@ -149,7 +149,7 @@ feature: ubuntu) export DEBIAN_FRONTEND=noninteractive sfRetryEx {{ or .reserved_LongTimeout "6m" }} {{ or .reserved_DefaultDelay 10 }} "sfApt update --allow-insecure-repositories" || sfFail 192 "error updating" - sfRetryEx {{ or .reserved_LongTimeout "6m" }} {{ or .reserved_DefaultDelay 10 }} "sfApt install -qqy apt-transport-https ca-certificates" || sfFail 193 "error installing apt tools (exit code $?)" + sfRetryEx {{ or .reserved_LongTimeout "6m" }} {{ or .reserved_DefaultDelay 10 }} "sfApt install -qqy --allow-change-held-packages apt-transport-https ca-certificates" || sfFail 193 "error installing apt tools (exit code $?)" sfRetryEx {{ or .reserved_LongTimeout "6m" }} {{ or .reserved_DefaultDelay 10 }} "curl -fsSL https://download.docker.com/linux/$LINUX_KIND/gpg | apt-key add -" || sfFail 194 "error updating gpg keys" echo "deb [arch=amd64] https://download.docker.com/linux/$LINUX_KIND $(lsb_release -cs) stable" >/etc/apt/sources.list.d/docker.list sfRetryEx {{ or .reserved_LongTimeout "6m" }} {{ or .reserved_DefaultDelay 10 }} "sfApt update --allow-insecure-repositories" || sfFail 192 "error updating" From d00cf61bd429d4f1016bb806950d58dda5408ee7 Mon Sep 17 00:00:00 2001 From: oscar Date: Tue, 14 Feb 2023 14:54:41 +0100 Subject: [PATCH 36/43] logs: log request --- lib/backend/handlers/network.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/lib/backend/handlers/network.go b/lib/backend/handlers/network.go index 55b430c8e..7679888b1 100644 --- a/lib/backend/handlers/network.go +++ b/lib/backend/handlers/network.go @@ -18,6 +18,7 @@ package handlers import ( "context" + "github.com/sanity-io/litter" "net" "github.com/CS-SI/SafeScale/v22/lib/backend" @@ -76,6 +77,11 @@ func (handler *networkHandler) Create(networkReq abstract.NetworkRequest, subnet networkReq.CIDR = defaultCIDR } + logrus.Warningf("netRequest: %s", litter.Sdump(networkReq)) + logrus.Warningf("subnetRequest: %s", litter.Sdump(subnetReq)) + logrus.Warningf("gwName: %s", litter.Sdump(gwName)) + logrus.Warningf("gwSizing: %s", litter.Sdump(gwSizing)) + // If there is conflict with docker quit thisCidr := netretry.CIDRString(networkReq.CIDR) conflict, err := thisCidr.IntersectsWith("172.17.0.0/16") From 8d72c92211a1f46eb207953fc2229eb3bf0b3f57 Mon Sep 17 00:00:00 2001 From: oscar Date: Wed, 15 Feb 2023 15:11:26 +0100 Subject: [PATCH 37/43] bug: metadata didn't handle correctly clusters created with previous versions --- lib/backend/resources/operations/metadatacore.go | 14 +++++++++----- .../resources/operations/metadatacore_debug.go | 14 +++++++++----- 2 files changed, 18 insertions(+), 10 deletions(-) diff --git a/lib/backend/resources/operations/metadatacore.go b/lib/backend/resources/operations/metadatacore.go index 6faf42314..484cd0554 100755 --- a/lib/backend/resources/operations/metadatacore.go +++ b/lib/backend/resources/operations/metadatacore.go @@ -347,7 +347,9 @@ func (myself *MetadataCore) Alter(inctx context.Context, callback resources.Call } if itis, xerr := myself.IsValid(); xerr == nil && !itis { - return fail.InconsistentError("the instance is not valid") + if almost, xerr := myself.isAlmostValid(); xerr == nil && !almost { // metadata from old clusters is INVALID + return fail.InconsistentError("the instance is not valid") + } } ctx, cancel := context.WithCancel(inctx) @@ -378,10 +380,12 @@ func (myself *MetadataCore) Alter(inctx context.Context, callback resources.Call return fail.InconsistentError("uninitialized metadata should not be altered") } - if id, err := myself.getID(); err != nil { - return fail.InconsistentError("uninitialized metadata should not be altered") - } else if id == "" { - return fail.InconsistentError("uninitialized metadata should not be altered") + if myself.kind != "cluster" { // another design mistake that must be horribly patched... + if id, err := myself.getID(); err != nil { + return fail.InconsistentError("uninitialized metadata should not be altered") + } else if id == "" { + return fail.InconsistentError("uninitialized metadata should not be altered") + } } // Make sure myself.properties is populated diff --git a/lib/backend/resources/operations/metadatacore_debug.go b/lib/backend/resources/operations/metadatacore_debug.go index 329174bda..d17dedc7e 100644 --- a/lib/backend/resources/operations/metadatacore_debug.go +++ b/lib/backend/resources/operations/metadatacore_debug.go @@ -363,7 +363,9 @@ func (myself *MetadataCore) Alter(inctx context.Context, callback resources.Call } if itis, xerr := myself.IsValid(); xerr == nil && !itis { - return fail.InconsistentError("the instance is not valid") + if almost, xerr := myself.isAlmostValid(); xerr == nil && !almost { // metadata from old clusters is INVALID + return fail.InconsistentError("the instance is not valid") + } } ctx, cancel := context.WithCancel(inctx) @@ -394,10 +396,12 @@ func (myself *MetadataCore) Alter(inctx context.Context, callback resources.Call return fail.InconsistentError("uninitialized metadata should not be altered") } - if id, err := myself.getID(); err != nil { - return fail.InconsistentError("uninitialized metadata should not be altered") - } else if id == "" { - return fail.InconsistentError("uninitialized metadata should not be altered") + if myself.kind != "cluster" { // another design mistake that must be horribly patched... + if id, err := myself.getID(); err != nil { + return fail.InconsistentError("uninitialized metadata should not be altered") + } else if id == "" { + return fail.InconsistentError("uninitialized metadata should not be altered") + } } // Make sure myself.properties is populated From dd60f01ccdb30c627b8e92e499437dd75d5ee614 Mon Sep 17 00:00:00 2001 From: oscar Date: Wed, 15 Feb 2023 15:14:37 +0100 Subject: [PATCH 38/43] bug: ubuntu 22.04 works now, no need to prevent its use --- .../resources/operations/clustertasks.go | 22 +++++-------------- 1 file changed, 5 insertions(+), 17 deletions(-) diff --git a/lib/backend/resources/operations/clustertasks.go b/lib/backend/resources/operations/clustertasks.go index 565ba0eae..2f6b156b4 100755 --- a/lib/backend/resources/operations/clustertasks.go +++ b/lib/backend/resources/operations/clustertasks.go @@ -174,12 +174,17 @@ func (instance *Cluster) taskCreateCluster(inctx context.Context, params interfa req.NodesDef.Image = req.OS } + // logrus.WithContext(ctx).Warningf("This is the request: %s", litter.Sdump(req)) + gatewaysDef, mastersDef, nodesDef, xerr := instance.determineSizingRequirements(ctx, req) xerr = debug.InjectPlannedFail(xerr) if xerr != nil { return nil, xerr } + // logrus.WithContext(ctx).Warningf("This is treated master request: %s", litter.Sdump(mastersDef)) + // logrus.WithContext(ctx).Warningf("This is treated node request: %s", litter.Sdump(nodesDef)) + if req.Flavor == clusterflavor.K8S { lowerOS := strings.ToLower(req.GatewaysDef.Image) if strings.Contains(lowerOS, "centos 7") { @@ -197,23 +202,6 @@ func (instance *Cluster) taskCreateCluster(inctx context.Context, params interfa } } - if req.Flavor != 0 { - lowerOS := strings.ToLower(req.GatewaysDef.Image) - if strings.Contains(lowerOS, "ubuntu 22.04") { - return nil, fail.NewError("Sorry, Ubuntu 22.04 not supported") - } - - lowerOS = strings.ToLower(req.MastersDef.Image) - if strings.Contains(lowerOS, "ubuntu 22.04") { - return nil, fail.NewError("Sorry, Ubuntu 22.04 not supported") - } - - lowerOS = strings.ToLower(req.NodesDef.Image) - if strings.Contains(lowerOS, "ubuntu 22.04") { - return nil, fail.NewError("Sorry, Ubuntu 22.04 not supported") - } - } - var networkInstance resources.Network var subnetInstance resources.Subnet defer func() { From 0bc2170fc8c0e39ab5d73d5b29e8bbafd00b3556 Mon Sep 17 00:00:00 2001 From: oscar Date: Wed, 15 Feb 2023 15:17:46 +0100 Subject: [PATCH 39/43] bug: disk sizing in cluster creation failed --- lib/backend/iaas/stacks/huaweicloud/compute.go | 4 ++++ lib/backend/resources/operations/host.go | 10 ++++++++++ 2 files changed, 14 insertions(+) diff --git a/lib/backend/iaas/stacks/huaweicloud/compute.go b/lib/backend/iaas/stacks/huaweicloud/compute.go index 479baa66c..a0ed1c3c6 100644 --- a/lib/backend/iaas/stacks/huaweicloud/compute.go +++ b/lib/backend/iaas/stacks/huaweicloud/compute.go @@ -523,6 +523,9 @@ func (s stack) CreateHost(ctx context.Context, request abstract.HostRequest, ext VolumeType: "SSD", VolumeSize: diskSize, } + + // logrus.WithContext(ctx).Warningf("And the real creation parameters: %s", litter.Sdump(bootdiskOpts)) + // Defines server userDataPhase1, xerr := userData.Generate(userdata.PHASE1_INIT) if xerr != nil { @@ -953,6 +956,7 @@ func (s stack) InspectHost(ctx context.Context, hostParam stacks.HostParameter) // ListImages lists available OS images func (s stack) ListImages(ctx context.Context, _ bool) (imgList []*abstract.Image, ferr fail.Error) { defer fail.OnPanic(&ferr) + // FIXME: context must NOT be ignored. if valid.IsNil(s) { return nil, fail.InvalidInstanceError() diff --git a/lib/backend/resources/operations/host.go b/lib/backend/resources/operations/host.go index 5e9406b46..7e7623ee7 100644 --- a/lib/backend/resources/operations/host.go +++ b/lib/backend/resources/operations/host.go @@ -902,6 +902,16 @@ func (instance *Host) implCreate( ar := result{nil, fail.ConvertError(err)} return ar, ar.err } + + if hostDef.MinDiskSize > hostReq.DiskSize { + hostReq.DiskSize = hostDef.MinDiskSize + } + + if hostDef.MaxDiskSize > hostReq.DiskSize { + hostReq.DiskSize = hostDef.MaxDiskSize + } + + // finally the call to create host ahf, userdataContent, xerr = svc.CreateHost(ctx, hostReq, extra) xerr = debug.InjectPlannedFail(xerr) if xerr != nil { From cfa7ca821876cf791e8cfa235986986fdbd58e3a Mon Sep 17 00:00:00 2001 From: oscar Date: Wed, 15 Feb 2023 15:43:34 +0100 Subject: [PATCH 40/43] bug: disabling ansible also must disable ansible-for-cluster --- lib/backend/resources/operations/cluster.go | 47 +++++++++++---------- 1 file changed, 25 insertions(+), 22 deletions(-) diff --git a/lib/backend/resources/operations/cluster.go b/lib/backend/resources/operations/cluster.go index 1229a3882..79d781790 100755 --- a/lib/backend/resources/operations/cluster.go +++ b/lib/backend/resources/operations/cluster.go @@ -2302,31 +2302,34 @@ func (instance *Cluster) configureCluster(inctx context.Context, req abstract.Cl } */ - if itis, err := instance.isFeatureDisabled(ctx, "ansible-for-cluster"); !itis && err == nil { - xerr = instance.Alter(ctx, func(_ data.Clonable, props *serialize.JSONProperties) fail.Error { - return props.Alter(clusterproperty.FeaturesV1, func(clonable data.Clonable) fail.Error { - featuresV1, ok := clonable.(*propertiesv1.ClusterFeatures) - if !ok { - return fail.InconsistentError("'*propertiesv1.ClusterFeatures' expected, '%s' provided", reflect.TypeOf(clonable).String()) - } + // disabling ansible also disables ansible-for-cluster + if aitis, err := instance.isFeatureDisabled(ctx, "ansible"); !aitis && err == nil { + if itis, err := instance.isFeatureDisabled(ctx, "ansible-for-cluster"); !itis && err == nil { + xerr = instance.Alter(ctx, func(_ data.Clonable, props *serialize.JSONProperties) fail.Error { + return props.Alter(clusterproperty.FeaturesV1, func(clonable data.Clonable) fail.Error { + featuresV1, ok := clonable.(*propertiesv1.ClusterFeatures) + if !ok { + return fail.InconsistentError("'*propertiesv1.ClusterFeatures' expected, '%s' provided", reflect.TypeOf(clonable).String()) + } - featuresV1.Installed["ansible"] = &propertiesv1.ClusterInstalledFeature{Name: "ansible"} - featuresV1.Installed["ansible-for-cluster"] = &propertiesv1.ClusterInstalledFeature{Name: "ansible-for-cluster"} - return nil + featuresV1.Installed["ansible"] = &propertiesv1.ClusterInstalledFeature{Name: "ansible"} + featuresV1.Installed["ansible-for-cluster"] = &propertiesv1.ClusterInstalledFeature{Name: "ansible-for-cluster"} + return nil + }) }) - }) - xerr = debug.InjectPlannedFail(xerr) - if xerr != nil { - xerr = fail.Wrap(xerr, callstack.WhereIsThis()) - chRes <- result{xerr} - return - } + xerr = debug.InjectPlannedFail(xerr) + if xerr != nil { + xerr = fail.Wrap(xerr, callstack.WhereIsThis()) + chRes <- result{xerr} + return + } - xerr = instance.regenerateClusterInventory(ctx) - xerr = debug.InjectPlannedFail(xerr) - if xerr != nil { - chRes <- result{xerr} - return + xerr = instance.regenerateClusterInventory(ctx) + xerr = debug.InjectPlannedFail(xerr) + if xerr != nil { + chRes <- result{xerr} + return + } } } From 8d173e3762aaf90837cfdca63d478d843f2dc8e6 Mon Sep 17 00:00:00 2001 From: oscar Date: Wed, 15 Feb 2023 15:43:56 +0100 Subject: [PATCH 41/43] chores: aws version bump --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index ddc9bb3aa..ae75996f7 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,7 @@ go 1.18 require ( github.com/Masterminds/sprig/v3 v3.2.3 github.com/antihax/optional v1.0.0 - github.com/aws/aws-sdk-go v1.44.194 + github.com/aws/aws-sdk-go v1.44.201 github.com/davecgh/go-spew v1.1.1 github.com/deckarep/golang-set v1.8.0 github.com/denisbrodbeck/machineid v1.0.1 diff --git a/go.sum b/go.sum index 17178e55e..4292aba8b 100644 --- a/go.sum +++ b/go.sum @@ -96,8 +96,8 @@ github.com/aws/aws-lambda-go v1.13.3/go.mod h1:4UKl9IzQMoD+QF79YdCuzCwp8VbmG4VAQ github.com/aws/aws-sdk-go v1.20.20/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= github.com/aws/aws-sdk-go v1.26.3/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= github.com/aws/aws-sdk-go v1.27.0/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= -github.com/aws/aws-sdk-go v1.44.194 h1:1ZDK+QDcc5oRbZGgRZSz561eR8XVizXCeGpoZKo33NU= -github.com/aws/aws-sdk-go v1.44.194/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI= +github.com/aws/aws-sdk-go v1.44.201 h1:gKtyFyiVGh/uTW7sCQaoyU6XCUsnI8+WWKmbEaABCfw= +github.com/aws/aws-sdk-go v1.44.201/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI= github.com/aws/aws-sdk-go-v2 v0.18.0/go.mod h1:JWVYvqSMppoMJC0x5wdwiImzgXTI9FuZwxzkQq9wy+g= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= From c4153a85e4ab557ade47aea5629e585080721b0c Mon Sep 17 00:00:00 2001 From: oscar Date: Wed, 15 Feb 2023 16:40:25 +0100 Subject: [PATCH 42/43] test: fixed UT --- lib/backend/iaas/objectstorage/bucketnames_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/backend/iaas/objectstorage/bucketnames_test.go b/lib/backend/iaas/objectstorage/bucketnames_test.go index 45bd67734..bfae10689 100644 --- a/lib/backend/iaas/objectstorage/bucketnames_test.go +++ b/lib/backend/iaas/objectstorage/bucketnames_test.go @@ -61,7 +61,7 @@ func TestBuildMetadataBucketName(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - got, err := BuildMetadataBucketName(tt.args.driver, tt.args.region, tt.args.domain, tt.args.project) + got, err := BuildMetadataBucketName(tt.args.driver, tt.args.region, tt.args.domain, tt.args.project, "") if (err != nil) != tt.wantErr { t.Errorf("BuildMetadataBucketName() error = %v, wantErr %v", err, tt.wantErr) return From 823504f8812db34af0e6eacb5de5acc5888304f3 Mon Sep 17 00:00:00 2001 From: oscar Date: Wed, 15 Feb 2023 17:41:02 +0100 Subject: [PATCH 43/43] clean: removed logs --- lib/backend/handlers/network.go | 6 ------ 1 file changed, 6 deletions(-) diff --git a/lib/backend/handlers/network.go b/lib/backend/handlers/network.go index 7679888b1..55b430c8e 100644 --- a/lib/backend/handlers/network.go +++ b/lib/backend/handlers/network.go @@ -18,7 +18,6 @@ package handlers import ( "context" - "github.com/sanity-io/litter" "net" "github.com/CS-SI/SafeScale/v22/lib/backend" @@ -77,11 +76,6 @@ func (handler *networkHandler) Create(networkReq abstract.NetworkRequest, subnet networkReq.CIDR = defaultCIDR } - logrus.Warningf("netRequest: %s", litter.Sdump(networkReq)) - logrus.Warningf("subnetRequest: %s", litter.Sdump(subnetReq)) - logrus.Warningf("gwName: %s", litter.Sdump(gwName)) - logrus.Warningf("gwSizing: %s", litter.Sdump(gwSizing)) - // If there is conflict with docker quit thisCidr := netretry.CIDRString(networkReq.CIDR) conflict, err := thisCidr.IntersectsWith("172.17.0.0/16")