From eeadd14ef6e7b5511a2ea8480e65cbe5c5abaa18 Mon Sep 17 00:00:00 2001 From: Vadim Gedz Date: Sat, 19 Aug 2023 00:36:02 +0300 Subject: [PATCH 01/29] initial progress checkpoint --- .gitignore | 6 +- Makefile | 19 ++- cmd/argo-watcher/argo.go | 8 -- cmd/argo-watcher/argo_status_updater.go | 10 +- go.mod | 27 +++- go.sum | 97 +++++++++++-- internal/models/argo.go | 95 ++++++++++++- pkg/updater/updater.go | 175 ++++++++++++++++++++++++ sonar-project.properties | 5 - 9 files changed, 398 insertions(+), 44 deletions(-) create mode 100644 pkg/updater/updater.go delete mode 100644 sonar-project.properties diff --git a/.gitignore b/.gitignore index a7c958e0..eddbf9b9 100644 --- a/.gitignore +++ b/.gitignore @@ -11,8 +11,8 @@ static/ **/.envrc **/.env -# directory for built binary files -bin/ +# built binary file +argo-watcher # swagger files **/swagger.* @@ -25,4 +25,4 @@ cmd/argo-watcher/docs cmd/argo-watcher/mock # goreleaser -dist/ \ No newline at end of file +dist/ diff --git a/Makefile b/Makefile index 5690b890..c743ff19 100644 --- a/Makefile +++ b/Makefile @@ -21,16 +21,23 @@ install-deps: ## Install dependencies test: mocks ## Run tests @ARGO_TIMEOUT=1 go test -v ./... -count=1 -coverprofile coverage.out `go list ./... | egrep -v '(test|mock)'` -.PHONY: ensure-dirs -ensure-dirs: - @mkdir -p bin - .PHONY: build -build: ensure-dirs docs ## Build the binaries +build: docs ## Build the binaries @echo "===> Building [$(CYAN)${VERSION}$(RESET)] version of [$(CYAN)argo-watcher$(RESET)] binary" - @CGO_ENABLED=0 go build -ldflags="-s -w -X main.version=${VERSION}" -o bin/argo-watcher ./cmd/argo-watcher + @CGO_ENABLED=0 go build -ldflags="-s -w -X main.version=${VERSION}" -o argo-watcher ./cmd/argo-watcher @echo "===> Done" +.PHONY: kind-upload +kind-upload: + @echo "===> Building [$(CYAN)dev$(RESET)] version of [$(CYAN)argo-watcher$(RESET)] binary" + @CGO_ENABLED=0 GOARCH=arm64 GOOS=linux go build -ldflags="-s -w -X main.version=dev" -o argo-watcher ./cmd/argo-watcher + @echo "===> Building [$(CYAN)argo-watcher$(RESET)] docker image" + @docker build -t argo-watcher:dev . + @echo "===> Loading [$(CYAN)argo-watcher$(RESET)] docker image into [$(CYAN)kind$(RESET)] cluster" + @kind load docker-image argo-watcher:dev -n disposable-cluster + @echo "===> Restarting [$(CYAN)argo-watcher$(RESET)] deployment" + @kubectl rollout restart deploy argo-watcher -n argo-watcher + .PHONY: build-goreleaser build-goreleaser: @echo "===> Building [$(CYAN)${VERSION}$(RESET)] version of [$(CYAN)argo-watcher$(RESET)] binary" diff --git a/cmd/argo-watcher/argo.go b/cmd/argo-watcher/argo.go index 12e4c280..0fd71c58 100644 --- a/cmd/argo-watcher/argo.go +++ b/cmd/argo-watcher/argo.go @@ -15,14 +15,6 @@ var ( argoSyncRetryDelay = 15 * time.Second ) -const ( - ArgoAppSuccess = iota - ArgoAppNotSynced - ArgoAppNotAvailable - ArgoAppNotHealthy - ArgoAppFailed -) - const ( ArgoAPIErrorTemplate = "ArgoCD API Error: %s" argoUnavailableErrorMessage = "connect: connection refused" diff --git a/cmd/argo-watcher/argo_status_updater.go b/cmd/argo-watcher/argo_status_updater.go index 84bd81f2..c6a27101 100644 --- a/cmd/argo-watcher/argo_status_updater.go +++ b/cmd/argo-watcher/argo_status_updater.go @@ -76,6 +76,14 @@ func (updater *ArgoStatusUpdater) waitForApplicationDeployment(task models.Task) var application *models.Application var err error + app, err := updater.argo.api.GetApplication(task.App) + if app.IsManagedByWatcher() { + log.Debug().Str("id", task.Id).Msg("Application is managed by watcher. Updating git repository.") + app.UpdateGitImageTag(&task) + } else { + log.Debug().Str("id", task.Id).Msg("Application is not managed by watcher. Skipping git repository update.") + } + // wait for application to get into deployed status or timeout log.Debug().Str("id", task.Id).Msg("Waiting for rollout") _ = retry.Do(func() error { @@ -107,7 +115,7 @@ func (updater *ArgoStatusUpdater) waitForApplicationDeployment(task models.Task) } func (updater *ArgoStatusUpdater) handleArgoAPIFailure(task models.Task, err error) { - var apiFailureStatus string = models.StatusFailedMessage + var apiFailureStatus = models.StatusFailedMessage // check if ArgoCD didn't have the app if task.IsAppNotFoundError(err) { diff --git a/go.mod b/go.mod index b3850edc..745f1ed9 100644 --- a/go.mod +++ b/go.mod @@ -6,6 +6,8 @@ require ( github.com/avast/retry-go/v4 v4.1.0 github.com/gin-gonic/contrib v0.0.0-20201101042839-6a891bf89f19 github.com/gin-gonic/gin v1.9.1 + github.com/go-git/go-billy/v5 v5.4.1 + github.com/go-git/go-git/v5 v5.8.1 github.com/golang-migrate/migrate/v4 v4.15.2 github.com/google/uuid v1.3.0 github.com/kelseyhightower/envconfig v1.4.0 @@ -17,20 +19,28 @@ require ( github.com/swaggo/gin-swagger v1.5.2 github.com/swaggo/swag v1.16.1 go.uber.org/mock v0.2.0 + gopkg.in/yaml.v2 v2.4.0 gorm.io/datatypes v1.2.0 gorm.io/driver/postgres v1.5.2 gorm.io/gorm v1.25.2 ) require ( + dario.cat/mergo v1.0.0 // indirect github.com/KyleBanks/depth v1.2.1 // indirect + github.com/Microsoft/go-winio v0.6.1 // indirect + github.com/ProtonMail/go-crypto v0.0.0-20230717121422-5aa5874ade95 // indirect + github.com/acomagu/bufpipe v1.0.4 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/bytedance/sonic v1.9.1 // indirect github.com/cespare/xxhash/v2 v2.1.2 // indirect github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 // indirect + github.com/cloudflare/circl v1.3.3 // indirect github.com/davecgh/go-spew v1.1.1 // indirect + github.com/emirpasic/gods v1.18.1 // indirect github.com/gabriel-vasile/mimetype v1.4.2 // indirect github.com/gin-contrib/sse v0.1.0 // indirect + github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect github.com/go-openapi/jsonpointer v0.19.6 // indirect github.com/go-openapi/jsonreference v0.20.2 // indirect github.com/go-openapi/spec v0.20.9 // indirect @@ -40,16 +50,19 @@ require ( github.com/go-playground/validator/v10 v10.14.0 // indirect github.com/go-sql-driver/mysql v1.7.0 // indirect github.com/goccy/go-json v0.10.2 // indirect + github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/golang/protobuf v1.5.2 // indirect github.com/hashicorp/errwrap v1.1.0 // indirect github.com/hashicorp/go-multierror v1.1.1 // indirect github.com/jackc/pgpassfile v1.0.0 // indirect github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a // indirect github.com/jackc/pgx/v5 v5.3.1 // indirect + github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect github.com/jinzhu/inflection v1.0.0 // indirect github.com/jinzhu/now v1.1.5 // indirect github.com/josharian/intern v1.0.0 // indirect github.com/json-iterator/go v1.1.12 // indirect + github.com/kevinburke/ssh_config v1.2.0 // indirect github.com/klauspost/cpuid/v2 v2.2.4 // indirect github.com/leodido/go-urn v1.2.4 // indirect github.com/mailru/easyjson v0.7.7 // indirect @@ -59,20 +72,26 @@ require ( github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect github.com/pelletier/go-toml/v2 v2.0.8 // indirect + github.com/pjbgf/sha1cd v0.3.0 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/prometheus/client_model v0.2.0 // indirect github.com/prometheus/common v0.32.1 // indirect github.com/prometheus/procfs v0.7.3 // indirect + github.com/sergi/go-diff v1.1.0 // indirect + github.com/skeema/knownhosts v1.2.0 // indirect github.com/twitchyliquid64/golang-asm v0.15.1 // indirect github.com/ugorji/go/codec v1.2.11 // indirect + github.com/xanzy/ssh-agent v0.3.3 // indirect go.uber.org/atomic v1.7.0 // indirect golang.org/x/arch v0.3.0 // indirect - golang.org/x/crypto v0.10.0 // indirect - golang.org/x/net v0.11.0 // indirect - golang.org/x/sys v0.9.0 // indirect - golang.org/x/text v0.10.0 // indirect + golang.org/x/crypto v0.11.0 // indirect + golang.org/x/mod v0.11.0 // indirect + golang.org/x/net v0.12.0 // indirect + golang.org/x/sys v0.10.0 // indirect + golang.org/x/text v0.11.0 // indirect golang.org/x/tools v0.10.0 // indirect google.golang.org/protobuf v1.30.0 // indirect + gopkg.in/warnings.v0 v0.1.2 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect gorm.io/driver/mysql v1.4.7 // indirect ) diff --git a/go.sum b/go.sum index 6fdc67ae..837fca7e 100644 --- a/go.sum +++ b/go.sum @@ -48,6 +48,8 @@ cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0Zeo cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= +dario.cat/mergo v1.0.0 h1:AGCNq9Evsj31mOgNPcLyXc+4PNABt905YmuqPYYpBWk= +dario.cat/mergo v1.0.0/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= gioui.org v0.0.0-20210308172011-57750fc8a0a6/go.mod h1:RSH6KIUZ0p2xy5zHDxgAM4zumjgTw83q2ge/PI+yyw8= github.com/AdaLogics/go-fuzz-headers v0.0.0-20210715213245-6c3934b029d8/go.mod h1:CzsSbkDixRphAF5hS6wbMKq0eI6ccJRb7/A0M6JBnwg= @@ -86,8 +88,9 @@ github.com/Microsoft/go-winio v0.4.17-0.20210211115548-6eac466e5fa3/go.mod h1:JP github.com/Microsoft/go-winio v0.4.17-0.20210324224401-5516f17a5958/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84= github.com/Microsoft/go-winio v0.4.17/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84= github.com/Microsoft/go-winio v0.5.1/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84= -github.com/Microsoft/go-winio v0.5.2 h1:a9IhgEQBCUEk6QCdml9CiJGhAws+YwffDHEMp1VMrpA= github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY= +github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow= +github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM= github.com/Microsoft/hcsshim v0.8.6/go.mod h1:Op3hHsoHPAvb6lceZHDtd9OkTew38wNoXnJs8iY7rUg= github.com/Microsoft/hcsshim v0.8.7-0.20190325164909-8abdbb8205e4/go.mod h1:Op3hHsoHPAvb6lceZHDtd9OkTew38wNoXnJs8iY7rUg= github.com/Microsoft/hcsshim v0.8.7/go.mod h1:OHd7sQqRFrYd3RmSgbgji+ctCwkbq2wbEYNSzOYtcBQ= @@ -104,11 +107,15 @@ github.com/Microsoft/hcsshim/test v0.0.0-20210227013316-43a75bb4edd3/go.mod h1:m github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ= github.com/NYTimes/gziphandler v1.1.1/go.mod h1:n/CVRwUEOgIxrgPvAQhUUr9oeUtvrhMomdKFjzJNB0c= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= +github.com/ProtonMail/go-crypto v0.0.0-20230717121422-5aa5874ade95 h1:KLq8BE0KwCL+mmXnjLWEAOYO+2l2AE4YMmqG1ZpZHBs= +github.com/ProtonMail/go-crypto v0.0.0-20230717121422-5aa5874ade95/go.mod h1:EjAoLdwvbIOoOQr3ihjnSoLZRtE8azugULFRteWMNc0= github.com/PuerkitoBio/purell v1.0.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= 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/logrus-bugsnag v0.0.0-20171204204709-577dee27f20d/go.mod h1:HI8ITrYtUY+O+ZhtlqUnD8+KwNPOyugEhfP9fdUIaEQ= +github.com/acomagu/bufpipe v1.0.4 h1:e3H4WUzM3npvo5uv95QuJM3cQspFNtFBzvJ2oNjKIDQ= +github.com/acomagu/bufpipe v1.0.4/go.mod h1:mxdxdup/WdsKVreO5GpW4+M/1CE2sMG4jeGJ2sYmHc4= github.com/agiledragon/gomonkey/v2 v2.3.1/go.mod h1:ap1AmDzcVOAz1YpeJ3TCzIgstoaWLA6jbbgxfB4w2iY= github.com/ajstarks/svgo v0.0.0-20180226025133-644b8db467af/go.mod h1:K08gAheRH3/J6wwsYMMT4xOr94bZjxIelGM0+d/wbFw= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= @@ -118,6 +125,7 @@ github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRF github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= github.com/alexflint/go-filemutex v0.0.0-20171022225611-72bdc8eae2ae/go.mod h1:CgnQgUtFrFz9mxFNtED3jI5tLDjKlOM+oUF/sTk6ps0= github.com/alexflint/go-filemutex v1.1.0/go.mod h1:7P4iRhttt/nUvUOrYIhcpMzv2G6CY9UnI16Z+UJqRyk= +github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be h1:9AeTilPcZAjCFIImctFaOjnTIavg87rW78vTPkQqLI8= github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= github.com/apache/arrow/go/arrow v0.0.0-20210818145353-234c94e4ce64/go.mod h1:2qMFB56yOP3KzkB3PbYZ4AlUFg3a88F67TIx5lB/WwY= github.com/apache/arrow/go/arrow v0.0.0-20211013220434-5962184e7a30/go.mod h1:Q7yQnSMnLvcXlZ8RV+jwz/6y1rQTqbX6C82SndT52Zs= @@ -125,6 +133,7 @@ github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hC github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= 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/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio= github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY= github.com/avast/retry-go/v4 v4.1.0 h1:CwudD9anYv6JMVnDuTRlK6kLo4dBamiL+F3U8YDiyfg= github.com/avast/retry-go/v4 v4.1.0/go.mod h1:HqmLvS2VLdStPCGDFjSuZ9pzlTqVRldCI4w2dO4m1Ms= @@ -178,6 +187,7 @@ github.com/buger/jsonparser v1.1.1/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx2 github.com/bugsnag/bugsnag-go v0.0.0-20141110184014-b1d153021fcd/go.mod h1:2oa8nejYd4cQ/b0hMIopN0lCRxU0bueqREvZLWFrtK8= github.com/bugsnag/osext v0.0.0-20130617224835-0dd3f918b21b/go.mod h1:obH5gd0BsqsP2LwDJ9aOkm/6J86V6lyAXCoQWGw3K50= github.com/bugsnag/panicwrap v0.0.0-20151223152923-e2c28503fcd0/go.mod h1:D/8v3kj0zr8ZAKg1AQ6crr+5VwKN5eIywRkfhyM/+dE= +github.com/bwesterb/go-ristretto v1.2.3/go.mod h1:fUIoIZaG73pV5biE2Blr2xEzDoMj7NFEuV9ekS419A0= github.com/bytedance/sonic v1.5.0/go.mod h1:ED5hyg4y6t3/9Ku1R6dU/4KyJ48DZ4jPhfY1O2AihPM= github.com/bytedance/sonic v1.9.1 h1:6iJ6NqdoxCDr6mbY8h18oSO+cShGSMRGCEo7F2h0x8s= github.com/bytedance/sonic v1.9.1/go.mod h1:i736AoUSYt75HyZLoJW9ERYxcy6eaN6h4BZXU064P/U= @@ -207,6 +217,8 @@ github.com/cilium/ebpf v0.4.0/go.mod h1:4tRaxcgiL706VnOzHOdBlY8IEAIdxINsQBcU4xJJ github.com/cilium/ebpf v0.6.2/go.mod h1:4tRaxcgiL706VnOzHOdBlY8IEAIdxINsQBcU4xJJXRs= github.com/cilium/ebpf v0.7.0/go.mod h1:/oI2+1shJiTGAMgl6/RgJr36Eo1jzrRcAWbcXO2usCA= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= +github.com/cloudflare/circl v1.3.3 h1:fE/Qz0QdIGqeWfnwq0RE0R7MI51s0M2E4Ga9kq5AEMs= +github.com/cloudflare/circl v1.3.3/go.mod h1:5XYMA4rFBvNIrhs50XuiBJ15vF2pZn4nnUKZrLbUZFA= github.com/cloudflare/golz4 v0.0.0-20150217214814-ef862a3cdc58/go.mod h1:EOBUe0h4xcZ5GoxqC5SDxFQ8gwyZPKQoEzownBlhI80= 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= @@ -388,8 +400,11 @@ github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:Htrtb github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/edsrzf/mmap-go v0.0.0-20170320065105-0bce6a688712/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M= github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc= +github.com/elazarl/goproxy v0.0.0-20221015165544-a0805db90819 h1:RIB4cRk+lBqKK3Oy0r2gRX4ui7tuhiZq2SuTtTCi0/0= github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= github.com/emicklei/go-restful v2.9.5+incompatible/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= +github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc= +github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ= 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= @@ -432,10 +447,18 @@ github.com/gin-gonic/contrib v0.0.0-20201101042839-6a891bf89f19/go.mod h1:iqneQ2 github.com/gin-gonic/gin v1.8.1/go.mod h1:ji8BvRH1azfM+SYow9zQ6SZMvR8qOMZHmsCuWR9tTTk= github.com/gin-gonic/gin v1.9.1 h1:4idEAncQnU5cB7BeOkPtxjfCSye0AAm1R0RVIqJ+Jmg= github.com/gin-gonic/gin v1.9.1/go.mod h1:hPrL7YrpYKXt5YId3A/Tnip5kqbEAP+KLuI3SUcPTeU= +github.com/gliderlabs/ssh v0.3.5 h1:OcaySEmAQJgyYcArR+gGGTHCyE7nvhEMTlYY+Dp8CpY= github.com/go-fonts/dejavu v0.1.0/go.mod h1:4Wt4I4OU2Nq9asgDCteaAaWZOV24E+0/Pwo0gppep4g= github.com/go-fonts/latin-modern v0.2.0/go.mod h1:rQVLdDMK+mK1xscDwsqM5J8U2jrRa3T0ecnM9pNujks= github.com/go-fonts/liberation v0.1.1/go.mod h1:K6qoJYypsmfVjWg8KOVDQhLc8UDgIK2HYqyqAO9z7GY= github.com/go-fonts/stix v0.1.0/go.mod h1:w/c1f0ldAUlJmLBvlbkvVXLAD+tAMqobIIQpmnUIzUY= +github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 h1:+zs/tPmkDkHx3U66DAb0lQFJrpS6731Oaa12ikc+DiI= +github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376/go.mod h1:an3vInlBmSxCcxctByoQdvwPiA7DTK7jaaFDBTtu0ic= +github.com/go-git/go-billy/v5 v5.4.1 h1:Uwp5tDRkPr+l/TnbHOQzp+tmJfLceOlbVucgpTz8ix4= +github.com/go-git/go-billy/v5 v5.4.1/go.mod h1:vjbugF6Fz7JIflbVpl1hJsGjSHNltrSw45YK/ukIvQg= +github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20230305113008-0c11038e723f h1:Pz0DHeFij3XFhoBRGUDPzSJ+w2UcK5/0JvF8DRI58r8= +github.com/go-git/go-git/v5 v5.8.1 h1:Zo79E4p7TRk0xoRgMq0RShiTHGKcKI4+DI6BfJc/Q+A= +github.com/go-git/go-git/v5 v5.8.1/go.mod h1:FHFuoD6yGz5OSKEBK+aWN9Oah0q54Jxl0abmj6GnqAo= 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= @@ -559,6 +582,7 @@ github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4er github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= @@ -607,8 +631,8 @@ github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.6 h1:BKbKCqvP6I+rmFHt06ZmyQtvB8xAkWdhFyr0ZUNZcxQ= github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= github.com/google/go-containerregistry v0.5.1/go.mod h1:Ct15B4yir3PLOP5jsy0GNeYVaIZs/MK/Jz5any1wFW0= github.com/google/go-github/v39 v39.2.0/go.mod h1:C1s8C5aCC9L+JXIYpJM5GYytdX52vC1bLvHEF1IhBrE= github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= @@ -753,6 +777,8 @@ github.com/jackc/puddle v0.0.0-20190608224051-11cab39313c9/go.mod h1:m4B5Dj62Y0f github.com/jackc/puddle v1.1.0/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= github.com/jackc/puddle v1.1.1/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= github.com/jackc/puddle v1.1.3/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= +github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A= +github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo= github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E= github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc= github.com/jinzhu/now v1.1.1/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= @@ -794,6 +820,8 @@ github.com/karrick/godirwalk v1.10.3/go.mod h1:RoGL9dQei4vP9ilrpETWE8CLOZ1kiN0Lh github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8= github.com/kelseyhightower/envconfig v1.4.0 h1:Im6hONhd3pLkfDFsbRgu68RDNkGF1r3dvMUtDTo2cv8= github.com/kelseyhightower/envconfig v1.4.0/go.mod h1:cccZRl6mQpaq41TPp5QxidR+Sa3axMbJDNb//FQX6Gg= +github.com/kevinburke/ssh_config v1.2.0 h1:x584FjTGwHzMwvHx18PXxbBVzfnxogHaAReU4gf13a4= +github.com/kevinburke/ssh_config v1.2.0/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM= 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= @@ -815,8 +843,8 @@ github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFB github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= -github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/pty v1.1.5/go.mod h1:9r2w37qlBe7rQ6e1fg1S/9xpWHSnaqNdHD3WcMdbPDA= github.com/kr/pty v1.1.8/go.mod h1:O1sed60cT9XZ5uDucP5qwvh+TE3NnUj51EiZO/lmSfw= @@ -850,6 +878,8 @@ github.com/markbates/oncer v0.0.0-20181203154359-bf2de49a0be2/go.mod h1:Ld9puTsI github.com/markbates/pkger v0.15.1/go.mod h1:0JoVlrol20BSywW79rN3kdFFsE5xYM+rSCQDXbLhiuI= github.com/markbates/safe v1.0.1/go.mod h1:nAqgmRi7cY2nqMc92/bSEeQA+R4OheNU2T1kNSCBdG0= github.com/marstr/guid v1.1.0/go.mod h1:74gB1z2wpxxInTG6yaqA7KrtM0NZ+RbrcqDvYHefzho= +github.com/matryer/is v1.2.0 h1:92UTHpy8CDwaJ08GqLDzhhuixiBUUD1p3AU6PHddz4A= +github.com/matryer/is v1.2.0/go.mod h1:2fLPjFQM9rhQ15aVEtbuwhJinnOqrmgXPNdZsdwlWXA= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ= github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= @@ -1002,6 +1032,8 @@ github.com/phpdave11/gofpdi v1.0.12/go.mod h1:vBmVV0Do6hSBHC8uKUQ71JGW+ZGQq74llk github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= github.com/pierrec/lz4/v4 v4.1.8/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4= github.com/pierrre/gotestcover v0.0.0-20160517101806-924dca7d15f0/go.mod h1:4xpMLz7RBWyB+ElzHu8Llua96TRCB3YwX+l5EP1wmHk= +github.com/pjbgf/sha1cd v0.3.0 h1:4D5XXmUUBUl/xQ6IjCkEAbqXskkq/4O7LmGn0AqMDs4= +github.com/pjbgf/sha1cd v0.3.0/go.mod h1:nZ1rrWOcGJ5uZgEEVL1VUM9iRQiZvWdbZjkKyFzPPsI= github.com/pkg/browser v0.0.0-20210706143420-7d21f8c997e2/go.mod h1:HKlIX3XHQyzLZPlr7++PzdhaXEj94dEiJgZDTsxEqUI= github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8/go.mod h1:HKlIX3XHQyzLZPlr7++PzdhaXEj94dEiJgZDTsxEqUI= github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= @@ -1063,8 +1095,8 @@ github.com/rogpeppe/go-internal v1.1.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFR github.com/rogpeppe/go-internal v1.2.2/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= -github.com/rogpeppe/go-internal v1.8.0 h1:FCbCCtXNOY3UtUuHUYaghJg4y7Fd14rXifAYUAtL9R8= github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE= +github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8= github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ= github.com/rs/xid v1.4.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= github.com/rs/zerolog v1.13.0/go.mod h1:YbFCdg8HfsridGWAh22vktObvhZbQsZXe4/zB0OKkWU= @@ -1082,6 +1114,8 @@ github.com/sclevine/spec v1.2.0/go.mod h1:W4J29eT/Kzv7/b9IWLB055Z+qvVC9vt0Arko24 github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= github.com/seccomp/libseccomp-golang v0.9.1/go.mod h1:GbW5+tmTXfcxTToHLXlScSlAvWlF4P2Ca7zGrPiEpWo= github.com/seccomp/libseccomp-golang v0.9.2-0.20210429002308-3879420cc921/go.mod h1:JA8cRccbGaA1s33RQf7Y1+q9gHmZX1yB/z9WDN1C6fg= +github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0= +github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= github.com/shopspring/decimal v0.0.0-20180709203117-cd690d0c9e24/go.mod h1:M+9NzErvs504Cn4c5DxATwIqPbtswREoFCre64PpcG4= github.com/shopspring/decimal v0.0.0-20200227202807-02e2044944cc/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= @@ -1094,8 +1128,10 @@ github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMB github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= -github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE= github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= +github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0= +github.com/skeema/knownhosts v1.2.0 h1:h9r9cf0+u7wSE+M183ZtMGgOJKiL96brpaz5ekfJCpM= +github.com/skeema/knownhosts v1.2.0/go.mod h1:g4fPeYpque7P0xefxtGzV81ihjC8sX2IqpAoNkjxbMo= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= github.com/smartystreets/goconvey v0.0.0-20190330032615-68dc04aab96a/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= @@ -1182,6 +1218,8 @@ github.com/vishvananda/netns v0.0.0-20210104183010-2eb08e3e575f/go.mod h1:DD4vA1 github.com/willf/bitset v1.1.11-0.20200630133818-d5bec3311243/go.mod h1:RjeCKbqT1RxIR/KWY6phxZiaY1IyutSBfGjNPySAYV4= github.com/willf/bitset v1.1.11/go.mod h1:83CECat5yLh5zVOf4P1ErAgKA5UDvKtgyUABdr3+MjI= github.com/xanzy/go-gitlab v0.15.0/go.mod h1:8zdQa/ri1dfn8eS3Ir1SyfvOKlw7WBJ8DVThkpGiXrs= +github.com/xanzy/ssh-agent v0.3.3 h1:+/15pJfg/RsTxqYcX6fHqOXZwwMP+2VyYWJeWM2qQFM= +github.com/xanzy/ssh-agent v0.3.3/go.mod h1:6dzNDKs0J9rVPHPhaGCukekBHKqfl+L3KghI1Bc68Uw= github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI= github.com/xdg-go/scram v1.0.2/go.mod h1:1WAq6h33pAW+iRreB34OORO2Nf7qel3VV3fjBj+hCSs= github.com/xdg-go/stringprep v1.0.2/go.mod h1:8F9zXuvzgwmyT5DUm4GUfZGDdT3W+LCvS6+da4O5kxM= @@ -1197,6 +1235,7 @@ github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/yuin/goldmark v1.4.0/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= github.com/yvasiyarov/go-metrics v0.0.0-20140926110328-57bccd1ccd43/go.mod h1:aX5oPXxHm3bOH+xeAttToC8pqch2ScQN/JoXYupl6xs= github.com/yvasiyarov/gorelic v0.0.0-20141212073537-a9bba5b9ab50/go.mod h1:NUSPSUX/bi6SeDMUh6brw0nXpxHnc96TguQh0+r/ssA= github.com/yvasiyarov/newrelic_platform_go v0.0.0-20140908184405-b21fdbd4370f/go.mod h1:GlGEuHIJweS1mbCqG+7vt2nvWLzLLnRHbXz5JKd/Qbg= @@ -1288,8 +1327,11 @@ golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.10.0 h1:LKqV2xt9+kDzSTfOhx4FrkEBcMrAgHSYgzywV9zcGmM= -golang.org/x/crypto v0.10.0/go.mod h1:o4eNf7Ede1fv+hwOwZsTHl9EsPFO6q6ZvYR8vYfY45I= +golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/crypto v0.3.1-0.20221117191849-2c476679df9a/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4= +golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU= +golang.org/x/crypto v0.11.0 h1:6Ewdq3tDic1mg5xRO4milcWCfMVQhI4NkqWWvqejpuA= +golang.org/x/crypto v0.11.0/go.mod h1:xgJhtzW8F9jGdVFWZESrid1U1bjeNy4zgy5cRr/CIio= golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= @@ -1337,7 +1379,10 @@ golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.5.0/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= +golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= +golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.11.0 h1:bUO06HqtnRcc/7l71XBe4WcqTZ+3AH1J59zWDDwLKgU= +golang.org/x/mod v0.11.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/net v0.0.0-20180218175443-cbe0f9307d01/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 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= @@ -1402,13 +1447,18 @@ golang.org/x/net v0.0.0-20210614182718-04defd469f4e/go.mod h1:9nx3DQGgdP8bBQD5qx golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210813160813-60bc85c4be6d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210825183410-e898025ed96a/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-20211216030914-fe4d6282115f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220111093109-d55c255bac03/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.11.0 h1:Gi2tvZIJyBtO9SDr1q9h5hEQCp/4L2RQ+ar0qjx2oNU= -golang.org/x/net v0.11.0/go.mod h1:2L/ixqYpgIVXmeoSA/4Lu7BzTG4KIyPIryS4IsOd1oQ= +golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= +golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= +golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= +golang.org/x/net v0.12.0 h1:cfawfvKITfUsFCeJIHJrbSxpeu/E81khclypR0GVT50= +golang.org/x/net v0.12.0/go.mod h1:zEVYFnQC7m/vmpQFELhcD1EWkZlX69l4oqgmer6hfKA= golang.org/x/oauth2 v0.0.0-20180227000427-d7d64896b5ff/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20181106182150-f42d05182288/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= @@ -1439,6 +1489,9 @@ golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E= golang.org/x/sys v0.0.0-20180224232135-f6cff0780e54/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= @@ -1563,16 +1616,26 @@ golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220111092808-5a964db01320/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220317061510-51cd9980dadf/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220704084225-05e143d24a9e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.9.0 h1:KS/R3tvhPqvJvwcKfnBHJwwthS11LRhmM5D59eEXa0s= -golang.org/x/sys v0.9.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.10.0 h1:SqMFp9UcQJZa+pmYuAKjd9xq1f0j5rLcDIk0mj4qAsA= +golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= +golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= +golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= +golang.org/x/term v0.10.0 h1:3R7pNqamzBraeqj/Tj8qt1aQ2HpmlC+Cx/qL/7hn4/c= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -1582,8 +1645,11 @@ golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/text v0.10.0 h1:UpjohKhiEgNc0CSauXmwYftY1+LlaC75SJwh0SgCX58= -golang.org/x/text v0.10.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= +golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= +golang.org/x/text v0.11.0 h1:LAntKIrcmeSKERyiOh0XMV39LXS8IE9UL2yP7+f5ij4= +golang.org/x/text v0.11.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= 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= @@ -1672,6 +1738,8 @@ golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.7/go.mod h1:LGqMHiF4EqQNHR1JncWGqT5BVaXmza+X+BDGol+dOxo= +golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= +golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= golang.org/x/tools v0.10.0 h1:tvDr/iQoUqNdohiYm0LmmKcBk+q86lb9EprIUFhHHGg= golang.org/x/tools v0.10.0/go.mod h1:UJwyiVBsOA2uwvK/e5OY3GTpDUJriEd+/YlqAwLPmyM= golang.org/x/xerrors v0.0.0-20190410155217-1f06c39b4373/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -1679,7 +1747,6 @@ golang.org/x/xerrors v0.0.0-20190513163551-3ee3066db522/go.mod h1:I/5z698sn9Ka8T golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= gonum.org/v1/gonum v0.0.0-20180816165407-929014505bf4/go.mod h1:Y+Yx5eoAFn32cQvJDxZx5Dpnq+c3wtXuadVZAcxbbBo= gonum.org/v1/gonum v0.8.2/go.mod h1:oe/vMfY3deqTw+1EZJhuvEW2iwGF1bW9wwu7XCu0+v0= @@ -1873,6 +1940,8 @@ gopkg.in/square/go-jose.v2 v2.2.2/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76 gopkg.in/square/go-jose.v2 v2.3.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= gopkg.in/square/go-jose.v2 v2.5.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= +gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME= +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= diff --git a/internal/models/argo.go b/internal/models/argo.go index 9d02dc12..4bb5e60f 100644 --- a/internal/models/argo.go +++ b/internal/models/argo.go @@ -2,6 +2,8 @@ package models import ( "fmt" + "github.com/rs/zerolog/log" + "github.com/shini4i/argo-watcher/pkg/updater" "strings" "github.com/shini4i/argo-watcher/internal/helpers" @@ -36,6 +38,17 @@ type ApplicationResource struct { } type Application struct { + Metadata struct { + Name string `json:"name"` + Annotations map[string]string `json:"annotations"` + } + Spec struct { + Source struct { + RepoURL string `json:"repoURL"` + TargetRevision string `json:"targetRevision"` + Path string `json:"path"` + } + } Status struct { Health struct { Status string `json:"status"` @@ -57,7 +70,7 @@ type Application struct { } `json:"status"` } -// Calculates application rollout status depending on the expected images and proxy configuration. +// GetRolloutStatus calculates application rollout status depending on the expected images and proxy configuration. func (app *Application) GetRolloutStatus(rolloutImages []string, registryProxyUrl string) string { // check if all the images rolled out for _, image := range rolloutImages { @@ -80,7 +93,7 @@ func (app *Application) GetRolloutStatus(rolloutImages []string, registryProxyUr return ArgoRolloutAppSuccess } -// Generate rollout failure message. +// GetRolloutMessage generates rollout failure message. func (app *Application) GetRolloutMessage(status string, rolloutImages []string) string { // handle application sync failure switch status { @@ -128,7 +141,7 @@ func (app *Application) GetRolloutMessage(status string, rolloutImages []string) ) } -// Check if rollout status is final. +// IsFinalRolloutStatus checks if rollout status is final. func (app *Application) IsFinalRolloutStatus(status string) bool { return status == ArgoRolloutAppSuccess } @@ -168,6 +181,82 @@ func (app *Application) ListUnhealthyResources() []string { return list } +// IsManagedByWatcher checks if the application is managed by the watcher. +// It checks if the application's metadata contains the "argo-watcher/managed" annotation with the value "true". +func (app *Application) IsManagedByWatcher() bool { + if app.Metadata.Annotations == nil { + return false + } + return app.Metadata.Annotations["argo-watcher/managed"] == "true" +} + +func (app *Application) processAppAnnotations(annotations map[string]string, task *Task) *updater.ArgoOverrideFile { + overrideFileContent := updater.ArgoOverrideFile{} + managedImages := extractManagedImages(annotations) + + if len(managedImages) == 0 { + log.Error().Msgf("argo-watcher/managed-images annotation not found, skipping image update") + return nil + } + + for _, image := range task.Images { + for appAlias, appImage := range managedImages { + if image.Image == appImage { + if tagPath, exists := annotations[fmt.Sprintf("argo-watcher/%s.helm.image-tag", appAlias)]; exists { + overrideFileContent.Helm.Parameters = append(overrideFileContent.Helm.Parameters, updater.ArgoParameterOverride{ + Name: tagPath, + Value: image.Tag, + }) + } else { + log.Error().Msgf("argo-watcher/%s.helm.image-tag annotation not found, skipping image %s update", appAlias, image.Image) + } + } + } + } + + return &overrideFileContent +} + +func (app *Application) UpdateGitImageTag(task *Task) { + if app.Spec.Source.Path == "" { + log.Warn().Str("id", task.Id).Msgf("No path found for app %s, unsupported Application configuration", app.Metadata.Name) + return + } + + releaseOverrides := app.processAppAnnotations(app.Metadata.Annotations, task) + if releaseOverrides == nil { + log.Warn().Str("id", task.Id).Msgf("No release overrides found for app %s", app.Metadata.Name) + return + } + + git := updater.GitRepo{RepoURL: app.Spec.Source.RepoURL, BranchName: app.Spec.Source.TargetRevision, Path: app.Spec.Source.Path} + if err := git.Clone(); err != nil { + log.Error().Str("id", task.Id).Msgf("Failed to clone git repository %s", app.Spec.Source.RepoURL) + return + } + + if err := git.UpdateApp(app.Metadata.Name, releaseOverrides); err != nil { + log.Error().Str("id", task.Id).Msgf("Failed to update git repository %s", app.Spec.Source.RepoURL) + return + } +} + +// extractManagedImages extracts the managed images from the application's annotations. +// It returns a map of the managed images, where the key is the application alias and the value is the image name. +func extractManagedImages(annotations map[string]string) map[string]string { + managedImages := map[string]string{} + + for annotation, value := range annotations { + if annotation == "argo-watcher/managed-images" { + for _, image := range strings.Split(value, ",") { + managedImages[strings.Split(image, "=")[0]] = strings.Split(image, "=")[1] + } + } + } + + return managedImages +} + type Userinfo struct { LoggedIn bool `json:"loggedIn"` Username string `json:"username"` diff --git a/pkg/updater/updater.go b/pkg/updater/updater.go new file mode 100644 index 00000000..37700066 --- /dev/null +++ b/pkg/updater/updater.go @@ -0,0 +1,175 @@ +package updater + +import ( + "fmt" + "github.com/go-git/go-billy/v5" + "github.com/go-git/go-billy/v5/memfs" + "github.com/go-git/go-git/v5" + "github.com/go-git/go-git/v5/plumbing" + "github.com/go-git/go-git/v5/plumbing/object" + "github.com/go-git/go-git/v5/plumbing/transport/ssh" + "github.com/go-git/go-git/v5/storage/memory" + "gopkg.in/yaml.v2" + "io" + "time" +) + +type ArgoOverrideFile struct { + Helm struct { + Parameters []ArgoParameterOverride `yaml:"parameters"` + } `yaml:"helm"` +} + +type ArgoParameterOverride struct { + Name string `yaml:"name"` + Value string `yaml:"value"` + ForceString bool `yaml:"forceString"` +} + +type GitRepo struct { + RepoURL string + BranchName string + Path string + fs billy.Filesystem + localRepo *git.Repository + sshAuth *ssh.PublicKeys +} + +func (repo *GitRepo) Clone() error { + var err error + + repo.fs = memfs.New() + + repo.sshAuth, err = ssh.NewPublicKeysFromFile("git", "/tmp/id_rsa", "") + if err != nil { + return err + } + + repo.localRepo, err = git.Clone(memory.NewStorage(), repo.fs, &git.CloneOptions{ + URL: repo.RepoURL, + ReferenceName: plumbing.ReferenceName("refs/heads/" + repo.BranchName), + SingleBranch: true, + Auth: repo.sshAuth, + }) + + return err +} + +func (repo *GitRepo) UpdateApp(appName string, overrideContent *ArgoOverrideFile) error { + overrideFileName := fmt.Sprintf("%s/.argocd-source-%s.yaml", repo.Path, appName) + commitMsg := fmt.Sprintf("argo-watcher(%s): update image tag", appName) + + overrideContent, err := repo.mergeOverrideFileContent(overrideFileName, overrideContent) + if err != nil { + return err + } + + if err := repo.commit(overrideFileName, commitMsg, overrideContent); err != nil { + return err + } + return nil +} + +func (repo *GitRepo) mergeOverrideFileContent(overrideFileName string, overrideContent *ArgoOverrideFile) (*ArgoOverrideFile, error) { + if !repo.overrideFileExists(overrideFileName) { + return overrideContent, nil + } + + existingOverrideFile := ArgoOverrideFile{} + tmp, err := repo.fs.Open(overrideFileName) + if err != nil { + return nil, err + } + + defer func(tmp billy.File) { + err := tmp.Close() + if err != nil { + fmt.Println(err) + } + }(tmp) + + content, err := io.ReadAll(tmp) + if err != nil { + return nil, err + } + + if err := yaml.Unmarshal(content, &existingOverrideFile); err != nil { + return nil, err + } + + for _, newParam := range overrideContent.Helm.Parameters { + found := false + for idx, existingParam := range existingOverrideFile.Helm.Parameters { + if existingParam.Name == newParam.Name { + // Update existing parameter + existingOverrideFile.Helm.Parameters[idx] = newParam + found = true + break + } + } + // If parameter with the same name doesn't exist, append it + if !found { + existingOverrideFile.Helm.Parameters = append(existingOverrideFile.Helm.Parameters, newParam) + } + } + + return &existingOverrideFile, nil +} + +func (repo *GitRepo) overrideFileExists(filename string) bool { + _, err := repo.fs.Stat(filename) + if err != nil { + return false + } + return true +} + +func (repo *GitRepo) commit(fileName, commitMsg string, overrideContent *ArgoOverrideFile) error { + create, err := repo.fs.Create(fileName) + if err != nil { + return err + } + + content, err := yaml.Marshal(overrideContent) + if err != nil { + return err + } + + _, err = create.Write(content) + if err := create.Close(); err != nil { + return err + } + + worktree, err := repo.localRepo.Worktree() + if err != nil { + return err + } + + _, err = worktree.Add(fileName) + if err != nil { + return err + } + + _, err = worktree.Commit(commitMsg, &git.CommitOptions{ + Author: &object.Signature{ + Name: "argo-watcher", + Email: "argo-watcher@linux-tech.io", + When: time.Now(), + }, + }) + + if err != nil { + return err + } + + err = repo.localRepo.Push(&git.PushOptions{ + Auth: repo.sshAuth, + RemoteName: "origin", + }) + + if err != nil { + return err + } + + return nil +} diff --git a/sonar-project.properties b/sonar-project.properties deleted file mode 100644 index c9478426..00000000 --- a/sonar-project.properties +++ /dev/null @@ -1,5 +0,0 @@ -sonar.organization=shini4i -sonar.projectKey=shini4i_argo-watcher -sonar.sources=. -sonar.exclusions=**/*_test.go, web/**, **/*.sql, cmd/mock/** -sonar.go.coverage.reportPaths=coverage.out From 2d52c58c9bc980703fe1c88dd513c677fb35467a Mon Sep 17 00:00:00 2001 From: Vadim Gedz Date: Fri, 25 Aug 2023 22:04:50 +0300 Subject: [PATCH 02/29] checkpoint --- internal/models/argo.go | 5 +++-- pkg/updater/updater.go | 17 +++++++++++++---- 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/internal/models/argo.go b/internal/models/argo.go index 4bb5e60f..a301129c 100644 --- a/internal/models/argo.go +++ b/internal/models/argo.go @@ -204,8 +204,9 @@ func (app *Application) processAppAnnotations(annotations map[string]string, tas if image.Image == appImage { if tagPath, exists := annotations[fmt.Sprintf("argo-watcher/%s.helm.image-tag", appAlias)]; exists { overrideFileContent.Helm.Parameters = append(overrideFileContent.Helm.Parameters, updater.ArgoParameterOverride{ - Name: tagPath, - Value: image.Tag, + Name: tagPath, + Value: image.Tag, + ForceString: true, }) } else { log.Error().Msgf("argo-watcher/%s.helm.image-tag annotation not found, skipping image %s update", appAlias, image.Image) diff --git a/pkg/updater/updater.go b/pkg/updater/updater.go index 37700066..fd4da6de 100644 --- a/pkg/updater/updater.go +++ b/pkg/updater/updater.go @@ -67,6 +67,9 @@ func (repo *GitRepo) UpdateApp(appName string, overrideContent *ArgoOverrideFile if err := repo.commit(overrideFileName, commitMsg, overrideContent); err != nil { return err } + + repo.close() + return nil } @@ -116,14 +119,13 @@ func (repo *GitRepo) mergeOverrideFileContent(overrideFileName string, overrideC return &existingOverrideFile, nil } +// overrideFileExists checks if the override file exists in the repository. func (repo *GitRepo) overrideFileExists(filename string) bool { _, err := repo.fs.Stat(filename) - if err != nil { - return false - } - return true + return err == nil } +// commit commits the override file to the repository. func (repo *GitRepo) commit(fileName, commitMsg string, overrideContent *ArgoOverrideFile) error { create, err := repo.fs.Create(fileName) if err != nil { @@ -173,3 +175,10 @@ func (repo *GitRepo) commit(fileName, commitMsg string, overrideContent *ArgoOve return nil } + +// close sets both the filesystem and the local repository to nil. +// This will allow the garbage collector to free the memory. +func (repo *GitRepo) close() { + repo.fs = nil + repo.localRepo = nil +} From 471a7bd924faba20c612b4da6f414de71e280f22 Mon Sep 17 00:00:00 2001 From: Vadim Gedz Date: Fri, 25 Aug 2023 22:18:53 +0300 Subject: [PATCH 03/29] checkpoint --- cmd/argo-watcher/argo_status_updater.go | 5 ++--- pkg/updater/updater.go | 26 +++++++++++++------------ 2 files changed, 16 insertions(+), 15 deletions(-) diff --git a/cmd/argo-watcher/argo_status_updater.go b/cmd/argo-watcher/argo_status_updater.go index c6a27101..792b22a2 100644 --- a/cmd/argo-watcher/argo_status_updater.go +++ b/cmd/argo-watcher/argo_status_updater.go @@ -130,8 +130,7 @@ func (updater *ArgoStatusUpdater) handleArgoAPIFailure(task models.Task, err err reason := fmt.Sprintf(ArgoAPIErrorTemplate, err.Error()) log.Warn().Str("id", task.Id).Msgf("Deployment failed with status \"%s\". Aborting with error: %s", apiFailureStatus, reason) - errStatusChange := updater.argo.state.SetTaskStatus(task.Id, apiFailureStatus, reason) - if errStatusChange != nil { - log.Error().Str("id", task.Id).Msgf(failedToUpdateTaskStatusTemplate, errStatusChange) + if err := updater.argo.state.SetTaskStatus(task.Id, apiFailureStatus, reason); err != nil { + log.Error().Str("id", task.Id).Msgf(failedToUpdateTaskStatusTemplate, err) } } diff --git a/pkg/updater/updater.go b/pkg/updater/updater.go index fd4da6de..941fe7ff 100644 --- a/pkg/updater/updater.go +++ b/pkg/updater/updater.go @@ -127,7 +127,7 @@ func (repo *GitRepo) overrideFileExists(filename string) bool { // commit commits the override file to the repository. func (repo *GitRepo) commit(fileName, commitMsg string, overrideContent *ArgoOverrideFile) error { - create, err := repo.fs.Create(fileName) + file, err := repo.fs.Create(fileName) if err != nil { return err } @@ -137,8 +137,11 @@ func (repo *GitRepo) commit(fileName, commitMsg string, overrideContent *ArgoOve return err } - _, err = create.Write(content) - if err := create.Close(); err != nil { + if _, err = file.Write(content); err != nil { + return err + } + + if err := file.Close(); err != nil { return err } @@ -147,29 +150,28 @@ func (repo *GitRepo) commit(fileName, commitMsg string, overrideContent *ArgoOve return err } - _, err = worktree.Add(fileName) - if err != nil { + if _, err = worktree.Add(fileName); err != nil { return err } - _, err = worktree.Commit(commitMsg, &git.CommitOptions{ + commitOpts := &git.CommitOptions{ Author: &object.Signature{ Name: "argo-watcher", - Email: "argo-watcher@linux-tech.io", + Email: "automation@linux-tech.io", When: time.Now(), }, - }) + } - if err != nil { + if _, err = worktree.Commit(commitMsg, commitOpts); err != nil { return err } - err = repo.localRepo.Push(&git.PushOptions{ + pushOpts := &git.PushOptions{ Auth: repo.sshAuth, RemoteName: "origin", - }) + } - if err != nil { + if err = repo.localRepo.Push(pushOpts); err != nil { return err } From 1a8495358eb8aa3f3dd3e9641287d5ad027e2673 Mon Sep 17 00:00:00 2001 From: Vadim Gedz Date: Fri, 25 Aug 2023 22:31:09 +0300 Subject: [PATCH 04/29] potential fix for tests --- cmd/argo-watcher/argo_status_updater_test.go | 4 ++-- pkg/updater/updater.go | 3 +-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/cmd/argo-watcher/argo_status_updater_test.go b/cmd/argo-watcher/argo_status_updater_test.go index b5324617..0541c70d 100644 --- a/cmd/argo-watcher/argo_status_updater_test.go +++ b/cmd/argo-watcher/argo_status_updater_test.go @@ -47,7 +47,7 @@ func TestArgoStatusUpdaterCheck(t *testing.T) { application.Status.Health.Status = "Healthy" // mock calls - apiMock.EXPECT().GetApplication(task.App).Return(&application, nil) + apiMock.EXPECT().GetApplication(task.App).Return(&application, nil).Times(2) metricsMock.EXPECT().ResetFailedDeployment(task.App) stateMock.EXPECT().SetTaskStatus(task.Id, models.StatusDeployedMessage, "") @@ -265,7 +265,7 @@ func TestArgoStatusUpdaterCheck(t *testing.T) { } // mock calls - apiMock.EXPECT().GetApplication(task.App).Return(nil, fmt.Errorf("Unexpected failure")) + apiMock.EXPECT().GetApplication(task.App).Return(nil, fmt.Errorf("unexpected failure")) metricsMock.EXPECT().AddFailedDeployment(task.App) stateMock.EXPECT().SetTaskStatus(task.Id, models.StatusFailedMessage, "ArgoCD API Error: Unexpected failure") diff --git a/pkg/updater/updater.go b/pkg/updater/updater.go index 941fe7ff..af1228d0 100644 --- a/pkg/updater/updater.go +++ b/pkg/updater/updater.go @@ -40,8 +40,7 @@ func (repo *GitRepo) Clone() error { repo.fs = memfs.New() - repo.sshAuth, err = ssh.NewPublicKeysFromFile("git", "/tmp/id_rsa", "") - if err != nil { + if repo.sshAuth, err = ssh.NewPublicKeysFromFile("git", "/tmp/id_rsa", ""); err != nil { return err } From 8fb96f02ec23012d2c2904abfc0c8c01bb2f56a4 Mon Sep 17 00:00:00 2001 From: Vadim Gedz Date: Fri, 25 Aug 2023 22:37:25 +0300 Subject: [PATCH 05/29] potential fix for tests pt2 --- cmd/argo-watcher/argo_status_updater_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/argo-watcher/argo_status_updater_test.go b/cmd/argo-watcher/argo_status_updater_test.go index 0541c70d..6bbf3f08 100644 --- a/cmd/argo-watcher/argo_status_updater_test.go +++ b/cmd/argo-watcher/argo_status_updater_test.go @@ -136,7 +136,7 @@ func TestArgoStatusUpdaterCheck(t *testing.T) { application.Status.Health.Status = "Healthy" // mock calls - apiMock.EXPECT().GetApplication(task.App).Return(&application, nil) + apiMock.EXPECT().GetApplication(task.App).Return(&application, nil).Times(2) metricsMock.EXPECT().ResetFailedDeployment(task.App) stateMock.EXPECT().SetTaskStatus(task.Id, models.StatusDeployedMessage, "") From 3da27ea55188694408a656c90949249c4d191a63 Mon Sep 17 00:00:00 2001 From: Vadim Gedz Date: Fri, 25 Aug 2023 23:56:19 +0300 Subject: [PATCH 06/29] potential fix for tests pt3 --- cmd/argo-watcher/argo_status_updater.go | 4 ++++ cmd/argo-watcher/argo_status_updater_test.go | 10 +++++----- internal/models/task.go | 4 ++-- 3 files changed, 11 insertions(+), 7 deletions(-) diff --git a/cmd/argo-watcher/argo_status_updater.go b/cmd/argo-watcher/argo_status_updater.go index 792b22a2..d6eefcdd 100644 --- a/cmd/argo-watcher/argo_status_updater.go +++ b/cmd/argo-watcher/argo_status_updater.go @@ -77,6 +77,10 @@ func (updater *ArgoStatusUpdater) waitForApplicationDeployment(task models.Task) var err error app, err := updater.argo.api.GetApplication(task.App) + if err != nil { + return nil, err + } + if app.IsManagedByWatcher() { log.Debug().Str("id", task.Id).Msg("Application is managed by watcher. Updating git repository.") app.UpdateGitImageTag(&task) diff --git a/cmd/argo-watcher/argo_status_updater_test.go b/cmd/argo-watcher/argo_status_updater_test.go index 6bbf3f08..aae69f53 100644 --- a/cmd/argo-watcher/argo_status_updater_test.go +++ b/cmd/argo-watcher/argo_status_updater_test.go @@ -177,7 +177,7 @@ func TestArgoStatusUpdaterCheck(t *testing.T) { application.Status.Health.Status = "Healthy" // mock calls - apiMock.EXPECT().GetApplication(task.App).Return(&application, nil) + apiMock.EXPECT().GetApplication(task.App).Return(&application, nil).Times(2) metricsMock.EXPECT().AddFailedDeployment(task.App) stateMock.EXPECT().SetTaskStatus(task.Id, models.StatusFailedMessage, "Application deployment failed. Rollout status \"not available\"\n\nList of current images (last app check):\n\ttest-registry/ghcr.io/shini4i/argo-watcher:dev\n\nList of expected images:\n\tghcr.io/shini4i/argo-watcher:dev") @@ -267,7 +267,7 @@ func TestArgoStatusUpdaterCheck(t *testing.T) { // mock calls apiMock.EXPECT().GetApplication(task.App).Return(nil, fmt.Errorf("unexpected failure")) metricsMock.EXPECT().AddFailedDeployment(task.App) - stateMock.EXPECT().SetTaskStatus(task.Id, models.StatusFailedMessage, "ArgoCD API Error: Unexpected failure") + stateMock.EXPECT().SetTaskStatus(task.Id, models.StatusFailedMessage, "ArgoCD API Error: unexpected failure") // run the rollout updater.WaitForRollout(task) @@ -304,7 +304,7 @@ func TestArgoStatusUpdaterCheck(t *testing.T) { application.Status.Summary.Images = []string{"test-image:v0.0.1"} // mock calls - apiMock.EXPECT().GetApplication(task.App).Return(&application, nil) + apiMock.EXPECT().GetApplication(task.App).Return(&application, nil).Times(2) metricsMock.EXPECT().AddFailedDeployment(task.App) stateMock.EXPECT().SetTaskStatus(task.Id, models.StatusFailedMessage, "Application deployment failed. Rollout status \"not available\"\n\nList of current images (last app check):\n\ttest-image:v0.0.1\n\nList of expected images:\n\tghcr.io/shini4i/argo-watcher:dev") @@ -348,7 +348,7 @@ func TestArgoStatusUpdaterCheck(t *testing.T) { application.Status.OperationState.Message = "Not working test app" // mock calls - apiMock.EXPECT().GetApplication(task.App).Return(&application, nil) + apiMock.EXPECT().GetApplication(task.App).Return(&application, nil).Times(2) metricsMock.EXPECT().AddFailedDeployment(task.App) stateMock.EXPECT().SetTaskStatus(task.Id, models.StatusFailedMessage, "Application deployment failed. Rollout status \"not synced\"\n\nApp status \"NotWorking\"\nApp message \"Not working test app\"\nResources:\n\t") @@ -390,7 +390,7 @@ func TestArgoStatusUpdaterCheck(t *testing.T) { application.Status.Health.Status = "NotHealthy" // mock calls - apiMock.EXPECT().GetApplication(task.App).Return(&application, nil) + apiMock.EXPECT().GetApplication(task.App).Return(&application, nil).Times(2) metricsMock.EXPECT().AddFailedDeployment(task.App) stateMock.EXPECT().SetTaskStatus(task.Id, models.StatusFailedMessage, "Application deployment failed. Rollout status \"not healthy\"\n\nApp sync status \"Synced\"\nApp health status \"NotHealthy\"\nResources:\n\t") diff --git a/internal/models/task.go b/internal/models/task.go index eed893b4..df8a4436 100644 --- a/internal/models/task.go +++ b/internal/models/task.go @@ -33,9 +33,9 @@ func (task *Task) ListImages() []string { return list } -// Check if app not found error. +// IsAppNotFoundError check if app not found error. func (task *Task) IsAppNotFoundError(err error) bool { - var appNotFoundError string = fmt.Sprintf("applications.argoproj.io \"%s\" not found", task.App) + var appNotFoundError = fmt.Sprintf("applications.argoproj.io \"%s\" not found", task.App) return strings.Contains(err.Error(), appNotFoundError) } From 228f4f4aa62c382919d30c718bfe0120fd508174 Mon Sep 17 00:00:00 2001 From: Vadim Gedz Date: Sat, 26 Aug 2023 00:33:04 +0300 Subject: [PATCH 07/29] skip empty commits --- pkg/updater/updater.go | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/pkg/updater/updater.go b/pkg/updater/updater.go index af1228d0..977a967e 100644 --- a/pkg/updater/updater.go +++ b/pkg/updater/updater.go @@ -9,6 +9,7 @@ import ( "github.com/go-git/go-git/v5/plumbing/object" "github.com/go-git/go-git/v5/plumbing/transport/ssh" "github.com/go-git/go-git/v5/storage/memory" + "github.com/rs/zerolog/log" "gopkg.in/yaml.v2" "io" "time" @@ -149,6 +150,18 @@ func (repo *GitRepo) commit(fileName, commitMsg string, overrideContent *ArgoOve return err } + // Check for changes in the working tree + status, err := worktree.Status() + if err != nil { + return err + } + + // If there are no changes, skip the commit + if status.IsClean() { + log.Debug().Msg("No changes detected. Skipping commit.") + return nil + } + if _, err = worktree.Add(fileName); err != nil { return err } From 1d89c75eeb7314611da311390c8a5031e064eba2 Mon Sep 17 00:00:00 2001 From: Vadim Gedz Date: Sat, 26 Aug 2023 01:02:14 +0300 Subject: [PATCH 08/29] add initial info to readme --- README.md | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/README.md b/README.md index 4f0192c0..29a06b0b 100644 --- a/README.md +++ b/README.md @@ -45,6 +45,31 @@ The workflow for deployment might be the following ## Documentation +> Starting with version v0.6.0, Argo Watcher now offers experimental support for making direct commits to the GitOps repository. + +
+Direct Git Integration +If you've been using Argo CD Image Updater across hundreds of applications, you might have noticed that the latency in detecting new images can sometimes slow down your deployments considerably. + +To address the challenges with deployment latency, we're excited to unveil an experimental feature in Argo Watcher that allows direct commits to your GitOps repository. + +We remain committed to supporting the straightforward scenario where users simply check the Application status. This ensures flexibility for those who prefer or need to use the original method. + +For those looking to experiment with faster image updates, you can leverage the new direct commit capability using the following annotations. + +```yaml + annotations: + argo-watcher/managed: "true" + argo-watcher/managed-images: "app=ghcr.io/shini4i/argo-watcher" + argo-watcher/app.helm.image-tag: "image.tag" +``` +This configuration will require mounting ssh key to the container. Support for this configuration is available in helm chart starting from verion `0.4.0`. + +⚠️ Important Note Regarding Direct Commit Feature: + +Please be aware that when using the direct commit feature, Argo Watcher does not verify the actual availability of the image. It assumes and trusts that the tag received from the client is correct. Ensure you have processes in place to validate image tags before relying on this feature. +
+ - Installation instructions and more information can be found in the [docs](docs/installation.md). - Development instructions can be found in the [docs](docs/development.md). - A short story about why this project was created can be found [here](https://medium.com/dyninno/a-journey-to-gitops-9aa445474eb6). From fa215f7b130e57d89f0b26c1594ee7aea6b0b4a9 Mon Sep 17 00:00:00 2001 From: Vadim Gedz Date: Sat, 26 Aug 2023 20:41:12 +0300 Subject: [PATCH 09/29] minor logic split --- pkg/updater/updater.go | 59 ++++++++++++++++++++++++++---------------- 1 file changed, 36 insertions(+), 23 deletions(-) diff --git a/pkg/updater/updater.go b/pkg/updater/updater.go index 977a967e..0186c266 100644 --- a/pkg/updater/updater.go +++ b/pkg/updater/updater.go @@ -100,21 +100,7 @@ func (repo *GitRepo) mergeOverrideFileContent(overrideFileName string, overrideC return nil, err } - for _, newParam := range overrideContent.Helm.Parameters { - found := false - for idx, existingParam := range existingOverrideFile.Helm.Parameters { - if existingParam.Name == newParam.Name { - // Update existing parameter - existingOverrideFile.Helm.Parameters[idx] = newParam - found = true - break - } - } - // If parameter with the same name doesn't exist, append it - if !found { - existingOverrideFile.Helm.Parameters = append(existingOverrideFile.Helm.Parameters, newParam) - } - } + mergeParameters(&existingOverrideFile, overrideContent) return &existingOverrideFile, nil } @@ -150,15 +136,9 @@ func (repo *GitRepo) commit(fileName, commitMsg string, overrideContent *ArgoOve return err } - // Check for changes in the working tree - status, err := worktree.Status() - if err != nil { + if changed, err := versionChanged(worktree); err != nil { return err - } - - // If there are no changes, skip the commit - if status.IsClean() { - log.Debug().Msg("No changes detected. Skipping commit.") + } else if !changed { return nil } @@ -196,3 +176,36 @@ func (repo *GitRepo) close() { repo.fs = nil repo.localRepo = nil } + +// versionChanged checks if the override file has changed. +func versionChanged(worktree *git.Worktree) (bool, error) { + status, err := worktree.Status() + if err != nil { + return false, err + } + + if status.IsClean() { + log.Debug().Msg("No changes detected. Skipping commit.") + return false, nil + } + return true, nil +} + +// mergeParameters merges the parameters from the new override file into the existing override file. +func mergeParameters(existing *ArgoOverrideFile, newContent *ArgoOverrideFile) { + for _, newParam := range newContent.Helm.Parameters { + found := false + for idx, existingParam := range existing.Helm.Parameters { + if existingParam.Name == newParam.Name { + // Update existing parameter + existing.Helm.Parameters[idx] = newParam + found = true + break + } + } + // If parameter with the same name doesn't exist, append it + if !found { + existing.Helm.Parameters = append(existing.Helm.Parameters, newParam) + } + } +} From c1e8c1c832f27b942e88695f9852e5d38019e84a Mon Sep 17 00:00:00 2001 From: Vadim Gedz Date: Sat, 26 Aug 2023 21:30:03 +0300 Subject: [PATCH 10/29] add a simple generated test --- pkg/updater/updater.go | 4 +- pkg/updater/updater_test.go | 133 ++++++++++++++++++++++++++++++++++++ 2 files changed, 135 insertions(+), 2 deletions(-) create mode 100644 pkg/updater/updater_test.go diff --git a/pkg/updater/updater.go b/pkg/updater/updater.go index 0186c266..2c62466d 100644 --- a/pkg/updater/updater.go +++ b/pkg/updater/updater.go @@ -148,8 +148,8 @@ func (repo *GitRepo) commit(fileName, commitMsg string, overrideContent *ArgoOve commitOpts := &git.CommitOptions{ Author: &object.Signature{ - Name: "argo-watcher", - Email: "automation@linux-tech.io", + Name: "github-actions[bot]", + Email: "github-actions[bot]@users.noreply.github.com", When: time.Now(), }, } diff --git a/pkg/updater/updater_test.go b/pkg/updater/updater_test.go new file mode 100644 index 00000000..361b066c --- /dev/null +++ b/pkg/updater/updater_test.go @@ -0,0 +1,133 @@ +package updater + +import ( + "github.com/stretchr/testify/assert" + "testing" +) + +func TestMergeParameters(t *testing.T) { + tests := []struct { + name string + existing ArgoOverrideFile + new ArgoOverrideFile + expected ArgoOverrideFile + }{ + { + name: "Merge with empty existing", + existing: ArgoOverrideFile{}, + new: ArgoOverrideFile{ + Helm: struct { + Parameters []ArgoParameterOverride `yaml:"parameters"` + }{ + Parameters: []ArgoParameterOverride{ + { + Name: "param1", + Value: "value1", + }, + }, + }, + }, + expected: ArgoOverrideFile{ + Helm: struct { + Parameters []ArgoParameterOverride `yaml:"parameters"` + }{ + Parameters: []ArgoParameterOverride{ + { + Name: "param1", + Value: "value1", + }, + }, + }, + }, + }, + { + name: "Overwrite parameter from newContent", + existing: ArgoOverrideFile{ + Helm: struct { + Parameters []ArgoParameterOverride `yaml:"parameters"` + }{ + Parameters: []ArgoParameterOverride{ + { + Name: "param1", + Value: "oldValue", + }, + }, + }, + }, + new: ArgoOverrideFile{ + Helm: struct { + Parameters []ArgoParameterOverride `yaml:"parameters"` + }{ + Parameters: []ArgoParameterOverride{ + { + Name: "param1", + Value: "newValue", + }, + }, + }, + }, + expected: ArgoOverrideFile{ + Helm: struct { + Parameters []ArgoParameterOverride `yaml:"parameters"` + }{ + Parameters: []ArgoParameterOverride{ + { + Name: "param1", + Value: "newValue", + }, + }, + }, + }, + }, + { + name: "Append parameter from newContent", + existing: ArgoOverrideFile{ + Helm: struct { + Parameters []ArgoParameterOverride `yaml:"parameters"` + }{ + Parameters: []ArgoParameterOverride{ + { + Name: "param1", + Value: "value1", + }, + }, + }, + }, + new: ArgoOverrideFile{ + Helm: struct { + Parameters []ArgoParameterOverride `yaml:"parameters"` + }{ + Parameters: []ArgoParameterOverride{ + { + Name: "param2", + Value: "value2", + }, + }, + }, + }, + expected: ArgoOverrideFile{ + Helm: struct { + Parameters []ArgoParameterOverride `yaml:"parameters"` + }{ + Parameters: []ArgoParameterOverride{ + { + Name: "param1", + Value: "value1", + }, + { + Name: "param2", + Value: "value2", + }, + }, + }, + }, + }, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + mergeParameters(&test.existing, &test.new) + assert.Equal(t, test.expected, test.existing) + }) + } +} From 7e126930e0de0b567698aa072f5a9f4eabac4983 Mon Sep 17 00:00:00 2001 From: Vadim Gedz Date: Sun, 27 Aug 2023 14:10:35 +0300 Subject: [PATCH 11/29] chore: add more tests --- internal/models/argo_test.go | 109 +++++++++++++++++++++++++++++++++++ 1 file changed, 109 insertions(+) diff --git a/internal/models/argo_test.go b/internal/models/argo_test.go index 943af66d..d6f73dc9 100644 --- a/internal/models/argo_test.go +++ b/internal/models/argo_test.go @@ -205,3 +205,112 @@ func TestApplication_IsFinalRollout(t *testing.T) { assert.Equal(t, false, application.IsFinalRolloutStatus(ArgoRolloutAppNotHealthy)) assert.Equal(t, false, application.IsFinalRolloutStatus(ArgoRolloutAppNotSynced)) } + +func TestIsManagedByWatcher(t *testing.T) { + tests := []struct { + name string + application Application + expected bool + }{ + { + name: "No annotations", + application: Application{ + Metadata: struct { + Name string `json:"name"` + Annotations map[string]string `json:"annotations"` + }{}, + }, + expected: false, + }, + { + name: "Managed by Watcher", + application: Application{ + Metadata: struct { + Name string `json:"name"` + Annotations map[string]string `json:"annotations"` + }{ + Annotations: map[string]string{ + "argo-watcher/managed": "true", + }, + }, + }, + expected: true, + }, + { + name: "Not managed by Watcher", + application: Application{ + Metadata: struct { + Name string `json:"name"` + Annotations map[string]string `json:"annotations"` + }{ + Annotations: map[string]string{ + "argo-watcher/managed": "false", + }, + }, + }, + expected: false, + }, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + assert.Equal(t, test.expected, test.application.IsManagedByWatcher()) + }) + } +} + +func TestExtractManagedImages(t *testing.T) { + tests := []struct { + name string + annotation map[string]string + expected map[string]string + }{ + { + name: "Extracts multiple managed images", + annotation: map[string]string{ + "argo-watcher/managed-images": "alias1=image1,alias2=image2", + }, + expected: map[string]string{ + "alias1": "image1", + "alias2": "image2", + }, + }, + { + name: "Extracts single managed image", + annotation: map[string]string{ + "argo-watcher/managed-images": "alias1=image1", + }, + expected: map[string]string{ + "alias1": "image1", + }, + }, + { + name: "No managed images", + annotation: map[string]string{}, + expected: map[string]string{}, + }, + { + name: "Non-related annotations", + annotation: map[string]string{ + "another-annotation": "alias1=image1", + }, + expected: map[string]string{}, + }, + { + name: "Mixed annotations", + annotation: map[string]string{ + "argo-watcher/managed-images": "alias1=image1", + "another-annotation": "somethingelse", + }, + expected: map[string]string{ + "alias1": "image1", + }, + }, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + assert.Equal(t, test.expected, extractManagedImages(test.annotation)) + }) + } +} From 6df22bece828072eb6524b5b68905399b525e59a Mon Sep 17 00:00:00 2001 From: Vadim Gedz Date: Sun, 27 Aug 2023 15:40:07 +0300 Subject: [PATCH 12/29] replace hardcoded values with const --- cmd/argo-watcher/state/postgres_state.go | 2 +- internal/models/argo.go | 16 +++++++++++----- internal/models/argo_test.go | 12 ++++++------ 3 files changed, 18 insertions(+), 12 deletions(-) diff --git a/cmd/argo-watcher/state/postgres_state.go b/cmd/argo-watcher/state/postgres_state.go index b879f38a..55b3e76e 100644 --- a/cmd/argo-watcher/state/postgres_state.go +++ b/cmd/argo-watcher/state/postgres_state.go @@ -242,7 +242,7 @@ func (state *PostgresState) doProcessPostgresObsoleteTasks() error { var result *gorm.DB - log.Debug().Msg("Marking app not found tasks older than 1 hour as aborted...") + log.Debug().Msg("Removing app not found tasks older than 1 hour from the database...") result = state.orm.Where("status = ?", models.StatusAppNotFoundMessage).Where("created < now() - interval '1 hour'").Delete(&state_models.TaskModel{}) if result.Error != nil { return result.Error diff --git a/internal/models/argo.go b/internal/models/argo.go index a301129c..4cb38fe6 100644 --- a/internal/models/argo.go +++ b/internal/models/argo.go @@ -16,6 +16,12 @@ const ( ArgoRolloutAppNotHealthy = "not healthy" ) +const ( + managedAnnotation = "argo-watcher/managed" + managedImagesAnnotation = "argo-watcher/managed-images" + managedImageTagPattern = "argo-watcher/%s.helm.image-tag" +) + type ApplicationOperationResource struct { HookPhase string `json:"hookPhase"` // example: Failed HookType string `json:"hookType"` // example: PreSync @@ -187,7 +193,7 @@ func (app *Application) IsManagedByWatcher() bool { if app.Metadata.Annotations == nil { return false } - return app.Metadata.Annotations["argo-watcher/managed"] == "true" + return app.Metadata.Annotations[managedAnnotation] == "true" } func (app *Application) processAppAnnotations(annotations map[string]string, task *Task) *updater.ArgoOverrideFile { @@ -195,21 +201,21 @@ func (app *Application) processAppAnnotations(annotations map[string]string, tas managedImages := extractManagedImages(annotations) if len(managedImages) == 0 { - log.Error().Msgf("argo-watcher/managed-images annotation not found, skipping image update") + log.Error().Msgf("%s annotation not found, skipping image update", managedImagesAnnotation) return nil } for _, image := range task.Images { for appAlias, appImage := range managedImages { if image.Image == appImage { - if tagPath, exists := annotations[fmt.Sprintf("argo-watcher/%s.helm.image-tag", appAlias)]; exists { + if tagPath, exists := annotations[fmt.Sprintf(managedImageTagPattern, appAlias)]; exists { overrideFileContent.Helm.Parameters = append(overrideFileContent.Helm.Parameters, updater.ArgoParameterOverride{ Name: tagPath, Value: image.Tag, ForceString: true, }) } else { - log.Error().Msgf("argo-watcher/%s.helm.image-tag annotation not found, skipping image %s update", appAlias, image.Image) + log.Error().Msgf("%s annotation not found, skipping image %s update", fmt.Sprintf(managedImageTagPattern, appAlias), image.Image) } } } @@ -248,7 +254,7 @@ func extractManagedImages(annotations map[string]string) map[string]string { managedImages := map[string]string{} for annotation, value := range annotations { - if annotation == "argo-watcher/managed-images" { + if annotation == managedImagesAnnotation { for _, image := range strings.Split(value, ",") { managedImages[strings.Split(image, "=")[0]] = strings.Split(image, "=")[1] } diff --git a/internal/models/argo_test.go b/internal/models/argo_test.go index d6f73dc9..6950a93f 100644 --- a/internal/models/argo_test.go +++ b/internal/models/argo_test.go @@ -230,7 +230,7 @@ func TestIsManagedByWatcher(t *testing.T) { Annotations map[string]string `json:"annotations"` }{ Annotations: map[string]string{ - "argo-watcher/managed": "true", + managedAnnotation: "true", }, }, }, @@ -244,7 +244,7 @@ func TestIsManagedByWatcher(t *testing.T) { Annotations map[string]string `json:"annotations"` }{ Annotations: map[string]string{ - "argo-watcher/managed": "false", + managedAnnotation: "false", }, }, }, @@ -268,7 +268,7 @@ func TestExtractManagedImages(t *testing.T) { { name: "Extracts multiple managed images", annotation: map[string]string{ - "argo-watcher/managed-images": "alias1=image1,alias2=image2", + managedImagesAnnotation: "alias1=image1,alias2=image2", }, expected: map[string]string{ "alias1": "image1", @@ -278,7 +278,7 @@ func TestExtractManagedImages(t *testing.T) { { name: "Extracts single managed image", annotation: map[string]string{ - "argo-watcher/managed-images": "alias1=image1", + managedImagesAnnotation: "alias1=image1", }, expected: map[string]string{ "alias1": "image1", @@ -299,8 +299,8 @@ func TestExtractManagedImages(t *testing.T) { { name: "Mixed annotations", annotation: map[string]string{ - "argo-watcher/managed-images": "alias1=image1", - "another-annotation": "somethingelse", + managedImagesAnnotation: "alias1=image1", + "another-annotation": "somethingelse", }, expected: map[string]string{ "alias1": "image1", From 6b359bd946949c5540eb2f974eaef1c2cd64ee84 Mon Sep 17 00:00:00 2001 From: Vadim Gedz Date: Sun, 27 Aug 2023 19:45:46 +0300 Subject: [PATCH 13/29] cleanup + env for updater --- cmd/argo-watcher/config/config.go | 2 +- cmd/argo-watcher/server.go | 2 +- cmd/argo-watcher/state/postgres_state.go | 2 +- internal/models/argo.go | 7 ++++++- pkg/updater/updater.go | 9 ++++++++- 5 files changed, 17 insertions(+), 5 deletions(-) diff --git a/cmd/argo-watcher/config/config.go b/cmd/argo-watcher/config/config.go index e9d984f0..b3934f1d 100644 --- a/cmd/argo-watcher/config/config.go +++ b/cmd/argo-watcher/config/config.go @@ -10,7 +10,7 @@ import ( ) const ( - LOG_FORMAT_TEXT = "text" + LogFormatText = "text" ) type ServerConfig struct { diff --git a/cmd/argo-watcher/server.go b/cmd/argo-watcher/server.go index a59d5367..7d70579e 100644 --- a/cmd/argo-watcher/server.go +++ b/cmd/argo-watcher/server.go @@ -15,7 +15,7 @@ import ( // If the log level string is invalid, it falls back to the default InfoLevel. func initLogs(logLevel string, logFormat string) { // set log format - if logFormat == config.LOG_FORMAT_TEXT { + if logFormat == config.LogFormatText { output := zerolog.ConsoleWriter{Out: os.Stdout, TimeFormat: time.RFC3339} log.Logger = zerolog.New(output).With().Timestamp().Logger() } diff --git a/cmd/argo-watcher/state/postgres_state.go b/cmd/argo-watcher/state/postgres_state.go index 55b3e76e..8927b39a 100644 --- a/cmd/argo-watcher/state/postgres_state.go +++ b/cmd/argo-watcher/state/postgres_state.go @@ -36,7 +36,7 @@ func (state *PostgresState) Connect(serverConfig *config.ServerConfig) error { // create connection ormConfig := &gorm.Config{} // we can leave logger enabled only for text format - if serverConfig.LogFormat != config.LOG_FORMAT_TEXT { + if serverConfig.LogFormat != config.LogFormatText { // disable logging until we implement zerolog logger for ORM ormConfig.Logger = logger.Default.LogMode(logger.Silent) } else { diff --git a/internal/models/argo.go b/internal/models/argo.go index 4cb38fe6..4cb4bd9a 100644 --- a/internal/models/argo.go +++ b/internal/models/argo.go @@ -236,7 +236,12 @@ func (app *Application) UpdateGitImageTag(task *Task) { return } - git := updater.GitRepo{RepoURL: app.Spec.Source.RepoURL, BranchName: app.Spec.Source.TargetRevision, Path: app.Spec.Source.Path} + git := updater.GitRepo{ + RepoURL: app.Spec.Source.RepoURL, + BranchName: app.Spec.Source.TargetRevision, + Path: app.Spec.Source.Path, + } + if err := git.Clone(); err != nil { log.Error().Str("id", task.Id).Msgf("Failed to clone git repository %s", app.Spec.Source.RepoURL) return diff --git a/pkg/updater/updater.go b/pkg/updater/updater.go index 2c62466d..adc848a7 100644 --- a/pkg/updater/updater.go +++ b/pkg/updater/updater.go @@ -12,9 +12,16 @@ import ( "github.com/rs/zerolog/log" "gopkg.in/yaml.v2" "io" + "os" "time" ) +var ( + sshKeyPath = os.Getenv("SSH_KEY_PATH") + sshKeyPass = os.Getenv("SSH_KEY_PASS") + sshKnownHosts = os.Getenv("SSH_KNOWN_HOSTS") +) + type ArgoOverrideFile struct { Helm struct { Parameters []ArgoParameterOverride `yaml:"parameters"` @@ -41,7 +48,7 @@ func (repo *GitRepo) Clone() error { repo.fs = memfs.New() - if repo.sshAuth, err = ssh.NewPublicKeysFromFile("git", "/tmp/id_rsa", ""); err != nil { + if repo.sshAuth, err = ssh.NewPublicKeysFromFile("git", sshKeyPath, sshKeyPass); err != nil { return err } From 1dfed33729dbb7c24481aa8a9da1283eea0c210d Mon Sep 17 00:00:00 2001 From: Vadim Gedz Date: Sun, 27 Aug 2023 20:33:15 +0300 Subject: [PATCH 14/29] replace missed hardcoded values --- pkg/updater/updater.go | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/pkg/updater/updater.go b/pkg/updater/updater.go index adc848a7..29ae9465 100644 --- a/pkg/updater/updater.go +++ b/pkg/updater/updater.go @@ -19,7 +19,8 @@ import ( var ( sshKeyPath = os.Getenv("SSH_KEY_PATH") sshKeyPass = os.Getenv("SSH_KEY_PASS") - sshKnownHosts = os.Getenv("SSH_KNOWN_HOSTS") + sshCommitUser = os.Getenv("SSH_COMMIT_USER") + sshCommitMail = os.Getenv("SSH_COMMIT_MAIL") ) type ArgoOverrideFile struct { @@ -155,8 +156,8 @@ func (repo *GitRepo) commit(fileName, commitMsg string, overrideContent *ArgoOve commitOpts := &git.CommitOptions{ Author: &object.Signature{ - Name: "github-actions[bot]", - Email: "github-actions[bot]@users.noreply.github.com", + Name: sshCommitUser, + Email: sshCommitMail, When: time.Now(), }, } From 755677fef1d7b11e2e4560ebd473a728f8a9b857 Mon Sep 17 00:00:00 2001 From: Vadims Gedzs Date: Mon, 28 Aug 2023 12:17:48 +0300 Subject: [PATCH 15/29] add more tests --- pkg/updater/updater_test.go | 68 +++++++++++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) diff --git a/pkg/updater/updater_test.go b/pkg/updater/updater_test.go index 361b066c..377efb1a 100644 --- a/pkg/updater/updater_test.go +++ b/pkg/updater/updater_test.go @@ -1,6 +1,9 @@ package updater import ( + "github.com/go-git/go-billy/v5" + "github.com/go-git/go-billy/v5/memfs" + "github.com/go-git/go-git/v5" "github.com/stretchr/testify/assert" "testing" ) @@ -131,3 +134,68 @@ func TestMergeParameters(t *testing.T) { }) } } + +func TestOverrideFileExists(t *testing.T) { + tests := []struct { + name string + setupFs func(fs billy.Filesystem) + filename string + expected bool + }{ + { + name: "File exists", + setupFs: func(fs billy.Filesystem) { + if _, err := fs.Create("/path/to/existing/file.yaml"); err != nil { + t.Error(err) + } + }, + filename: "/path/to/existing/file.yaml", + expected: true, + }, + { + name: "File does not exist", + setupFs: func(fs billy.Filesystem) {}, + filename: "/path/to/nonexistent/file.yaml", + expected: false, + }, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + // Setup mock filesystem + mockFs := memfs.New() + test.setupFs(mockFs) + + // Initialize GitRepo with mock filesystem + repo := &GitRepo{ + fs: mockFs, + } + + got := repo.overrideFileExists(test.filename) + assert.Equal(t, test.expected, got) + }) + } +} + +func TestGitRepo_Close(t *testing.T) { + mockFs := memfs.New() + + // Mock a local repo. In a real-world scenario, this would be a valid git.Repository + mockLocalRepo := &git.Repository{} + + // Initialize an example GitRepo + repo := &GitRepo{ + fs: mockFs, + localRepo: mockLocalRepo, + } + + // Check if the fs and localRepo fields are initialized + assert.NotNil(t, repo.fs) + assert.NotNil(t, repo.localRepo) + + repo.close() + + // Check if the fs and localRepo fields are nil after calling close + assert.Nil(t, repo.fs) + assert.Nil(t, repo.localRepo) +} From dccf17db9e33f90ddf2304f0a13b0e7161ef5d3c Mon Sep 17 00:00:00 2001 From: Vadims Gedzs Date: Mon, 28 Aug 2023 17:16:15 +0300 Subject: [PATCH 16/29] add trivial task validation --- cmd/argo-watcher/argo_status_updater.go | 6 ++--- cmd/argo-watcher/config/config.go | 1 + cmd/argo-watcher/router.go | 8 +++++++ internal/models/task.go | 20 +++++++++-------- pkg/client/client.go | 12 ++++++---- pkg/updater/updater.go | 29 +++++++++++++++---------- 6 files changed, 48 insertions(+), 28 deletions(-) diff --git a/cmd/argo-watcher/argo_status_updater.go b/cmd/argo-watcher/argo_status_updater.go index d6eefcdd..f20bc927 100644 --- a/cmd/argo-watcher/argo_status_updater.go +++ b/cmd/argo-watcher/argo_status_updater.go @@ -81,11 +81,11 @@ func (updater *ArgoStatusUpdater) waitForApplicationDeployment(task models.Task) return nil, err } - if app.IsManagedByWatcher() { - log.Debug().Str("id", task.Id).Msg("Application is managed by watcher. Updating git repository.") + if app.IsManagedByWatcher() && task.Validated { + log.Debug().Str("id", task.Id).Msg("Application managed by watcher. Initiating git repo update.") app.UpdateGitImageTag(&task) } else { - log.Debug().Str("id", task.Id).Msg("Application is not managed by watcher. Skipping git repository update.") + log.Debug().Str("id", task.Id).Msg("Skipping git repo update: Application not managed by watcher or token is absent/invalid.") } // wait for application to get into deployed status or timeout diff --git a/cmd/argo-watcher/config/config.go b/cmd/argo-watcher/config/config.go index b3934f1d..169c97ec 100644 --- a/cmd/argo-watcher/config/config.go +++ b/cmd/argo-watcher/config/config.go @@ -33,6 +33,7 @@ type ServerConfig struct { DbUser string `required:"false" envconfig:"DB_USER"` DbPassword string `required:"false" envconfig:"DB_PASSWORD"` DbMigrationsPath string `required:"false" envconfig:"DB_MIGRATIONS_PATH" default:"db/migrations"` // deprecated + DeployToken string `required:"false" envoconfig:"ARGO_WATCHER_DEPLOY_TOKEN"` } // NewServerConfig parses the server configuration from environment variables using the envconfig package. diff --git a/cmd/argo-watcher/router.go b/cmd/argo-watcher/router.go index 2b0a0fa4..567f61d1 100644 --- a/cmd/argo-watcher/router.go +++ b/cmd/argo-watcher/router.go @@ -111,6 +111,14 @@ func (env *Env) addTask(c *gin.Context) { return } + // not an optimal solution, but for PoC it's fine + // need to find a better way to pass the token later + if c.GetHeader("ARGO_DEPLOY_TOKEN") == env.config.DeployToken { + log.Debug().Msgf("Deploy token is valid for task %s", task.Id) + task.Validated = true + } + log.Debug().Msgf("Deploy token is missing or invalid for task %s", task.Id) + newTask, err := env.argo.AddTask(task) if err != nil { log.Error().Msgf("Couldn't process new task. Got the following error: %s", err) diff --git a/internal/models/task.go b/internal/models/task.go index df8a4436..2b3728b5 100644 --- a/internal/models/task.go +++ b/internal/models/task.go @@ -11,15 +11,17 @@ type Image struct { } type Task struct { - Id string `json:"id,omitempty"` - Created float64 `json:"created,omitempty"` - Updated float64 `json:"updated,omitempty"` - App string `json:"app" binding:"required" example:"argo-watcher"` - Author string `json:"author" binding:"required" example:"John Doe"` - Project string `json:"project" binding:"required" example:"Demo"` - Images []Image `json:"images" binding:"required"` - Status string `json:"status,omitempty"` - StatusReason string `json:"status_reason,omitempty"` + Id string `json:"id,omitempty"` + Created float64 `json:"created,omitempty"` + Updated float64 `json:"updated,omitempty"` + App string `json:"app" binding:"required" example:"argo-watcher"` + Author string `json:"author" binding:"required" example:"John Doe"` + Project string `json:"project" binding:"required" example:"Demo"` + Images []Image `json:"images" binding:"required"` + Status string `json:"status,omitempty"` + StatusReason string `json:"status_reason,omitempty"` + ProvidedToken string `json:"token,omitempty"` + Validated bool } // ListImages returns a list of strings representing the images of the task. diff --git a/pkg/client/client.go b/pkg/client/client.go index 62d4aa5e..6c9e35f9 100644 --- a/pkg/client/client.go +++ b/pkg/client/client.go @@ -127,10 +127,11 @@ func ClientWatcher() { } task := models.Task{ - App: os.Getenv("ARGO_APP"), - Author: os.Getenv("COMMIT_AUTHOR"), - Project: os.Getenv("PROJECT_NAME"), - Images: images, + App: os.Getenv("ARGO_APP"), + Author: os.Getenv("COMMIT_AUTHOR"), + Project: os.Getenv("PROJECT_NAME"), + ProvidedToken: os.Getenv("ARGO_WATCHER_TOKEN"), + Images: images, } debug, _ := strconv.ParseBool(os.Getenv("DEBUG")) @@ -144,6 +145,9 @@ func ClientWatcher() { "IMAGE_TAG: %s\n"+ "IMAGES: %s\n\n", watcher.baseUrl, task.App, task.Author, task.Project, tag, task.Images) + if task.ProvidedToken == "" { + fmt.Println("ARGO_WATCHER_TOKEN is not set, git commit will not be performed.") + } } fmt.Printf("Waiting for %s app to be running on %s version.\n", task.App, tag) diff --git a/pkg/updater/updater.go b/pkg/updater/updater.go index 29ae9465..1f3c3091 100644 --- a/pkg/updater/updater.go +++ b/pkg/updater/updater.go @@ -87,19 +87,8 @@ func (repo *GitRepo) mergeOverrideFileContent(overrideFileName string, overrideC } existingOverrideFile := ArgoOverrideFile{} - tmp, err := repo.fs.Open(overrideFileName) - if err != nil { - return nil, err - } - - defer func(tmp billy.File) { - err := tmp.Close() - if err != nil { - fmt.Println(err) - } - }(tmp) - content, err := io.ReadAll(tmp) + content, err := repo.getFileContent(overrideFileName) if err != nil { return nil, err } @@ -113,6 +102,22 @@ func (repo *GitRepo) mergeOverrideFileContent(overrideFileName string, overrideC return &existingOverrideFile, nil } +func (repo *GitRepo) getFileContent(filename string) ([]byte, error) { + tmp, err := repo.fs.Open(filename) + if err != nil { + return nil, err + } + + defer func(tmp billy.File) { + err := tmp.Close() + if err != nil { + fmt.Println(err) + } + }(tmp) + + return io.ReadAll(tmp) +} + // overrideFileExists checks if the override file exists in the repository. func (repo *GitRepo) overrideFileExists(filename string) bool { _, err := repo.fs.Stat(filename) From 61fe28474ff0cf9fc0079f004fb06a9470ba86f3 Mon Sep 17 00:00:00 2001 From: Vadim Gedz Date: Mon, 28 Aug 2023 21:12:56 +0300 Subject: [PATCH 17/29] fix(config): typo --- cmd/argo-watcher/config/config.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/argo-watcher/config/config.go b/cmd/argo-watcher/config/config.go index 169c97ec..f81c53b2 100644 --- a/cmd/argo-watcher/config/config.go +++ b/cmd/argo-watcher/config/config.go @@ -33,7 +33,7 @@ type ServerConfig struct { DbUser string `required:"false" envconfig:"DB_USER"` DbPassword string `required:"false" envconfig:"DB_PASSWORD"` DbMigrationsPath string `required:"false" envconfig:"DB_MIGRATIONS_PATH" default:"db/migrations"` // deprecated - DeployToken string `required:"false" envoconfig:"ARGO_WATCHER_DEPLOY_TOKEN"` + DeployToken string `required:"false" envconfig:"ARGO_WATCHER_DEPLOY_TOKEN"` } // NewServerConfig parses the server configuration from environment variables using the envconfig package. From 6cc674e1f79cdcc0e48acf5e102bb40cec9917e9 Mon Sep 17 00:00:00 2001 From: Vadim Gedz Date: Mon, 28 Aug 2023 22:32:31 +0300 Subject: [PATCH 18/29] add a simple mutex --- cmd/argo-watcher/argo_status_updater.go | 4 ++++ cmd/argo-watcher/router.go | 4 ++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/cmd/argo-watcher/argo_status_updater.go b/cmd/argo-watcher/argo_status_updater.go index f20bc927..d34762fd 100644 --- a/cmd/argo-watcher/argo_status_updater.go +++ b/cmd/argo-watcher/argo_status_updater.go @@ -4,6 +4,7 @@ import ( "errors" "fmt" "strings" + "sync" "time" "github.com/avast/retry-go/v4" @@ -17,6 +18,7 @@ type ArgoStatusUpdater struct { argo Argo registryProxyUrl string retryOptions []retry.Option + sync.Mutex } func (updater *ArgoStatusUpdater) Init(argo Argo, retryAttempts uint, retryDelay time.Duration, registryProxyUrl string) { @@ -82,6 +84,8 @@ func (updater *ArgoStatusUpdater) waitForApplicationDeployment(task models.Task) } if app.IsManagedByWatcher() && task.Validated { + updater.Lock() + defer updater.Unlock() log.Debug().Str("id", task.Id).Msg("Application managed by watcher. Initiating git repo update.") app.UpdateGitImageTag(&task) } else { diff --git a/cmd/argo-watcher/router.go b/cmd/argo-watcher/router.go index 567f61d1..b73264d3 100644 --- a/cmd/argo-watcher/router.go +++ b/cmd/argo-watcher/router.go @@ -114,10 +114,10 @@ func (env *Env) addTask(c *gin.Context) { // not an optimal solution, but for PoC it's fine // need to find a better way to pass the token later if c.GetHeader("ARGO_DEPLOY_TOKEN") == env.config.DeployToken { - log.Debug().Msgf("Deploy token is valid for task %s", task.Id) + log.Debug().Msgf("deploy token is validated for app %s", task.App) task.Validated = true } - log.Debug().Msgf("Deploy token is missing or invalid for task %s", task.Id) + log.Debug().Msgf("deploy token for app %s failed validation", task.App) newTask, err := env.argo.AddTask(task) if err != nil { From 5af839b4d8e22e1f94d9db74d041057c5c46c580 Mon Sep 17 00:00:00 2001 From: Vadim Gedz Date: Tue, 29 Aug 2023 10:52:36 +0300 Subject: [PATCH 19/29] reject tasks with invalid token --- cmd/argo-watcher/router.go | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/cmd/argo-watcher/router.go b/cmd/argo-watcher/router.go index b73264d3..bd46be9a 100644 --- a/cmd/argo-watcher/router.go +++ b/cmd/argo-watcher/router.go @@ -113,11 +113,19 @@ func (env *Env) addTask(c *gin.Context) { // not an optimal solution, but for PoC it's fine // need to find a better way to pass the token later - if c.GetHeader("ARGO_DEPLOY_TOKEN") == env.config.DeployToken { + deployToken := c.GetHeader("ARGO_DEPLOY_TOKEN") + + if deployToken != "" && deployToken == env.config.DeployToken { log.Debug().Msgf("deploy token is validated for app %s", task.App) task.Validated = true + } else if deployToken != "" && deployToken != env.config.DeployToken { + // if token is provided, but it's not valid we should not process the task + log.Debug().Msgf("deploy token is invalid for app %s, aborting", task.App) + c.JSON(http.StatusUnauthorized, models.TaskStatus{}) + return + } else { + log.Debug().Msgf("deploy token is not provided for app %s", task.App) } - log.Debug().Msgf("deploy token for app %s failed validation", task.App) newTask, err := env.argo.AddTask(task) if err != nil { From 1177a3f38248d1cef4e28a5d6afff8cfaf3d085e Mon Sep 17 00:00:00 2001 From: Vadim Gedz Date: Tue, 29 Aug 2023 11:33:20 +0300 Subject: [PATCH 20/29] update docs + make client and server use the same variable name --- cmd/argo-watcher/router.go | 2 +- docs/installation.md | 80 +++++++++++++++++++++----------------- pkg/client/client.go | 4 +- 3 files changed, 48 insertions(+), 38 deletions(-) diff --git a/cmd/argo-watcher/router.go b/cmd/argo-watcher/router.go index bd46be9a..2aa7d99b 100644 --- a/cmd/argo-watcher/router.go +++ b/cmd/argo-watcher/router.go @@ -120,7 +120,7 @@ func (env *Env) addTask(c *gin.Context) { task.Validated = true } else if deployToken != "" && deployToken != env.config.DeployToken { // if token is provided, but it's not valid we should not process the task - log.Debug().Msgf("deploy token is invalid for app %s, aborting", task.App) + log.Warn().Msgf("deploy token is invalid for app %s, aborting", task.App) c.JSON(http.StatusUnauthorized, models.TaskStatus{}) return } else { diff --git a/docs/installation.md b/docs/installation.md index 0c4199a8..08a36c2d 100644 --- a/docs/installation.md +++ b/docs/installation.md @@ -15,8 +15,12 @@ argo: # p, role:watcher, applications, get, */*, allow # p, role:watcher, applications, sync, */*, allow # g, watcher, role:watcher - # secret with ARGO_TOKEN key + # secret with ARGO_TOKEN key and optional ARGO_WATCHER_DEPLOY_TOKEN (should match ARGO_WATCHER_DEPLOY_TOKEN on client side) secretName: "argo-watcher" + # the following values are required only if you want to use Argo Watcher to manage deployments + updater: + # A secret containing ssh key that would be used to interact with git repositories + sshSecretName: "ssh-secret" # credentials to access postgresql and store deployment monitoring tasks # can be omitted if persistence is not required (state will be stored in memory) @@ -43,35 +47,40 @@ ingress: Argo Watcher Server supports the following environment variables -| Variable | Description | Default | Mandatory | -|---------------------|-----------------------------------------------------------------------------|-----------|---------------| -| ARGO_URL | ArgoCD URL | | Yes | -| ARGO_TOKEN | ArgoCD API token | | Yes | -| ARGO_API_TIMEOUT | Timeout for ArgoCD API calls. Defaults to 60 seconds | 60 | No | -| ARGO_TIMEOUT | Time that Argo Watcher is allowed to wait for deployment. | 0 | No | -| ARGO_REFRESH_APP | Refresh application during status check | true | No | -| DOCKER_IMAGES_PROXY | Define registry proxy url for image checks | | No | -| STATE_TYPE | Accepts "in-memory" (non-HA option) and "postgres" (HA option). | | Yes | -| STATIC_FILES_PATH | Path to the UI website of Argo Watcher | static | No | -| SKIP_TLS_VERIFY | Skip SSL verification during API calls | false | No | -| LOG_LEVEL | Severity for logging (trace,debug,info,warn,error,fatal, panic) | info | No | -| LOG_FORMAT | json (used for production by default) or text (used for development) | json | No | -| HOST | Host for Argo Watcher server. | 0.0.0.0 | No | -| PORT | Port for Argo Watcher server. | 8080 | No | -| DB_HOST | Database host (Required for STATE_TYPE=postgres) | localhost | Conditional | -| DB_PORT | Database port (Required for STATE_TYPE=postgres) | 5432 | Conditional | -| DB_NAME | Database name (Required for STATE_TYPE=postgres) | | Conditional | -| DB_USER | Database username(Required for STATE_TYPE=postgres) | | Conditional | -| DB_PASSWORD | Database password (Required for STATE_TYPE=postgres) | | Conditional | - +| Variable | Description | Default | Mandatory | +|---------------------|----------------------------------------------------------------------|-----------|-------------| +| ARGO_URL | ArgoCD URL | | Yes | +| ARGO_TOKEN | ArgoCD API token | | Yes | +| ARGO_API_TIMEOUT | Timeout for ArgoCD API calls. Defaults to 60 seconds | 60 | No | +| ARGO_TIMEOUT | Time that Argo Watcher is allowed to wait for deployment. | 0 | No | +| ARGO_REFRESH_APP | Refresh application during status check | true | No | +| DOCKER_IMAGES_PROXY | Define registry proxy url for image checks | | No | +| STATE_TYPE | Accepts "in-memory" (non-HA option) and "postgres" (HA option). | | Yes | +| STATIC_FILES_PATH | Path to the UI website of Argo Watcher | static | No | +| SKIP_TLS_VERIFY | Skip SSL verification during API calls | false | No | +| LOG_LEVEL | Severity for logging (trace,debug,info,warn,error,fatal, panic) | info | No | +| LOG_FORMAT | json (used for production by default) or text (used for development) | json | No | +| HOST | Host for Argo Watcher server. | 0.0.0.0 | No | +| PORT | Port for Argo Watcher server. | 8080 | No | +| DB_HOST | Database host (Required for STATE_TYPE=postgres) | localhost | Conditional | +| DB_PORT | Database port (Required for STATE_TYPE=postgres) | 5432 | Conditional | +| DB_NAME | Database name (Required for STATE_TYPE=postgres) | | Conditional | +| DB_USER | Database username(Required for STATE_TYPE=postgres) | | Conditional | +| DB_PASSWORD | Database password (Required for STATE_TYPE=postgres) | | Conditional | +| SSH_KEY_PATH | Path to ssh key that would be used to interact with git repositories | | Conditional | +| SSH_KEY_PASS | Password for ssh key | | No | +| SSH_COMMIT_USER | Git user name for commit | | No | +| SSH_COMMIT_EMAIL | Git user email for commit | | No | # Client setup -The client is designed to run on Kubernetes runners. We have a [dedicated docker image](https://ghcr.io/shini4i/argo-watcher-client) for Argo Watcher Client CI/CD jobs. +The client is designed to run on Kubernetes runners. We have +a [dedicated docker image](https://ghcr.io/shini4i/argo-watcher-client) for Argo Watcher Client CI/CD jobs. ## Running on GitLab CI/CD -Example deployment setup for running with GitLab CI/CD (reference: https://docs.gitlab.com/ee/ci/docker/using_kaniko.html) +Example deployment setup for running with GitLab CI/CD ( +reference: https://docs.gitlab.com/ee/ci/docker/using_kaniko.html) ```yaml # we have only deployment stage @@ -83,7 +92,7 @@ build: stage: deploy image: name: gcr.io/kaniko-project/executor:v1.9.0-debug - entrypoint: [""] + entrypoint: [ "" ] script: - /kaniko/executor --context "${CI_PROJECT_DIR}" @@ -107,7 +116,7 @@ watch: script: - /argo-watcher -client # run after we build the image - needs: [build] + needs: [ build ] # wait only on main and only when build was successfull rules: - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH @@ -116,12 +125,13 @@ watch: Argo Watcher Client supports the following environment variables -| Variable | Description | Mandatory | -|------------------|------------------------------------------------------------------------|-----------| -| ARGO_WATCHER_URL | The url of argo-watcher instance | Yes | -| ARGO_APP | The name of argo app to check for images rollout | Yes | -| COMMIT_AUTHOR | The person who made commit/triggered pipeline | Yes | -| PROJECT_NAME | An identificator of the business project (not related to argo project) | Yes | -| IMAGES | A list of images (separated by ",") that should contain specific tag | Yes | -| IMAGE_TAG | An image tag that is expected to be rolled out | Yes | -| DEBUG | Print various debug information | No | +| Variable | Description | Mandatory | +|---------------------------|---------------------------------------------------------------------------------------------------------------------------|-----------| +| ARGO_WATCHER_URL | The url of argo-watcher instance | Yes | +| ARGO_APP | The name of argo app to check for images rollout | Yes | +| COMMIT_AUTHOR | The person who made commit/triggered pipeline | Yes | +| PROJECT_NAME | An identificator of the business project (not related to argo project) | Yes | +| IMAGES | A list of images (separated by ",") that should contain specific tag | Yes | +| IMAGE_TAG | An image tag that is expected to be rolled out | Yes | +| ARGO_WATCHER_DEPLOY_TOKEN | A token to enable git image override (required when argo watcher is managing deployments instead of argocd image updater) | No | +| DEBUG | Print various debug information | No | diff --git a/pkg/client/client.go b/pkg/client/client.go index 6c9e35f9..b567448b 100644 --- a/pkg/client/client.go +++ b/pkg/client/client.go @@ -130,7 +130,7 @@ func ClientWatcher() { App: os.Getenv("ARGO_APP"), Author: os.Getenv("COMMIT_AUTHOR"), Project: os.Getenv("PROJECT_NAME"), - ProvidedToken: os.Getenv("ARGO_WATCHER_TOKEN"), + ProvidedToken: os.Getenv("ARGO_WATCHER_DEPLOY_TOKEN"), Images: images, } @@ -146,7 +146,7 @@ func ClientWatcher() { "IMAGES: %s\n\n", watcher.baseUrl, task.App, task.Author, task.Project, tag, task.Images) if task.ProvidedToken == "" { - fmt.Println("ARGO_WATCHER_TOKEN is not set, git commit will not be performed.") + fmt.Println("ARGO_WATCHER_DEPLOY_TOKEN is not set, git commit will not be performed.") } } From c1f3b0d256c5d4338da70241cb4c49786167c5ba Mon Sep 17 00:00:00 2001 From: Vadim Gedz Date: Tue, 29 Aug 2023 12:21:35 +0300 Subject: [PATCH 21/29] minor logic fix --- cmd/argo-watcher/argo_status_updater.go | 5 +++- cmd/argo-watcher/router.go | 2 +- internal/models/argo.go | 34 ++++++++++++++++--------- internal/models/task.go | 21 ++++++++------- pkg/client/client.go | 21 +++++++++------ 5 files changed, 50 insertions(+), 33 deletions(-) diff --git a/cmd/argo-watcher/argo_status_updater.go b/cmd/argo-watcher/argo_status_updater.go index d34762fd..2e148917 100644 --- a/cmd/argo-watcher/argo_status_updater.go +++ b/cmd/argo-watcher/argo_status_updater.go @@ -87,7 +87,10 @@ func (updater *ArgoStatusUpdater) waitForApplicationDeployment(task models.Task) updater.Lock() defer updater.Unlock() log.Debug().Str("id", task.Id).Msg("Application managed by watcher. Initiating git repo update.") - app.UpdateGitImageTag(&task) + if err := app.UpdateGitImageTag(&task); err != nil { + log.Error().Str("id", task.Id).Msgf("Failed to update git repo. Error: %s", err.Error()) + return nil, err + } } else { log.Debug().Str("id", task.Id).Msg("Skipping git repo update: Application not managed by watcher or token is absent/invalid.") } diff --git a/cmd/argo-watcher/router.go b/cmd/argo-watcher/router.go index 2aa7d99b..10c456f6 100644 --- a/cmd/argo-watcher/router.go +++ b/cmd/argo-watcher/router.go @@ -113,7 +113,7 @@ func (env *Env) addTask(c *gin.Context) { // not an optimal solution, but for PoC it's fine // need to find a better way to pass the token later - deployToken := c.GetHeader("ARGO_DEPLOY_TOKEN") + deployToken := c.GetHeader("ARGO_WATCHER_DEPLOY_TOKEN") if deployToken != "" && deployToken == env.config.DeployToken { log.Debug().Msgf("deploy token is validated for app %s", task.App) diff --git a/internal/models/argo.go b/internal/models/argo.go index 4cb4bd9a..c3ff8ab1 100644 --- a/internal/models/argo.go +++ b/internal/models/argo.go @@ -196,13 +196,16 @@ func (app *Application) IsManagedByWatcher() bool { return app.Metadata.Annotations[managedAnnotation] == "true" } -func (app *Application) processAppAnnotations(annotations map[string]string, task *Task) *updater.ArgoOverrideFile { +func (app *Application) processAppAnnotations(annotations map[string]string, task *Task) (*updater.ArgoOverrideFile, error) { overrideFileContent := updater.ArgoOverrideFile{} - managedImages := extractManagedImages(annotations) + managedImages, err := extractManagedImages(annotations) + if err != nil { + return nil, err + } if len(managedImages) == 0 { log.Error().Msgf("%s annotation not found, skipping image update", managedImagesAnnotation) - return nil + return nil, nil } for _, image := range task.Images { @@ -221,19 +224,24 @@ func (app *Application) processAppAnnotations(annotations map[string]string, tas } } - return &overrideFileContent + return &overrideFileContent, nil } -func (app *Application) UpdateGitImageTag(task *Task) { +func (app *Application) UpdateGitImageTag(task *Task) error { if app.Spec.Source.Path == "" { log.Warn().Str("id", task.Id).Msgf("No path found for app %s, unsupported Application configuration", app.Metadata.Name) - return + // technically, unsupported Application configuration is not an error (or is it?) + return nil + } + + releaseOverrides, err := app.processAppAnnotations(app.Metadata.Annotations, task) + if err != nil { + return err } - releaseOverrides := app.processAppAnnotations(app.Metadata.Annotations, task) if releaseOverrides == nil { log.Warn().Str("id", task.Id).Msgf("No release overrides found for app %s", app.Metadata.Name) - return + return nil } git := updater.GitRepo{ @@ -244,18 +252,20 @@ func (app *Application) UpdateGitImageTag(task *Task) { if err := git.Clone(); err != nil { log.Error().Str("id", task.Id).Msgf("Failed to clone git repository %s", app.Spec.Source.RepoURL) - return + return err } if err := git.UpdateApp(app.Metadata.Name, releaseOverrides); err != nil { log.Error().Str("id", task.Id).Msgf("Failed to update git repository %s", app.Spec.Source.RepoURL) - return + return err } + + return nil } // extractManagedImages extracts the managed images from the application's annotations. // It returns a map of the managed images, where the key is the application alias and the value is the image name. -func extractManagedImages(annotations map[string]string) map[string]string { +func extractManagedImages(annotations map[string]string) (map[string]string, error) { managedImages := map[string]string{} for annotation, value := range annotations { @@ -266,7 +276,7 @@ func extractManagedImages(annotations map[string]string) map[string]string { } } - return managedImages + return managedImages, nil } type Userinfo struct { diff --git a/internal/models/task.go b/internal/models/task.go index 2b3728b5..3e7f614d 100644 --- a/internal/models/task.go +++ b/internal/models/task.go @@ -11,17 +11,16 @@ type Image struct { } type Task struct { - Id string `json:"id,omitempty"` - Created float64 `json:"created,omitempty"` - Updated float64 `json:"updated,omitempty"` - App string `json:"app" binding:"required" example:"argo-watcher"` - Author string `json:"author" binding:"required" example:"John Doe"` - Project string `json:"project" binding:"required" example:"Demo"` - Images []Image `json:"images" binding:"required"` - Status string `json:"status,omitempty"` - StatusReason string `json:"status_reason,omitempty"` - ProvidedToken string `json:"token,omitempty"` - Validated bool + Id string `json:"id,omitempty"` + Created float64 `json:"created,omitempty"` + Updated float64 `json:"updated,omitempty"` + App string `json:"app" binding:"required" example:"argo-watcher"` + Author string `json:"author" binding:"required" example:"John Doe"` + Project string `json:"project" binding:"required" example:"Demo"` + Images []Image `json:"images" binding:"required"` + Status string `json:"status,omitempty"` + StatusReason string `json:"status_reason,omitempty"` + Validated bool } // ListImages returns a list of strings representing the images of the task. diff --git a/pkg/client/client.go b/pkg/client/client.go index b567448b..1da1f849 100644 --- a/pkg/client/client.go +++ b/pkg/client/client.go @@ -24,7 +24,7 @@ var ( tag = os.Getenv("IMAGE_TAG") ) -func (watcher *Watcher) addTask(task models.Task) string { +func (watcher *Watcher) addTask(task models.Task, token string) string { body, err := json.Marshal(task) if err != nil { panic(err) @@ -38,6 +38,10 @@ func (watcher *Watcher) addTask(task models.Task) string { request.Header.Set("Content-Type", "application/json; charset=UTF-8") + if token != "" { + request.Header.Set("ARGO_WATCHER_DEPLOY_TOKEN", token) + } + response, err := watcher.client.Do(request) if err != nil { panic(err) @@ -127,15 +131,16 @@ func ClientWatcher() { } task := models.Task{ - App: os.Getenv("ARGO_APP"), - Author: os.Getenv("COMMIT_AUTHOR"), - Project: os.Getenv("PROJECT_NAME"), - ProvidedToken: os.Getenv("ARGO_WATCHER_DEPLOY_TOKEN"), - Images: images, + App: os.Getenv("ARGO_APP"), + Author: os.Getenv("COMMIT_AUTHOR"), + Project: os.Getenv("PROJECT_NAME"), + Images: images, } debug, _ := strconv.ParseBool(os.Getenv("DEBUG")) + deployToken := os.Getenv("ARGO_WATCHER_DEPLOY_TOKEN") + if debug { fmt.Printf("Got the following configuration:\n"+ "ARGO_WATCHER_URL: %s\n"+ @@ -145,14 +150,14 @@ func ClientWatcher() { "IMAGE_TAG: %s\n"+ "IMAGES: %s\n\n", watcher.baseUrl, task.App, task.Author, task.Project, tag, task.Images) - if task.ProvidedToken == "" { + if deployToken == "" { fmt.Println("ARGO_WATCHER_DEPLOY_TOKEN is not set, git commit will not be performed.") } } fmt.Printf("Waiting for %s app to be running on %s version.\n", task.App, tag) - id := watcher.addTask(task) + id := watcher.addTask(task, deployToken) time.Sleep(5 * time.Second) From a6c5401ea8fe3155a787c271e977f85dc0871240 Mon Sep 17 00:00:00 2001 From: Vadim Gedz Date: Tue, 29 Aug 2023 16:04:29 +0300 Subject: [PATCH 22/29] add annotations issue handling --- internal/models/argo.go | 6 +++++- internal/models/argo_test.go | 4 +++- pkg/client/client_test.go | 2 +- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/internal/models/argo.go b/internal/models/argo.go index c3ff8ab1..b5be5154 100644 --- a/internal/models/argo.go +++ b/internal/models/argo.go @@ -271,7 +271,11 @@ func extractManagedImages(annotations map[string]string) (map[string]string, err for annotation, value := range annotations { if annotation == managedImagesAnnotation { for _, image := range strings.Split(value, ",") { - managedImages[strings.Split(image, "=")[0]] = strings.Split(image, "=")[1] + if !strings.Contains(image, "=") { + return nil, fmt.Errorf("invalid format for %s annotation", managedImagesAnnotation) + } + managedImage := strings.Split(image, "=") + managedImages[managedImage[0]] = managedImage[1] } } } diff --git a/internal/models/argo_test.go b/internal/models/argo_test.go index 6950a93f..24a0a3cd 100644 --- a/internal/models/argo_test.go +++ b/internal/models/argo_test.go @@ -310,7 +310,9 @@ func TestExtractManagedImages(t *testing.T) { for _, test := range tests { t.Run(test.name, func(t *testing.T) { - assert.Equal(t, test.expected, extractManagedImages(test.annotation)) + extractedImages, err := extractManagedImages(test.annotation) + assert.NoError(t, err) + assert.Equal(t, test.expected, extractedImages) }) } } diff --git a/pkg/client/client_test.go b/pkg/client/client_test.go index bc131902..602d1750 100644 --- a/pkg/client/client_test.go +++ b/pkg/client/client_test.go @@ -106,7 +106,7 @@ func TestAddTask(t *testing.T) { }, } - id := client.addTask(task) + id := client.addTask(task, "") if id != expected.Id { t.Errorf("Expected id %s, got %s", expected.Id, id) From 3c4dd4733083595f8af6b64d4fa0887b3dc93052 Mon Sep 17 00:00:00 2001 From: Vadim Gedz Date: Tue, 29 Aug 2023 23:56:14 +0300 Subject: [PATCH 23/29] fix and improve mutext logic --- cmd/argo-watcher/argo_status_updater.go | 26 ++++++++++++++--- cmd/argo-watcher/argo_status_updater_test.go | 30 ++++++++++++++++++++ 2 files changed, 52 insertions(+), 4 deletions(-) diff --git a/cmd/argo-watcher/argo_status_updater.go b/cmd/argo-watcher/argo_status_updater.go index 2e148917..9c5642f7 100644 --- a/cmd/argo-watcher/argo_status_updater.go +++ b/cmd/argo-watcher/argo_status_updater.go @@ -14,11 +14,21 @@ import ( const failedToUpdateTaskStatusTemplate string = "Failed to change task status: %s" +type MutexMap struct { + m sync.Map +} + +func (mm *MutexMap) Get(key string) *sync.Mutex { + log.Debug().Msgf("getting mutex for key %s", key) + m, _ := mm.m.LoadOrStore(key, &sync.Mutex{}) + return m.(*sync.Mutex) +} + type ArgoStatusUpdater struct { argo Argo registryProxyUrl string retryOptions []retry.Option - sync.Mutex + mutex MutexMap } func (updater *ArgoStatusUpdater) Init(argo Argo, retryAttempts uint, retryDelay time.Duration, registryProxyUrl string) { @@ -83,15 +93,23 @@ func (updater *ArgoStatusUpdater) waitForApplicationDeployment(task models.Task) return nil, err } + // This mutex is used only to avoid concurrent updates of the same application. + mutex := updater.mutex.Get(task.App) + + // Locking the mutex explicitly to potentially unlock within the next if block, + // avoiding defer to unlock before the function's end. This approach may be revised later + mutex.Lock() + if app.IsManagedByWatcher() && task.Validated { - updater.Lock() - defer updater.Unlock() log.Debug().Str("id", task.Id).Msg("Application managed by watcher. Initiating git repo update.") - if err := app.UpdateGitImageTag(&task); err != nil { + err := app.UpdateGitImageTag(&task) + mutex.Unlock() + if err != nil { log.Error().Str("id", task.Id).Msgf("Failed to update git repo. Error: %s", err.Error()) return nil, err } } else { + mutex.Unlock() log.Debug().Str("id", task.Id).Msg("Skipping git repo update: Application not managed by watcher or token is absent/invalid.") } diff --git a/cmd/argo-watcher/argo_status_updater_test.go b/cmd/argo-watcher/argo_status_updater_test.go index aae69f53..a25aef66 100644 --- a/cmd/argo-watcher/argo_status_updater_test.go +++ b/cmd/argo-watcher/argo_status_updater_test.go @@ -2,6 +2,8 @@ package main import ( "fmt" + "github.com/stretchr/testify/assert" + "sync" "testing" "time" @@ -399,3 +401,31 @@ func TestArgoStatusUpdaterCheck(t *testing.T) { updater.WaitForRollout(task) }) } + +func TestMutexMapGet(t *testing.T) { + mm := &MutexMap{} + + key := "testKey" + mutex1 := mm.Get(key) + assert.NotNil(t, mutex1) + + // Fetch the mutex again + mutex2 := mm.Get(key) + assert.NotNil(t, mutex2) + + // Ensure they're the same + assert.Equal(t, mutex1, mutex2) + + // Test concurrency + wg := &sync.WaitGroup{} + const numRoutines = 50 + for i := 0; i < numRoutines; i++ { + wg.Add(1) + go func() { + defer wg.Done() + m := mm.Get(key) + assert.Equal(t, mutex1, m) + }() + } + wg.Wait() +} From 9b53f73e0443f9b9e23e42c11b0fdd2efcd68a9c Mon Sep 17 00:00:00 2001 From: Vadim Gedz Date: Wed, 30 Aug 2023 00:00:00 +0300 Subject: [PATCH 24/29] fix comment --- cmd/argo-watcher/argo_status_updater.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/argo-watcher/argo_status_updater.go b/cmd/argo-watcher/argo_status_updater.go index 9c5642f7..e86f2a0d 100644 --- a/cmd/argo-watcher/argo_status_updater.go +++ b/cmd/argo-watcher/argo_status_updater.go @@ -96,7 +96,7 @@ func (updater *ArgoStatusUpdater) waitForApplicationDeployment(task models.Task) // This mutex is used only to avoid concurrent updates of the same application. mutex := updater.mutex.Get(task.App) - // Locking the mutex explicitly to potentially unlock within the next if block, + // Locking the mutex here to unlock within the next if block without duplicating the code, // avoiding defer to unlock before the function's end. This approach may be revised later mutex.Lock() From 6f214d2859219ca3c67dcae7a9addb3f82ec184b Mon Sep 17 00:00:00 2001 From: Vadim Gedz Date: Wed, 30 Aug 2023 14:10:14 +0300 Subject: [PATCH 25/29] add a simple retry for updater activities --- cmd/argo-watcher/argo_status_updater.go | 21 +++++++++++++++++++-- internal/models/argo.go | 3 +-- 2 files changed, 20 insertions(+), 4 deletions(-) diff --git a/cmd/argo-watcher/argo_status_updater.go b/cmd/argo-watcher/argo_status_updater.go index e86f2a0d..3ab93f3a 100644 --- a/cmd/argo-watcher/argo_status_updater.go +++ b/cmd/argo-watcher/argo_status_updater.go @@ -19,7 +19,7 @@ type MutexMap struct { } func (mm *MutexMap) Get(key string) *sync.Mutex { - log.Debug().Msgf("getting mutex for key %s", key) + log.Debug().Msgf("acquiring mutex for %s app", key) m, _ := mm.m.LoadOrStore(key, &sync.Mutex{}) return m.(*sync.Mutex) } @@ -102,7 +102,24 @@ func (updater *ArgoStatusUpdater) waitForApplicationDeployment(task models.Task) if app.IsManagedByWatcher() && task.Validated { log.Debug().Str("id", task.Id).Msg("Application managed by watcher. Initiating git repo update.") - err := app.UpdateGitImageTag(&task) + + // simplest way to deal with potential git conflicts + // need to be replaced with a more sophisticated solution after PoC + err := retry.Do( + func() error { + if err := app.UpdateGitImageTag(&task); err != nil { + return err + } + return nil + }, + retry.DelayType(retry.FixedDelay), + retry.Attempts(3), + retry.OnRetry(func(n uint, err error) { + log.Warn().Str("id", task.Id).Msgf("Failed to update git repo. Error: %s, retrying...", err.Error()) + }), + retry.LastErrorOnly(true), + ) + mutex.Unlock() if err != nil { log.Error().Str("id", task.Id).Msgf("Failed to update git repo. Error: %s", err.Error()) diff --git a/internal/models/argo.go b/internal/models/argo.go index b5be5154..a4c5704a 100644 --- a/internal/models/argo.go +++ b/internal/models/argo.go @@ -3,10 +3,9 @@ package models import ( "fmt" "github.com/rs/zerolog/log" + "github.com/shini4i/argo-watcher/internal/helpers" "github.com/shini4i/argo-watcher/pkg/updater" "strings" - - "github.com/shini4i/argo-watcher/internal/helpers" ) const ( From 69abd2a7387b1a56d9e9799dc1f579336e459280 Mon Sep 17 00:00:00 2001 From: Vadim Gedz Date: Wed, 30 Aug 2023 14:44:27 +0300 Subject: [PATCH 26/29] add golangci-lint exclusion --- cmd/argo-watcher/argo_status_updater.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/argo-watcher/argo_status_updater.go b/cmd/argo-watcher/argo_status_updater.go index 3ab93f3a..0241eef9 100644 --- a/cmd/argo-watcher/argo_status_updater.go +++ b/cmd/argo-watcher/argo_status_updater.go @@ -21,7 +21,7 @@ type MutexMap struct { func (mm *MutexMap) Get(key string) *sync.Mutex { log.Debug().Msgf("acquiring mutex for %s app", key) m, _ := mm.m.LoadOrStore(key, &sync.Mutex{}) - return m.(*sync.Mutex) + return m.(*sync.Mutex) // nolint:forcetypeassert // type assertion is guaranteed to be correct } type ArgoStatusUpdater struct { From 23502c10d1d9aef909128eae60de224fda30d832 Mon Sep 17 00:00:00 2001 From: Vadim Gedz Date: Wed, 30 Aug 2023 18:03:33 +0300 Subject: [PATCH 27/29] chore: bump project dependencies --- go.mod | 24 ++++++++--------- go.sum | 83 ++++++++++++++++++---------------------------------------- 2 files changed, 38 insertions(+), 69 deletions(-) diff --git a/go.mod b/go.mod index 745f1ed9..26ff8a79 100644 --- a/go.mod +++ b/go.mod @@ -3,20 +3,20 @@ module github.com/shini4i/argo-watcher go 1.20 require ( - github.com/avast/retry-go/v4 v4.1.0 + github.com/avast/retry-go/v4 v4.5.0 github.com/gin-gonic/contrib v0.0.0-20201101042839-6a891bf89f19 github.com/gin-gonic/gin v1.9.1 github.com/go-git/go-billy/v5 v5.4.1 github.com/go-git/go-git/v5 v5.8.1 github.com/golang-migrate/migrate/v4 v4.15.2 - github.com/google/uuid v1.3.0 + github.com/google/uuid v1.3.1 github.com/kelseyhightower/envconfig v1.4.0 github.com/lib/pq v1.10.6 - github.com/prometheus/client_golang v1.12.2 - github.com/rs/zerolog v1.29.1 + github.com/prometheus/client_golang v1.16.0 + github.com/rs/zerolog v1.30.0 github.com/stretchr/testify v1.8.3 - github.com/swaggo/files v0.0.0-20220728132757-551d4a08d97a - github.com/swaggo/gin-swagger v1.5.2 + github.com/swaggo/files v1.0.1 + github.com/swaggo/gin-swagger v1.6.0 github.com/swaggo/swag v1.16.1 go.uber.org/mock v0.2.0 gopkg.in/yaml.v2 v2.4.0 @@ -33,7 +33,7 @@ require ( github.com/acomagu/bufpipe v1.0.4 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/bytedance/sonic v1.9.1 // indirect - github.com/cespare/xxhash/v2 v2.1.2 // indirect + github.com/cespare/xxhash/v2 v2.2.0 // indirect github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 // indirect github.com/cloudflare/circl v1.3.3 // indirect github.com/davecgh/go-spew v1.1.1 // indirect @@ -51,7 +51,7 @@ require ( github.com/go-sql-driver/mysql v1.7.0 // indirect github.com/goccy/go-json v0.10.2 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect - github.com/golang/protobuf v1.5.2 // indirect + github.com/golang/protobuf v1.5.3 // indirect github.com/hashicorp/errwrap v1.1.0 // indirect github.com/hashicorp/go-multierror v1.1.1 // indirect github.com/jackc/pgpassfile v1.0.0 // indirect @@ -68,15 +68,15 @@ require ( github.com/mailru/easyjson v0.7.7 // indirect github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.19 // indirect - github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 // indirect + github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect github.com/pelletier/go-toml/v2 v2.0.8 // indirect github.com/pjbgf/sha1cd v0.3.0 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect - github.com/prometheus/client_model v0.2.0 // indirect - github.com/prometheus/common v0.32.1 // indirect - github.com/prometheus/procfs v0.7.3 // indirect + github.com/prometheus/client_model v0.3.0 // indirect + github.com/prometheus/common v0.42.0 // indirect + github.com/prometheus/procfs v0.10.1 // indirect github.com/sergi/go-diff v1.1.0 // indirect github.com/skeema/knownhosts v1.2.0 // indirect github.com/twitchyliquid64/golang-asm v0.15.1 // indirect diff --git a/go.sum b/go.sum index 837fca7e..e0378322 100644 --- a/go.sum +++ b/go.sum @@ -116,7 +116,6 @@ github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdko github.com/Shopify/logrus-bugsnag v0.0.0-20171204204709-577dee27f20d/go.mod h1:HI8ITrYtUY+O+ZhtlqUnD8+KwNPOyugEhfP9fdUIaEQ= github.com/acomagu/bufpipe v1.0.4 h1:e3H4WUzM3npvo5uv95QuJM3cQspFNtFBzvJ2oNjKIDQ= github.com/acomagu/bufpipe v1.0.4/go.mod h1:mxdxdup/WdsKVreO5GpW4+M/1CE2sMG4jeGJ2sYmHc4= -github.com/agiledragon/gomonkey/v2 v2.3.1/go.mod h1:ap1AmDzcVOAz1YpeJ3TCzIgstoaWLA6jbbgxfB4w2iY= github.com/ajstarks/svgo v0.0.0-20180226025133-644b8db467af/go.mod h1:K08gAheRH3/J6wwsYMMT4xOr94bZjxIelGM0+d/wbFw= 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= @@ -135,8 +134,8 @@ github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmV github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio= github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY= -github.com/avast/retry-go/v4 v4.1.0 h1:CwudD9anYv6JMVnDuTRlK6kLo4dBamiL+F3U8YDiyfg= -github.com/avast/retry-go/v4 v4.1.0/go.mod h1:HqmLvS2VLdStPCGDFjSuZ9pzlTqVRldCI4w2dO4m1Ms= +github.com/avast/retry-go/v4 v4.5.0 h1:QoRAZZ90cj5oni2Lsgl2GW8mNTnUCnmpx/iKpwVisHg= +github.com/avast/retry-go/v4 v4.5.0/go.mod h1:7hLEXp0oku2Nir2xBAsg0PTphp9z71bN5Aq1fboC3+I= github.com/aws/aws-sdk-go v1.15.11/go.mod h1:mFuSZ37Z9YOHbQEwBWztmVzqXrEkub65tZoCYDt7FT0= github.com/aws/aws-sdk-go v1.17.7/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= github.com/aws/aws-sdk-go-v2 v1.8.0/go.mod h1:xEFuWz+3TYdlPRuo+CqATbeDWIWyaT5uAPwPaWtgse0= @@ -199,8 +198,9 @@ github.com/certifi/gocertifi v0.0.0-20191021191039-0944d244cd40/go.mod h1:sGbDF6 github.com/certifi/gocertifi v0.0.0-20200922220541-2c3bb06c6054/go.mod h1:sGbDF6GwGcLpkNXPUTkMRoywsNa/ol15pxFe6ERfguA= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE= github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= +github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/checkpoint-restore/go-criu/v4 v4.1.0/go.mod h1:xUQBLp4RLc5zJtWY++yjOoMoB5lihDt7fai+75m+rGw= github.com/checkpoint-restore/go-criu/v5 v5.0.0/go.mod h1:cfwC0EG7HMUenopBsUf9d89JlCLQIfgVcNsNN0t6T2M= github.com/checkpoint-restore/go-criu/v5 v5.3.0/go.mod h1:E/eQpaFtUKGOOSEBZgmKAcn+zUUwWxqcaKZlF54wK8E= @@ -439,12 +439,10 @@ github.com/getsentry/raven-go v0.2.0/go.mod h1:KungGk8q33+aIAZUIVWZDr2OfAEBsO49P 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/gzip v0.0.6 h1:NjcunTcGAj5CO1gn4N8jHOSIeRFHIbn51z6K+xaN4d4= -github.com/gin-contrib/gzip v0.0.6/go.mod h1:QOJlmV2xmayAjkNS2Y8NQsMneuRShOU/kjovCXNuzzk= 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/contrib v0.0.0-20201101042839-6a891bf89f19 h1:J2LPEOcQmWaooBnBtUDV9KHFEnP5LYTZY03GiQ0oQBw= github.com/gin-gonic/contrib v0.0.0-20201101042839-6a891bf89f19/go.mod h1:iqneQ2Df3omzIVTkIfn7c1acsVnMGiSLn4XF5Blh3Yg= -github.com/gin-gonic/gin v1.8.1/go.mod h1:ji8BvRH1azfM+SYow9zQ6SZMvR8qOMZHmsCuWR9tTTk= github.com/gin-gonic/gin v1.9.1 h1:4idEAncQnU5cB7BeOkPtxjfCSye0AAm1R0RVIqJ+Jmg= github.com/gin-gonic/gin v1.9.1/go.mod h1:hPrL7YrpYKXt5YId3A/Tnip5kqbEAP+KLuI3SUcPTeU= github.com/gliderlabs/ssh v0.3.5 h1:OcaySEmAQJgyYcArR+gGGTHCyE7nvhEMTlYY+Dp8CpY= @@ -488,13 +486,11 @@ github.com/go-openapi/jsonreference v0.0.0-20160704190145-13c6e3589ad9/go.mod h1 github.com/go-openapi/jsonreference v0.19.2/go.mod h1:jMjeRr2HHw6nAVajTXJ4eiUwohSTlpa0o73RUL1owJc= github.com/go-openapi/jsonreference v0.19.3/go.mod h1:rjx6GuL8TTa9VaixXglHmQmIL98+wF9xc8zWvFonSJ8= github.com/go-openapi/jsonreference v0.19.5/go.mod h1:RdybgQwPxbL4UEjuAruzK1x3nE69AqPYEJeo/TWfEeg= -github.com/go-openapi/jsonreference v0.19.6/go.mod h1:diGHMEHg2IqXZGKxqyvWdfWU/aim5Dprw5bqpKkTvns= github.com/go-openapi/jsonreference v0.20.0/go.mod h1:Ag74Ico3lPc+zR+qjn4XBUmXymS4zJbYVCZmcgkasdo= github.com/go-openapi/jsonreference v0.20.2 h1:3sVjiK66+uXK/6oQ8xgcRKcFgQ5KXa2KvnJRumpMGbE= github.com/go-openapi/jsonreference v0.20.2/go.mod h1:Bl1zwGIM8/wsvqjsOQLJ/SH+En5Ap4rVB5KVcIDZG2k= github.com/go-openapi/spec v0.0.0-20160808142527-6aced65f8501/go.mod h1:J8+jY1nAiCcj+friV/PDoE1/3eeccG9LYBs0tYvLOWc= github.com/go-openapi/spec v0.19.3/go.mod h1:FpwSN1ksY1eteniUU7X0N/BgJ7a4WvBFVA8Lj9mJglo= -github.com/go-openapi/spec v0.20.4/go.mod h1:faYFR1CvsJZ0mNsmsphTMSoRrNV3TEDoAM7FOEWeq8I= github.com/go-openapi/spec v0.20.9 h1:xnlYNQAwKd2VQRRfwTEI0DcK+2cbuvI/0c7jx3gA8/8= github.com/go-openapi/spec v0.20.9/go.mod h1:2OpW+JddWPrpXSCIX8eOx7lZ5iyuWj3RYR6VaaBKcWA= github.com/go-openapi/swag v0.0.0-20160704191624-1d0bd113de87/go.mod h1:DXUve3Dpr1UfpPtxFw+EFuQ41HhCWZfha5jSVRG7C7I= @@ -505,15 +501,11 @@ github.com/go-openapi/swag v0.19.15/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/ github.com/go-openapi/swag v0.22.3/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14= github.com/go-openapi/swag v0.22.4 h1:QLMzNJnMGPRNDCbySlcj1x01tzU8/9LTTL9hZZZogBU= github.com/go-openapi/swag v0.22.4/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14= -github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s= -github.com/go-playground/locales v0.14.0/go.mod h1:sawfccIbzZTqEDETgFXqTho0QybSa7l++s0DH+LDiLs= github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA= github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY= -github.com/go-playground/universal-translator v0.18.0/go.mod h1:UvRDBj+xPUEGrFYl+lu/H90nyDXpg0fqeB/AQUGNTVA= github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY= github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY= -github.com/go-playground/validator/v10 v10.10.0/go.mod h1:74x4gJWsvQexRdW8Pn3dXSGrTK4nAUsbPlLADvpJkos= github.com/go-playground/validator/v10 v10.14.0 h1:vgvQWe3XCz3gIeFDm/HnTIbj6UGmg/+t63MyGU2n5js= github.com/go-playground/validator/v10 v10.14.0/go.mod h1:9iXMNT7sEkjXb0I+enO7QXmzG6QCsPWY4zveKFVRSyU= github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= @@ -547,7 +539,6 @@ github.com/gobuffalo/packd v0.1.0/go.mod h1:M2Juc+hhDXf/PnmBANFCqx4DM3wRbgDvnVWe github.com/gobuffalo/packr/v2 v2.0.9/go.mod h1:emmyGweYTm6Kdper+iywB6YK5YzuKchGtJQZ0Odn4pQ= github.com/gobuffalo/packr/v2 v2.2.0/go.mod h1:CaAwI0GPIAv+5wKLtv8Afwl+Cm78K/I/VCm/3ptBN+0= github.com/gobuffalo/syncx v0.0.0-20190224160051-33c29581e754/go.mod h1:HhnNqWY95UYwwW3uSASeV7vtgYkT2t16hJgV3AEPUpw= -github.com/goccy/go-json v0.9.7/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU= github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= github.com/gocql/gocql v0.0.0-20210515062232-b7ef815b4556/go.mod h1:DL0ekTmBSTdlNF25Orwt/JMzqIq3EJ4MVa/J/uK64OY= @@ -610,8 +601,9 @@ github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= github.com/golang/protobuf v1.5.1/go.mod h1:DopwsBzvsk0Fs44TXzsVbJyPhcCPeIwnvohx4u74HPM= -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/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= +github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/golang/snappy v0.0.0-20170215233205-553a64147049/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= @@ -663,8 +655,9 @@ github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+ 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.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.3.1 h1:KjJaJ9iWZ3jOFZIf1Lqf4laDRCasjl0BCmnEGxkdLb4= +github.com/google/uuid v1.3.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= github.com/googleapis/gax-go/v2 v2.1.0/go.mod h1:Q3nei7sK6ybPYH7twZdmQpAd1MKb7pfu6SK+H1/DsU0= @@ -843,7 +836,6 @@ github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFB github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= -github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/pty v1.1.5/go.mod h1:9r2w37qlBe7rQ6e1fg1S/9xpWHSnaqNdHD3WcMdbPDA= @@ -852,7 +844,6 @@ 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/ktrysmt/go-bitbucket v0.6.4/go.mod h1:9u0v3hsd2rqCHRIpbir1oP7F58uo5dq19sBYvuMoyQ4= -github.com/leodido/go-urn v1.2.1/go.mod h1:zt4jvISO2HfUBqxjfIshjdMTYS56ZS/qv49ictyFfxY= github.com/leodido/go-urn v1.2.4 h1:XlAE/cm/ms7TE/VMVoduSpNBoyc2dOxHs5MZSwAN63Q= github.com/leodido/go-urn v1.2.4/go.mod h1:7ZrI8mTSeBSHl/UaRyKQW1qZeMgak41ANeCNaVckg+4= github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= @@ -908,8 +899,9 @@ github.com/mattn/go-sqlite3 v1.14.6/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A github.com/mattn/go-sqlite3 v1.14.10/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= github.com/mattn/go-sqlite3 v1.14.15 h1:vfoHhTN1af61xCRSWzFIWzx2YskyMTwHLrExkBOjvxI= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= -github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 h1:I0XW9+e1XWDxdcEniV4rQAIOPUGDq67JSCiRCgGCZLI= github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= +github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo= +github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= github.com/maxbrunsfeld/counterfeiter/v6 v6.2.2/go.mod h1:eD9eIE7cdwcMi9rYluz88Jz2VyhSmden33/aXg4oVIY= github.com/microsoft/go-mssqldb v0.17.0 h1:Fto83dMZPnYv1Zwx5vHHxpNraeEaUlQ/hhHLgZiaenE= github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= @@ -1013,17 +1005,11 @@ github.com/opencontainers/selinux v1.8.0/go.mod h1:RScLhm78qiWa2gbVCcGkC7tCGdgk3 github.com/opencontainers/selinux v1.8.2/go.mod h1:MUIHuUEvKB1wtJjQdOyYRgOnLD2xAPP8dBsCoU0KuF8= github.com/opencontainers/selinux v1.10.0/go.mod h1:2i0OySw99QjzBBQByd1Gr9gSjvuho1lHsJxIJ3gGbJI= github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= -github.com/otiai10/copy v1.7.0/go.mod h1:rmRl6QPdJj6EiUqXQ/4Nn2lLXoNQjFCQbbNrxgc/t3U= -github.com/otiai10/curr v0.0.0-20150429015615-9b4961190c95/go.mod h1:9qAhocn7zKJG+0mI8eUu6xqkFDYS2kb2saOteoSB3cE= -github.com/otiai10/curr v1.0.0/go.mod h1:LskTG5wDwr8Rs+nNQ+1LlxRjAtTZZjtJW4rMXl6j4vs= -github.com/otiai10/mint v1.3.0/go.mod h1:F5AjcsTsWUqX+Na9fpHb52P8pcRX2CI6A3ctIT91xUo= -github.com/otiai10/mint v1.3.3/go.mod h1:/yxELlJQ0ufhjUwhshSj+wFjZ78CnZ48/1wtmBH1OTc= github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= github.com/pelletier/go-toml v1.7.0/go.mod h1:vwGMzjaWMwyfHwgIBhI2YUM4fB6nL6lVAvS1LBMMhTE= github.com/pelletier/go-toml v1.8.1/go.mod h1:T2/BmBdy8dvIRq1a/8aqjN41wvWlN4lrapLU/GW4pbc= github.com/pelletier/go-toml v1.9.3/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= -github.com/pelletier/go-toml/v2 v2.0.1/go.mod h1:r9LEWfGN8R5k0VXJ+0BkIe7MYkRdwZOjgMj2KwnJFUo= github.com/pelletier/go-toml/v2 v2.0.8 h1:0ctb6s9mE31h0/lhu+J6OPmVeDxJn+kYnJc2jZR9tGQ= github.com/pelletier/go-toml/v2 v2.0.8/go.mod h1:vuYfssBdrU2XDZ9bYydBu6t+6a6PYNcZljzZR9VXg+4= github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU= @@ -1031,12 +1017,10 @@ github.com/phpdave11/gofpdf v1.4.2/go.mod h1:zpO6xFn9yxo3YLyMvW8HcKWVdbNqgIfOOp2 github.com/phpdave11/gofpdi v1.0.12/go.mod h1:vBmVV0Do6hSBHC8uKUQ71JGW+ZGQq74llk/7bXwjDoI= github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= github.com/pierrec/lz4/v4 v4.1.8/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4= -github.com/pierrre/gotestcover v0.0.0-20160517101806-924dca7d15f0/go.mod h1:4xpMLz7RBWyB+ElzHu8Llua96TRCB3YwX+l5EP1wmHk= github.com/pjbgf/sha1cd v0.3.0 h1:4D5XXmUUBUl/xQ6IjCkEAbqXskkq/4O7LmGn0AqMDs4= github.com/pjbgf/sha1cd v0.3.0/go.mod h1:nZ1rrWOcGJ5uZgEEVL1VUM9iRQiZvWdbZjkKyFzPPsI= github.com/pkg/browser v0.0.0-20210706143420-7d21f8c997e2/go.mod h1:HKlIX3XHQyzLZPlr7++PzdhaXEj94dEiJgZDTsxEqUI= github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8/go.mod h1:HKlIX3XHQyzLZPlr7++PzdhaXEj94dEiJgZDTsxEqUI= -github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1-0.20171018195549-f15c970de5b7/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= @@ -1054,14 +1038,15 @@ github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5Fsn github.com/prometheus/client_golang v1.1.0/go.mod h1:I1FGZT9+L76gKKOs5djB6ezCbFQP1xR9D75/vuwEF3g= 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.2 h1:51L9cDoUHVrXx4zWYlcLQIZ+d+VXHgqnYKkIuq4g/34= -github.com/prometheus/client_golang v1.12.2/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY= +github.com/prometheus/client_golang v1.16.0 h1:yk/hx9hDbrGHovbci4BY+pRMfSuuat626eFsHb7tmT8= +github.com/prometheus/client_golang v1.16.0/go.mod h1:Zsulrv/L9oM40tJ7T815tM89lFEugiJ9HzIqaAx4LKc= github.com/prometheus/client_model v0.0.0-20171117100541-99fa1f4be8e5/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/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.2.0 h1:uq5h0d+GuxiXLJLNABMgp2qUWDPiLvgCzz2dUR+/W/M= github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.3.0 h1:UBgGFHqYdG/TPFD1B1ogZywDqEkwp3fBMvqdiQ7Xew4= +github.com/prometheus/client_model v0.3.0/go.mod h1:LDGWKZIo7rky3hgvBe+caln+Dr3dPggB5dvjtD7w9+w= github.com/prometheus/common v0.0.0-20180110214958-89604d197083/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= @@ -1070,8 +1055,8 @@ github.com/prometheus/common v0.6.0/go.mod h1:eBmuwkDJBwy6iBfxCBob6t6dR6ENT/y+J+ github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc= github.com/prometheus/common v0.30.0/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= -github.com/prometheus/common v0.32.1 h1:hWIdL3N2HoUx3B8j3YN9mWor0qhY/NlEKZEaXxuIRh4= -github.com/prometheus/common v0.32.1/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= +github.com/prometheus/common v0.42.0 h1:EKsfXEYo4JpWMHH5cg+KOUWeuJSov1Id8zGR8eeI1YM= +github.com/prometheus/common v0.42.0/go.mod h1:xBwqVerjNdUDjgODMpudtOMwlOwf2SaTr1yjz4b7Zbc= github.com/prometheus/procfs v0.0.0-20180125133057-cb4147076ac7/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= @@ -1083,26 +1068,24 @@ github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+Gx github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= github.com/prometheus/procfs v0.2.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/prometheus/procfs v0.10.1 h1:kYK1Va/YMlutzCGazswoHKo//tZVlFpKYh+PymziUAg= +github.com/prometheus/procfs v0.10.1/go.mod h1:nwNm2aOCAYw8uTR/9bWRREkZFxAUcWzPHWJq+XBB/FM= github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= github.com/remyoudompheng/bigfft v0.0.0-20190728182440-6a916e37a237/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= -github.com/robertkrimen/godocdown v0.0.0-20130622164427-0bfa04905481/go.mod h1:C9WhFzY47SzYBIvzFqSvHIR6ROgDo4TtdTuRaOMjF/s= github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-internal v1.1.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.2.2/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= -github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= -github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE= github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8= github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ= -github.com/rs/xid v1.4.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= +github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= github.com/rs/zerolog v1.13.0/go.mod h1:YbFCdg8HfsridGWAh22vktObvhZbQsZXe4/zB0OKkWU= github.com/rs/zerolog v1.15.0/go.mod h1:xYTKnLHcpfU2225ny5qZjxnj9NvkumZYjJHlAThCjNc= -github.com/rs/zerolog v1.29.1 h1:cO+d60CHkknCbvzEWxP0S9K6KqyTjrCNUy1LdQLCGPc= -github.com/rs/zerolog v1.29.1/go.mod h1:Le6ESbR7hc+DP6Lt1THiV8CQSdkkNrd3R0XbEgp3ZBU= +github.com/rs/zerolog v1.30.0 h1:SymVODrcRsaRaSInD9yQtKbtWqwsfoPcRff/oRXLj4c= +github.com/rs/zerolog v1.30.0/go.mod h1:/tk+P47gFdPXq4QYjvCmT5/Gsug2nagsFWBWhAiSi1w= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/ruudk/golang-pdf417 v0.0.0-20181029194003-1af4ab5afa58/go.mod h1:6lfFZQK844Gfx8o5WFuvpxWRwnSoipWe/p622j1v06w= github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= @@ -1178,12 +1161,10 @@ github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o github.com/stretchr/testify v1.8.3 h1:RP3t2pwF7cMEbC1dqtB6poj3niw/9gnV4Cjg5oW5gtY= github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= -github.com/swaggo/files v0.0.0-20220610200504-28940afbdbfe/go.mod h1:lKJPbtWzJ9JhsTN1k1gZgleJWY/cqq0psdoMmaThG3w= -github.com/swaggo/files v0.0.0-20220728132757-551d4a08d97a h1:kAe4YSu0O0UFn1DowNo2MY5p6xzqtJ/wQ7LZynSvGaY= -github.com/swaggo/files v0.0.0-20220728132757-551d4a08d97a/go.mod h1:lKJPbtWzJ9JhsTN1k1gZgleJWY/cqq0psdoMmaThG3w= -github.com/swaggo/gin-swagger v1.5.2 h1:dj2es17EaOHoy0Owu4xn3An1mI8/xjdFyIH6KAbOdYo= -github.com/swaggo/gin-swagger v1.5.2/go.mod h1:Cbj/MlHApPOjZdf4joWFXLLgmZVPyh54GPvPPyVjVZM= -github.com/swaggo/swag v1.8.1/go.mod h1:ugemnJsPZm/kRwFUnzBlbHRd0JY9zE1M4F+uy2pAaPQ= +github.com/swaggo/files v1.0.1 h1:J1bVJ4XHZNq0I46UU90611i9/YzdrF7x92oX1ig5IdE= +github.com/swaggo/files v1.0.1/go.mod h1:0qXmMNH6sXNf+73t65aKeB+ApmgxdnkQzVTAj2uaMUg= +github.com/swaggo/gin-swagger v1.6.0 h1:y8sxvQ3E20/RCyrXeFfg60r6H0Z+SwpTjMYsMm+zy8M= +github.com/swaggo/gin-swagger v1.6.0/go.mod h1:BG00cCEy294xtVpyIAHG6+e2Qzj/xKlRdOqDkvq0uzo= github.com/swaggo/swag v1.16.1 h1:fTNRhKstPKxcnoKsytm4sahr8FaYzUcT7i1/3nd/fBg= github.com/swaggo/swag v1.16.1/go.mod h1:9/LMvHycG3NFHfR6LwvikHv5iFvmPADQ359cKikGxto= github.com/syndtr/gocapability v0.0.0-20170704070218-db04d3cc01c8/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww= @@ -1198,15 +1179,12 @@ github.com/tv42/httpunix v0.0.0-20191220191345-2ba4b9c3382c/go.mod h1:hzIxponao9 github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI= github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08= github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc= -github.com/ugorji/go v1.2.7/go.mod h1:nF9osbDWLy6bDVv/Rtoh6QgnvNDpmCalQV5urGCCS6M= -github.com/ugorji/go/codec v1.2.7/go.mod h1:WGN1fab3R1fzQlVQTkfxVtIBhWDRqOviHU95kRgeqEY= github.com/ugorji/go/codec v1.2.11 h1:BMaWp1Bb6fHwEtbplGBGJ498wD+LKlNSl25MjdZY4dU= github.com/ugorji/go/codec v1.2.11/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg= github.com/urfave/cli v0.0.0-20171014202726-7bc6a0acffa5/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= 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.2/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= -github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI= github.com/vishvananda/netlink v0.0.0-20181108222139-023a6dafdcdf/go.mod h1:+SR5DhBJrl6ZM7CoCKvpw5BKroDKQ+PJqOg65H/2ktk= github.com/vishvananda/netlink v1.1.0/go.mod h1:cTgwzPIzzgDAYoQrMm0EdrjRUBkTqKYppBueQtXaqoE= github.com/vishvananda/netlink v1.1.1-0.20201029203352-d40f9887b852/go.mod h1:twkDnbuQxJYemMlGd4JFIcuhgX83tXhKS2B/PRMpOho= @@ -1234,7 +1212,6 @@ github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= -github.com/yuin/goldmark v1.4.0/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= github.com/yvasiyarov/go-metrics v0.0.0-20140926110328-57bccd1ccd43/go.mod h1:aX5oPXxHm3bOH+xeAttToC8pqch2ScQN/JoXYupl6xs= github.com/yvasiyarov/gorelic v0.0.0-20141212073537-a9bba5b9ab50/go.mod h1:NUSPSUX/bi6SeDMUh6brw0nXpxHnc96TguQh0+r/ssA= @@ -1324,7 +1301,6 @@ golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de/go.mod h1:LzIPMQfyMNhhGPh golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= -golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= @@ -1437,14 +1413,12 @@ golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= -golang.org/x/net v0.0.0-20210421230115-4e50805a0758/go.mod h1:72T/g9IO56b78aLF+1Kcs5dz7/ng1VjMUvfKvpfy+jM= golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210505024714-0287a6fb4125/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210520170846-37e1c6afe023/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210614182718-04defd469f4e/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210813160813-60bc85c4be6d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210825183410-e898025ed96a/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= @@ -1452,10 +1426,10 @@ golang.org/x/net v0.0.0-20211209124913-491a49abca63/go.mod h1:9nx3DQGgdP8bBQD5qx golang.org/x/net v0.0.0-20211216030914-fe4d6282115f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220111093109-d55c255bac03/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= +golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= golang.org/x/net v0.12.0 h1:cfawfvKITfUsFCeJIHJrbSxpeu/E81khclypR0GVT50= golang.org/x/net v0.12.0/go.mod h1:zEVYFnQC7m/vmpQFELhcD1EWkZlX69l4oqgmer6hfKA= @@ -1585,7 +1559,6 @@ golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210324051608-47abb6519492/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210420072515-93ed5bcd2bfe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210426230700-d19ff857e887/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -1608,13 +1581,11 @@ golang.org/x/sys v0.0.0-20210906170528-6f6e22806c34/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20210908233432-aa78b53d3365/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211107104306-e0b2ad06fe42/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211116061358-0a5406a5449c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211124211545-fe61309f8881/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211205182925-97ca703d548d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220111092808-5a964db01320/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220317061510-51cd9980dadf/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220704084225-05e143d24a9e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -1737,7 +1708,6 @@ golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.7/go.mod h1:LGqMHiF4EqQNHR1JncWGqT5BVaXmza+X+BDGol+dOxo= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= golang.org/x/tools v0.10.0 h1:tvDr/iQoUqNdohiYm0LmmKcBk+q86lb9EprIUFhHHGg= @@ -1915,7 +1885,6 @@ google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlba google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng= google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= gopkg.in/airbrake/gobrake.v2 v2.0.9/go.mod h1:/h5ZAUhDkGaJfjzjKLSjv6zCL6O0LLBxU4K+aSYdM/U= From 705ded89ee1325fdbf66efe8f2eec279444c012d Mon Sep 17 00:00:00 2001 From: Vadim Gedz Date: Wed, 30 Aug 2023 20:06:32 +0300 Subject: [PATCH 28/29] update pre-commit configuration --- .pre-commit-config.yaml | 12 ++++++++++++ db/migrations/000001_init.up.sql | 2 +- db/migrations/000002_status_reason.up.sql | 2 +- db/migrations/000003_orm_migration.up.sql | 2 +- docs/development.md | 2 +- 5 files changed, 16 insertions(+), 4 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 797e1186..88136111 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -4,8 +4,20 @@ repos: hooks: - id: end-of-file-fixer - id: trailing-whitespace + - id: check-yaml + - id: check-added-large-files + - id: no-commit-to-branch + args: + - --branch=main + - repo: https://github.com/hadolint/hadolint + rev: v2.12.0 + hooks: + - id: hadolint + args: + - --ignore=DL3018 - repo: https://github.com/dnephin/pre-commit-golang rev: v0.5.1 hooks: - id: go-fmt - id: go-mod-tidy + - id: golangci-lint diff --git a/db/migrations/000001_init.up.sql b/db/migrations/000001_init.up.sql index 77e00229..aa07e854 100644 --- a/db/migrations/000001_init.up.sql +++ b/db/migrations/000001_init.up.sql @@ -9,4 +9,4 @@ CREATE TABLE IF NOT EXISTS tasks author VARCHAR(255) DEFAULT NULL, project VARCHAR(255) DEFAULT NULL ); -CREATE INDEX IF NOT EXISTS tasks_idx_created ON tasks (created); \ No newline at end of file +CREATE INDEX IF NOT EXISTS tasks_idx_created ON tasks (created); diff --git a/db/migrations/000002_status_reason.up.sql b/db/migrations/000002_status_reason.up.sql index 78ee3c40..57fd03df 100644 --- a/db/migrations/000002_status_reason.up.sql +++ b/db/migrations/000002_status_reason.up.sql @@ -1 +1 @@ -ALTER TABLE tasks ADD COLUMN status_reason TEXT DEFAULT ''; \ No newline at end of file +ALTER TABLE tasks ADD COLUMN status_reason TEXT DEFAULT ''; diff --git a/db/migrations/000003_orm_migration.up.sql b/db/migrations/000003_orm_migration.up.sql index cd282aee..fbeecf89 100644 --- a/db/migrations/000003_orm_migration.up.sql +++ b/db/migrations/000003_orm_migration.up.sql @@ -19,4 +19,4 @@ ALTER TABLE public.tasks ALTER COLUMN project DROP DEFAULT; ALTER TABLE public.tasks ALTER COLUMN status_reason DROP DEFAULT; ALTER TABLE public.tasks ALTER COLUMN images TYPE JSONB; -CREATE INDEX IF NOT EXISTS "idx_tasks_status" ON "tasks" ("status"); \ No newline at end of file +CREATE INDEX IF NOT EXISTS "idx_tasks_status" ON "tasks" ("status"); diff --git a/docs/development.md b/docs/development.md index 5363d771..f2d3a87e 100644 --- a/docs/development.md +++ b/docs/development.md @@ -72,7 +72,7 @@ LOG_LEVEL=debug LOG_FORMAT=text ARGO_URL=http://localhost:8081 ARGO_TOKEN=exampl Start database ```shell # start the database in a separate terminal window -docker compose up postgres +docker compose up postgres ``` Start server From 1ffee91f3e413e5377b9d7d3e82fd5acbeea070c Mon Sep 17 00:00:00 2001 From: Vadim Gedz Date: Wed, 30 Aug 2023 22:21:11 +0300 Subject: [PATCH 29/29] bump golang version to 1.21 --- .../workflows/run-tests-and-sonar-scan.yml | 2 +- go.mod | 4 ++-- go.sum | 21 +++++++++++++++++++ 3 files changed, 24 insertions(+), 3 deletions(-) diff --git a/.github/workflows/run-tests-and-sonar-scan.yml b/.github/workflows/run-tests-and-sonar-scan.yml index e1a0e805..c2f3f269 100644 --- a/.github/workflows/run-tests-and-sonar-scan.yml +++ b/.github/workflows/run-tests-and-sonar-scan.yml @@ -6,7 +6,7 @@ on: pull_request: types: [opened, synchronize, reopened] env: - GOLANG_VERSION: '1.20.4' + GOLANG_VERSION: '1.21.0' jobs: golangci: diff --git a/go.mod b/go.mod index 26ff8a79..ceda4c51 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/shini4i/argo-watcher -go 1.20 +go 1.21 require ( github.com/avast/retry-go/v4 v4.5.0 @@ -22,7 +22,7 @@ require ( gopkg.in/yaml.v2 v2.4.0 gorm.io/datatypes v1.2.0 gorm.io/driver/postgres v1.5.2 - gorm.io/gorm v1.25.2 + gorm.io/gorm v1.25.4 ) require ( diff --git a/go.sum b/go.sum index e0378322..e93efcf1 100644 --- a/go.sum +++ b/go.sum @@ -125,6 +125,7 @@ github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk5 github.com/alexflint/go-filemutex v0.0.0-20171022225611-72bdc8eae2ae/go.mod h1:CgnQgUtFrFz9mxFNtED3jI5tLDjKlOM+oUF/sTk6ps0= github.com/alexflint/go-filemutex v1.1.0/go.mod h1:7P4iRhttt/nUvUOrYIhcpMzv2G6CY9UnI16Z+UJqRyk= github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be h1:9AeTilPcZAjCFIImctFaOjnTIavg87rW78vTPkQqLI8= +github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be/go.mod h1:ySMOLuWl6zY27l47sB3qLNK6tF2fkHG55UZxx8oIVo4= github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= github.com/apache/arrow/go/arrow v0.0.0-20210818145353-234c94e4ce64/go.mod h1:2qMFB56yOP3KzkB3PbYZ4AlUFg3a88F67TIx5lB/WwY= github.com/apache/arrow/go/arrow v0.0.0-20211013220434-5962184e7a30/go.mod h1:Q7yQnSMnLvcXlZ8RV+jwz/6y1rQTqbX6C82SndT52Zs= @@ -133,6 +134,7 @@ github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5 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/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio= +github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY= github.com/avast/retry-go/v4 v4.5.0 h1:QoRAZZ90cj5oni2Lsgl2GW8mNTnUCnmpx/iKpwVisHg= github.com/avast/retry-go/v4 v4.5.0/go.mod h1:7hLEXp0oku2Nir2xBAsg0PTphp9z71bN5Aq1fboC3+I= @@ -401,6 +403,7 @@ github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25Kn github.com/edsrzf/mmap-go v0.0.0-20170320065105-0bce6a688712/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M= github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc= github.com/elazarl/goproxy v0.0.0-20221015165544-a0805db90819 h1:RIB4cRk+lBqKK3Oy0r2gRX4ui7tuhiZq2SuTtTCi0/0= +github.com/elazarl/goproxy v0.0.0-20221015165544-a0805db90819/go.mod h1:Ro8st/ElPeALwNFlcTpWmkr6IoMFfkjXAvTHpevnDsM= github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= github.com/emicklei/go-restful v2.9.5+incompatible/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc= @@ -439,6 +442,7 @@ github.com/getsentry/raven-go v0.2.0/go.mod h1:KungGk8q33+aIAZUIVWZDr2OfAEBsO49P 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/gzip v0.0.6 h1:NjcunTcGAj5CO1gn4N8jHOSIeRFHIbn51z6K+xaN4d4= +github.com/gin-contrib/gzip v0.0.6/go.mod h1:QOJlmV2xmayAjkNS2Y8NQsMneuRShOU/kjovCXNuzzk= 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/contrib v0.0.0-20201101042839-6a891bf89f19 h1:J2LPEOcQmWaooBnBtUDV9KHFEnP5LYTZY03GiQ0oQBw= @@ -446,6 +450,7 @@ github.com/gin-gonic/contrib v0.0.0-20201101042839-6a891bf89f19/go.mod h1:iqneQ2 github.com/gin-gonic/gin v1.9.1 h1:4idEAncQnU5cB7BeOkPtxjfCSye0AAm1R0RVIqJ+Jmg= github.com/gin-gonic/gin v1.9.1/go.mod h1:hPrL7YrpYKXt5YId3A/Tnip5kqbEAP+KLuI3SUcPTeU= github.com/gliderlabs/ssh v0.3.5 h1:OcaySEmAQJgyYcArR+gGGTHCyE7nvhEMTlYY+Dp8CpY= +github.com/gliderlabs/ssh v0.3.5/go.mod h1:8XB4KraRrX39qHhT6yxPsHedjA08I/uBVwj4xC+/+z4= github.com/go-fonts/dejavu v0.1.0/go.mod h1:4Wt4I4OU2Nq9asgDCteaAaWZOV24E+0/Pwo0gppep4g= github.com/go-fonts/latin-modern v0.2.0/go.mod h1:rQVLdDMK+mK1xscDwsqM5J8U2jrRa3T0ecnM9pNujks= github.com/go-fonts/liberation v0.1.1/go.mod h1:K6qoJYypsmfVjWg8KOVDQhLc8UDgIK2HYqyqAO9z7GY= @@ -455,6 +460,7 @@ github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376/go.mod h1:an3vInlBmS github.com/go-git/go-billy/v5 v5.4.1 h1:Uwp5tDRkPr+l/TnbHOQzp+tmJfLceOlbVucgpTz8ix4= github.com/go-git/go-billy/v5 v5.4.1/go.mod h1:vjbugF6Fz7JIflbVpl1hJsGjSHNltrSw45YK/ukIvQg= github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20230305113008-0c11038e723f h1:Pz0DHeFij3XFhoBRGUDPzSJ+w2UcK5/0JvF8DRI58r8= +github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20230305113008-0c11038e723f/go.mod h1:8LHG1a3SRW71ettAD/jW13h8c6AqjVSeL11RAdgaqpo= github.com/go-git/go-git/v5 v5.8.1 h1:Zo79E4p7TRk0xoRgMq0RShiTHGKcKI4+DI6BfJc/Q+A= github.com/go-git/go-git/v5 v5.8.1/go.mod h1:FHFuoD6yGz5OSKEBK+aWN9Oah0q54Jxl0abmj6GnqAo= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= @@ -502,6 +508,7 @@ github.com/go-openapi/swag v0.22.3/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+ github.com/go-openapi/swag v0.22.4 h1:QLMzNJnMGPRNDCbySlcj1x01tzU8/9LTTL9hZZZogBU= github.com/go-openapi/swag v0.22.4/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14= github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s= +github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA= github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY= github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY= @@ -565,7 +572,9 @@ github.com/golang-migrate/migrate/v4 v4.15.2 h1:vU+M05vs6jWHKDdmE1Ecwj0BznygFc4Q github.com/golang-migrate/migrate/v4 v4.15.2/go.mod h1:f2toGLkYqD3JH+Todi4aZ2ZdbeUNx4sIwiOK96rE9Lw= github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0= github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9 h1:au07oEsX2xN0ktxqI+Sida1w446QrXBRJ0nee3SNZlA= +github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0= github.com/golang-sql/sqlexp v0.1.0 h1:ZCD6MBpcuOVfGVqsEmY5/4FtYiKz6tSyUv9LPEDei6A= +github.com/golang-sql/sqlexp v0.1.0/go.mod h1:J4ad9Vo8ZCWQ2GMrC4UCQy1JpCbwU9m3EOqtpKwwwHI= github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= @@ -625,6 +634,7 @@ github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-containerregistry v0.5.1/go.mod h1:Ct15B4yir3PLOP5jsy0GNeYVaIZs/MK/Jz5any1wFW0= github.com/google/go-github/v39 v39.2.0/go.mod h1:C1s8C5aCC9L+JXIYpJM5GYytdX52vC1bLvHEF1IhBrE= github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= @@ -837,6 +847,7 @@ github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORN github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/pty v1.1.5/go.mod h1:9r2w37qlBe7rQ6e1fg1S/9xpWHSnaqNdHD3WcMdbPDA= github.com/kr/pty v1.1.8/go.mod h1:O1sed60cT9XZ5uDucP5qwvh+TE3NnUj51EiZO/lmSfw= @@ -898,12 +909,14 @@ github.com/mattn/go-sqlite3 v1.9.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOq github.com/mattn/go-sqlite3 v1.14.6/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= github.com/mattn/go-sqlite3 v1.14.10/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= github.com/mattn/go-sqlite3 v1.14.15 h1:vfoHhTN1af61xCRSWzFIWzx2YskyMTwHLrExkBOjvxI= +github.com/mattn/go-sqlite3 v1.14.15/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo= github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= github.com/maxbrunsfeld/counterfeiter/v6 v6.2.2/go.mod h1:eD9eIE7cdwcMi9rYluz88Jz2VyhSmden33/aXg4oVIY= github.com/microsoft/go-mssqldb v0.17.0 h1:Fto83dMZPnYv1Zwx5vHHxpNraeEaUlQ/hhHLgZiaenE= +github.com/microsoft/go-mssqldb v0.17.0/go.mod h1:OkoNGhGEs8EZqchVTtochlXruEhEOaO4S0d2sB5aeGQ= github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= github.com/miekg/pkcs11 v1.0.3/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WTFxgs= github.com/mistifyio/go-zfs v2.1.2-0.20190413222219-f784269be439+incompatible/go.mod h1:8AuVvqP/mXw1px98n46wfvcGfQ4ci2FwoAjKYxuo3Z4= @@ -1080,6 +1093,7 @@ github.com/rogpeppe/go-internal v1.1.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFR github.com/rogpeppe/go-internal v1.2.2/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8= +github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ= github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= github.com/rs/zerolog v1.13.0/go.mod h1:YbFCdg8HfsridGWAh22vktObvhZbQsZXe4/zB0OKkWU= @@ -1113,6 +1127,7 @@ 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.8.1/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/skeema/knownhosts v1.2.0 h1:h9r9cf0+u7wSE+M183ZtMGgOJKiL96brpaz5ekfJCpM= github.com/skeema/knownhosts v1.2.0/go.mod h1:g4fPeYpque7P0xefxtGzV81ihjC8sX2IqpAoNkjxbMo= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= @@ -1466,6 +1481,7 @@ golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E= +golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= golang.org/x/sys v0.0.0-20180224232135-f6cff0780e54/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= @@ -1607,6 +1623,7 @@ golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= golang.org/x/term v0.10.0 h1:3R7pNqamzBraeqj/Tj8qt1aQ2HpmlC+Cx/qL/7hn4/c= +golang.org/x/term v0.10.0/go.mod h1:lpqdcUyK/oCiQxvxVrppt5ggO2KCZ5QblwqPnfZ6d5o= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -1935,12 +1952,16 @@ gorm.io/driver/postgres v1.0.8/go.mod h1:4eOzrI1MUfm6ObJU/UcmbXyiHSs8jSwH95G5P5d gorm.io/driver/postgres v1.5.2 h1:ytTDxxEv+MplXOfFe3Lzm7SjG09fcdb3Z/c056DTBx0= gorm.io/driver/postgres v1.5.2/go.mod h1:fmpX0m2I1PKuR7mKZiEluwrP3hbs+ps7JIGMUBpCgl8= gorm.io/driver/sqlite v1.4.3 h1:HBBcZSDnWi5BW3B3rwvVTc510KGkBkexlOg0QrmLUuU= +gorm.io/driver/sqlite v1.4.3/go.mod h1:0Aq3iPO+v9ZKbcdiz8gLWRw5VOPcBOPUQJFLq5e2ecI= gorm.io/driver/sqlserver v1.4.1 h1:t4r4r6Jam5E6ejqP7N82qAJIJAht27EGT41HyPfXRw0= +gorm.io/driver/sqlserver v1.4.1/go.mod h1:DJ4P+MeZbc5rvY58PnmN1Lnyvb5gw5NPzGshHDnJLig= gorm.io/gorm v1.20.12/go.mod h1:0HFTzE/SqkGTzK6TlDPPQbAYCluiVvhzoA1+aVyzenw= gorm.io/gorm v1.21.4/go.mod h1:0HFTzE/SqkGTzK6TlDPPQbAYCluiVvhzoA1+aVyzenw= gorm.io/gorm v1.23.8/go.mod h1:l2lP/RyAtc1ynaTjFksBde/O8v9oOGIApu2/xRitmZk= gorm.io/gorm v1.25.2 h1:gs1o6Vsa+oVKG/a9ElL3XgyGfghFfkKA2SInQaCyMho= gorm.io/gorm v1.25.2/go.mod h1:L4uxeKpfBml98NYqVqwAdmV1a2nBtAec/cf3fpucW/k= +gorm.io/gorm v1.25.4 h1:iyNd8fNAe8W9dvtlgeRI5zSVZPsq3OpcTu37cYcpCmw= +gorm.io/gorm v1.25.4/go.mod h1:L4uxeKpfBml98NYqVqwAdmV1a2nBtAec/cf3fpucW/k= gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= gotest.tools/v3 v3.0.2/go.mod h1:3SzNCllyD9/Y+b5r9JIKQ474KzkZyqLqEfYqMsX94Bk= gotest.tools/v3 v3.0.3/go.mod h1:Z7Lb0S5l+klDB31fvDQX8ss/FlKDxtlFlw3Oa8Ymbl8=