From 4242f0ba2118359808b54b3cd91c8f2a5abb7b62 Mon Sep 17 00:00:00 2001 From: Artem Gavrilov Date: Mon, 9 Sep 2024 14:28:58 +0200 Subject: [PATCH 1/5] Migrate to buf schema v2 and move api related tasks to dedicated Makefile for PMM v3 (#3178) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Migrate to buf schema v2 and move api related tasks to dedicated Makefile * Hit CI --------- Co-authored-by: Jiří Čtvrtka <62988319+JiriCtvrtka@users.noreply.github.com> --- .github/workflows/main.yml | 2 +- Makefile.include | 135 ++------------------------- api/Makefile | 127 +++++++++++++++++++++++++ api/buf.gen.yaml | 34 +++++++ api/buf.lock | 20 ++-- api/buf.yaml | 37 +++++--- descriptor.bin => api/descriptor.bin | Bin buf.gen.yaml | 44 --------- buf.work.yaml | 3 - 9 files changed, 198 insertions(+), 204 deletions(-) create mode 100644 api/Makefile create mode 100644 api/buf.gen.yaml rename descriptor.bin => api/descriptor.bin (100%) delete mode 100644 buf.gen.yaml delete mode 100644 buf.work.yaml diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 7c1c51fab8..09de98cf79 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -68,7 +68,7 @@ jobs: - name: Update API compatibility descriptors run: | # log if descriptors changed, useful for "update descriptors" PRs - make descriptors + make -C api descriptors git diff --text - name: Run check-license diff --git a/Makefile.include b/Makefile.include index f329c5aa5d..615f32251b 100644 --- a/Makefile.include +++ b/Makefile.include @@ -1,5 +1,4 @@ -# vim: ts=8:sw=8:ft=make:noai:noet -SWAGGER_UI_VERSION?=latest + .PHONY: default init release gen test clean all default: help @@ -25,8 +24,8 @@ release: ## Build release versions of all components make -C qan-api2 release gen: clean ## Generate files - make gen-api - make clean_swagger + make -C api gen + make -C api clean-swagger make -C agent gen make -C admin gen @@ -38,129 +37,13 @@ gen: clean ## Generate files make format ## TODO: One formatting run is not enough, figure out why. go install -v ./... +clean: ## Remove generated files + make -C api clean + gen-mocks: find . -name mock_*.go -delete ./bin/mockery --config .mockery.yaml -gen-api: ## Generate PMM API - # generated by descriptors target - bin/buf breaking --against descriptor.bin api - - bin/buf generate -v api - - SPECS="\ - api/agentlocal/v1 \ - api/server/v1 \ - api/user/v1 \ - api/inventory/v1 \ - api/management/v1 \ - api/management/v1/service \ - api/actions/v1 \ - api/advisors/v1 \ - api/alerting/v1 \ - api/backup/v1 \ - api/dump/v1beta1 \ - api/accesscontrol/v1beta1 \ - api/qan/v1 \ - api/platform/v1"; \ - for API in $$SPECS; do \ - set -x ; \ - bin/swagger mixin $$API/json/header.json $$API/*.swagger.json --output=$$API/json/$$(basename $$API).json --keep-spec-order; \ - bin/swagger flatten --with-flatten=expand --with-flatten=remove-unused $$API/json/$$(basename $$API).json --output=$$API/json/$$(basename $$API).json ; \ - bin/swagger validate $$API/json/$$(basename $$API).json ; \ - bin/swagger generate client --with-flatten=expand --with-flatten=remove-unused --spec=$$API/json/$$(basename $$API).json --target=$$API/json \ - --additional-initialism=aws \ - --additional-initialism=db \ - --additional-initialism=ok \ - --additional-initialism=pmm \ - --additional-initialism=psmdb \ - --additional-initialism=pxc \ - --additional-initialism=pt \ - --additional-initialism=qan \ - --additional-initialism=rds \ - --additional-initialism=sql \ - --additional-initialism=ha ; \ - done - - # generate public API spec, omit agentlocal and inventory (always private), - # as well as a number of protos that are in beta (not v1 yet, they all go to a similar call below) - bin/swagger mixin --output=api/swagger/swagger.json \ - api/swagger/header.json \ - api/server/v1/json/v1.json \ - api/user/v1/json/v1.json \ - api/inventory/v1/json/v1.json \ - api/management/v1/json/v1.json \ - api/actions/v1/json/v1.json \ - api/alerting/v1/json/v1.json \ - api/advisors/v1/json/v1.json \ - api/backup/v1/json/v1.json \ - api/qan/v1/json/v1.json \ - api/platform/v1/json/v1.json - bin/swagger validate api/swagger/swagger.json - - bin/swagger-order --output=api/swagger/swagger.json api/swagger/swagger.json - - # generate API spec with all PMM Server APIs (omit agentlocal) - bin/swagger mixin --output=api/swagger/swagger-dev.json \ - api/swagger/header-dev.json \ - api/server/v1/json/v1.json \ - api/user/v1/json/v1.json \ - api/inventory/v1/json/v1.json \ - api/management/v1/json/v1.json \ - api/actions/v1/json/v1.json \ - api/alerting/v1/json/v1.json \ - api/advisors/v1/json/v1.json \ - api/backup/v1/json/v1.json \ - api/dump/v1beta1/json/v1beta1.json \ - api/accesscontrol/v1beta1/json/v1beta1.json \ - api/qan/v1/json/v1.json \ - api/platform/v1/json/v1.json - - bin/swagger validate api/swagger/swagger-dev.json - - bin/swagger-order --output=api/swagger/swagger-dev.json api/swagger/swagger-dev.json - -clean_swagger: - find api -name '*.swagger.json' -print -delete - - -ifeq ($(shell test "${SWAGGER_UI_VERSION}" = "latest" && echo 1 || echo 0), 1) -get_swagger_version: -override SWAGGER_UI_VERSION = $(shell curl --silent --head https://github.com/swagger-api/swagger-ui/releases/latest | grep -E '^[lL]ocation' | sed 's;^.*/;;') -else -get_swagger_version: -endif - -update-swagger: get_swagger_version ## Update Swagger UI in api/swagger, use `SWAGGER_UI_VERSION=xxx make update-swagger` to choose a version other than latest - curl --output /tmp/swagger.tar.gz -sSfL "https://github.com/swagger-api/swagger-ui/archive/refs/tags/${SWAGGER_UI_VERSION}.tar.gz" - tar xf /tmp/swagger.tar.gz --transform 's;swagger-ui-.*/dist/;api/swagger/;g' - rm -f api/swagger/.npmrc - sed -i 's/url: ".*"/url: "\/swagger.json",\n validatorUrl: "none"/' api/swagger/swagger-initializer.js - -clean: clean_swagger ## Remove generated files - find api -name '*.pb.go' -print -delete - find api -name '*.pb.gw.go' -print -delete - find api -name '*.validate.go' -print -delete - - SPECS="\ - api/agentlocal/v1 \ - api/server/v1 \ - api/user/v1 \ - api/inventory/v1 \ - api/management/v1 \ - api/actions/v1 \ - api/alerting/v1 \ - api/advisors/v1 \ - api/backup/v1 \ - api/dump/v1beta1 \ - api/accesscontrol/v1beta1 \ - api/qan/v1 \ - api/platform/v1"; \ - for API in $$SPECS; do \ - rm -fr $$API/json/client $$API/json/models $$API/json/$$(basename $$API).json ; \ - done - rm -f api/swagger/swagger.json api/swagger/swagger-dev.json - test-common: ## Run tests from API (and other shared) packages only (i.e it ignores directories that are explicitly listed) go test $(shell go list ./... | grep -v -e admin -e agent -e managed -e api-tests -e qan-api2 -e update) @@ -182,14 +65,10 @@ check-all: check-license check ## Run golangci linter to check for changes ag FILES = $(shell find . -type f -name '*.go') format: ## Format source code + make -C api format bin/gofumpt -l -w $(FILES) bin/goimports -local github.com/percona/pmm -l -w $(FILES) bin/gci write --section Standard --section Default --section "Prefix(github.com/percona/pmm)" $(FILES) - bin/buf format api -w serve: ## Serve API documentation with nginx nginx -p . -c api/nginx/nginx.conf - -descriptors: ## Update API compatibility descriptors - #./prototool break descriptor-set . -o api/api.descriptor - bin/buf build -o descriptor.bin --as-file-descriptor-set api diff --git a/api/Makefile b/api/Makefile new file mode 100644 index 0000000000..922866a671 --- /dev/null +++ b/api/Makefile @@ -0,0 +1,127 @@ +# vim: ts=8:sw=8:ft=make:noai:noet +SWAGGER_UI_VERSION?=latest + +gen: ## Generate PMM API + # generated by descriptors target + ../bin/buf breaking --against descriptor.bin . + + ../bin/buf generate -v . + + SPECS="\ + agentlocal/v1 \ + server/v1 \ + user/v1 \ + inventory/v1 \ + management/v1 \ + management/v1/service \ + actions/v1 \ + advisors/v1 \ + alerting/v1 \ + backup/v1 \ + dump/v1beta1 \ + accesscontrol/v1beta1 \ + qan/v1 \ + platform/v1"; \ + for API in $$SPECS; do \ + set -x ; \ + ../bin/swagger mixin $$API/json/header.json $$API/*.swagger.json --output=$$API/json/$$(basename $$API).json --keep-spec-order; \ + ../bin/swagger flatten --with-flatten=expand --with-flatten=remove-unused $$API/json/$$(basename $$API).json --output=$$API/json/$$(basename $$API).json ; \ + ../bin/swagger validate $$API/json/$$(basename $$API).json ; \ + ../bin/swagger generate client --with-flatten=expand --with-flatten=remove-unused --spec=$$API/json/$$(basename $$API).json --target=$$API/json \ + --additional-initialism=aws \ + --additional-initialism=db \ + --additional-initialism=ok \ + --additional-initialism=pmm \ + --additional-initialism=psmdb \ + --additional-initialism=pxc \ + --additional-initialism=pt \ + --additional-initialism=qan \ + --additional-initialism=rds \ + --additional-initialism=sql \ + --additional-initialism=ha ; \ + done + + # generate public API spec, omit agentlocal and inventory (always private), + # as well as a number of protos that are in beta (not v1 yet, they all go to a similar call below) + ../bin/swagger mixin --output=swagger/swagger.json \ + swagger/header.json \ + server/v1/json/v1.json \ + user/v1/json/v1.json \ + inventory/v1/json/v1.json \ + management/v1/json/v1.json \ + actions/v1/json/v1.json \ + alerting/v1/json/v1.json \ + advisors/v1/json/v1.json \ + backup/v1/json/v1.json \ + qan/v1/json/v1.json \ + platform/v1/json/v1.json + ../bin/swagger validate swagger/swagger.json + + ../bin/swagger-order --output=swagger/swagger.json swagger/swagger.json + + # generate API spec with all PMM Server APIs (omit agentlocal) + ../bin/swagger mixin --output=swagger/swagger-dev.json \ + swagger/header-dev.json \ + server/v1/json/v1.json \ + user/v1/json/v1.json \ + inventory/v1/json/v1.json \ + management/v1/json/v1.json \ + actions/v1/json/v1.json \ + alerting/v1/json/v1.json \ + advisors/v1/json/v1.json \ + backup/v1/json/v1.json \ + dump/v1beta1/json/v1beta1.json \ + accesscontrol/v1beta1/json/v1beta1.json \ + qan/v1/json/v1.json \ + platform/v1/json/v1.json + + ../bin/swagger validate swagger/swagger-dev.json + + ../bin/swagger-order --output=swagger/swagger-dev.json swagger/swagger-dev.json + +format: ## Format API definitions + ../bin/buf format . -w + +clean-swagger: + find . -name '*.swagger.json' -print -delete + + +ifeq ($(shell test "${SWAGGER_UI_VERSION}" = "latest" && echo 1 || echo 0), 1) +get_swagger_version: +override SWAGGER_UI_VERSION = $(shell curl --silent --head https://github.com/swagger-api/swagger-ui/releases/latest | grep -E '^[lL]ocation' | sed 's;^.*/;;') +else +get_swagger_version: +endif + +update-swagger: get_swagger_version ## Update Swagger UI in swagger, use `SWAGGER_UI_VERSION=xxx make update-swagger` to choose a version other than latest + curl --output /tmp/swagger.tar.gz -sSfL "https://github.com/swagger-api/swagger-ui/archive/refs/tags/${SWAGGER_UI_VERSION}.tar.gz" + tar xf /tmp/swagger.tar.gz --transform 's;swagger-ui-.*/dist/;swagger/;g' + rm -f swagger/.npmrc + sed -i 's/url: ".*"/url: "\/swagger.json",\n validatorUrl: "none"/' swagger/swagger-initializer.js + +clean: clean-swagger ## Remove generated files + find . -name '*.pb.go' -print -delete + find . -name '*.pb.gw.go' -print -delete + find . -name '*.validate.go' -print -delete + + SPECS="\ + agentlocal/v1 \ + server/v1 \ + user/v1 \ + inventory/v1 \ + management/v1 \ + actions/v1 \ + alerting/v1 \ + advisors/v1 \ + backup/v1 \ + dump/v1beta1 \ + accesscontrol/v1beta1 \ + qan/v1 \ + platform/v1"; \ + for API in $$SPECS; do \ + rm -fr $$API/json/client $$API/json/models $$API/json/$$(basename $$API).json ; \ + done + rm -f swagger/swagger.json swagger/swagger-dev.json + +descriptors: ## Update API compatibility descriptors + ../bin/buf build -o descriptor.bin --as-file-descriptor-set . \ No newline at end of file diff --git a/api/buf.gen.yaml b/api/buf.gen.yaml new file mode 100644 index 0000000000..b412cc9f32 --- /dev/null +++ b/api/buf.gen.yaml @@ -0,0 +1,34 @@ +version: v2 +managed: + enabled: true + disable: + - file_option: go_package + module: buf.build/googleapis/googleapis + - file_option: go_package + module: buf.build/grpc-ecosystem/grpc-gateway + - file_option: go_package + module: buf.build/envoyproxy/protoc-gen-validate + override: + - file_option: go_package_prefix + value: github.com/percona/pmm/api +plugins: + - local: ../bin/protoc-gen-go + out: . + opt: paths=source_relative + - local: ../bin/protoc-gen-go-grpc + out: . + opt: paths=source_relative + - local: ../bin/protoc-gen-grpc-gateway + out: . + opt: paths=source_relative + - local: ../bin/protoc-gen-validate + out: . + opt: + - paths=source_relative + - lang=go + - local: ../bin/protoc-gen-openapiv2 + out: . + opt: + - simple_operation_ids=true + - json_names_for_fields=false + - proto3_optional_nullable=true diff --git a/api/buf.lock b/api/buf.lock index 66753d27f3..0e9cebedcf 100644 --- a/api/buf.lock +++ b/api/buf.lock @@ -1,18 +1,12 @@ # Generated by buf. DO NOT EDIT. -version: v1 +version: v2 deps: - - remote: buf.build - owner: envoyproxy - repository: protoc-gen-validate + - name: buf.build/envoyproxy/protoc-gen-validate commit: eac44469a7af47e7839a7f1f3d7ac004 - digest: shake256:0feabcde01b6b11e3c75a5e3f807968d5995626546f39c37e5d4205892b3a59cced0ed83b35a2eb9e6dddd3309660ad46b737c9dcd224b425de0a6654ce04417 - - remote: buf.build - owner: googleapis - repository: googleapis + digest: b5:2ef7b25d9671fde82d58278e94d209788fb6a42936cc2d60e42303b67dcdb72b2d0e121238ba44caf1870a34edab55518df5d3f1ee1e62b8d9b6cf98817eae6e + - name: buf.build/googleapis/googleapis commit: 28151c0d0a1641bf938a7672c500e01d - digest: shake256:49215edf8ef57f7863004539deff8834cfb2195113f0b890dd1f67815d9353e28e668019165b9d872395871eeafcbab3ccfdb2b5f11734d3cca95be9e8d139de - - remote: buf.build - owner: grpc-ecosystem - repository: grpc-gateway + digest: b5:93b70089baa4fc05a92d3e52db91a4b7812db3b57b9664f6cb301733938cb630e377a938e8a56779388171c749c1d42a2e9a6c6230f2ff45f127a8102a6a27d0 + - name: buf.build/grpc-ecosystem/grpc-gateway commit: 3f42134f4c564983838425bc43c7a65f - digest: shake256:3d11d4c0fe5e05fda0131afefbce233940e27f0c31c5d4e385686aea58ccd30f72053f61af432fa83f1fc11cda57f5f18ca3da26a29064f73c5a0d076bba8d92 + digest: b5:291b947d8ac09492517557e4e72e294788cb8201afc7d0df7bda80fa10931adb60d4d669208a7696bf24f1ecb2a33a16d4c1e766e6f31809248b00343119569b diff --git a/api/buf.yaml b/api/buf.yaml index 84e841ca3e..b130c4ee02 100644 --- a/api/buf.yaml +++ b/api/buf.yaml @@ -1,21 +1,28 @@ -version: v1 -breaking: - use: - - FILE +version: v2 +modules: + - path: . +deps: + - buf.build/envoyproxy/protoc-gen-validate + - buf.build/googleapis/googleapis + - buf.build/grpc-ecosystem/grpc-gateway lint: use: - DEFAULT + except: + - FIELD_NOT_REQUIRED + - PACKAGE_NO_IMPORT_CYCLE ignore_only: + PACKAGE_VERSION_SUFFIX: + - api/common/common.proto + - api/common/metrics_resolutions.proto RPC_REQUEST_STANDARD_NAME: - - agent/v1/agent.proto # We want our naming in this file to be different + - api/agent/v1/agent.proto RPC_RESPONSE_STANDARD_NAME: - - agent/v1/agent.proto # We want our naming in this file to be different - PACKAGE_VERSION_SUFFIX: - - common/common.proto # We don't want to version this file - - common/metrics_resolutions.proto # We don't want to version this file - - -deps: - - buf.build/googleapis/googleapis - - buf.build/grpc-ecosystem/grpc-gateway - - buf.build/envoyproxy/protoc-gen-validate + - api/agent/v1/agent.proto + disallow_comment_ignores: true +breaking: + use: + - FILE + except: + - EXTENSION_NO_DELETE + - FIELD_SAME_DEFAULT diff --git a/descriptor.bin b/api/descriptor.bin similarity index 100% rename from descriptor.bin rename to api/descriptor.bin diff --git a/buf.gen.yaml b/buf.gen.yaml deleted file mode 100644 index 53d088dcf4..0000000000 --- a/buf.gen.yaml +++ /dev/null @@ -1,44 +0,0 @@ -version: v1 -managed: - enabled: true - go_package_prefix: - default: github.com/percona/pmm/api - except: - - buf.build/googleapis/googleapis - - buf.build/grpc-ecosystem/grpc-gateway - - buf.build/envoyproxy/protoc-gen-validate - -plugins: - - name: go - path: bin/protoc-gen-go - out: api - opt: - - paths=source_relative - - - name: go-grpc - path: bin/protoc-gen-go-grpc - out: api - opt: - - paths=source_relative - - - name: grpc-gateway - path: bin/protoc-gen-grpc-gateway - out: api - opt: - - paths=source_relative - - - name: validate - path: bin/protoc-gen-validate - out: api - opt: - - paths=source_relative - - lang=go - - - name: openapiv2 - out: api - path: bin/protoc-gen-openapiv2 - opt: - - simple_operation_ids=true - - json_names_for_fields=false - - proto3_optional_nullable=true - # - visibility_restriction_selectors=INTERNAL # Uncomment to show elements marked up with `INTERNAL` diff --git a/buf.work.yaml b/buf.work.yaml deleted file mode 100644 index a2fa5f5176..0000000000 --- a/buf.work.yaml +++ /dev/null @@ -1,3 +0,0 @@ -version: v1 -directories: - - api From 5561f584c01297523d401b087c6c701c675ed3b2 Mon Sep 17 00:00:00 2001 From: Michael Okoko <10512379+idoqo@users.noreply.github.com> Date: Wed, 11 Sep 2024 11:14:16 +0100 Subject: [PATCH 2/5] PMM-13077 list change log for PMM server version (#3045) * Support release notes for PMM versions This adds support for PMM release notes by fetching the correct markdown files from github. It also includes fixes for api tests by accepting v3 prefixes in versions. * use separate endpoint for listing versions * replace dockerhub/github with version service endpoints * fix tests * use better naming for rpc * drop todo * use check dev for version service * fix method name for changelogs * include release notes text in response --- api-tests/server/updates_test.go | 36 + api/descriptor.bin | Bin 703985 -> 705189 bytes .../server_service/check_updates_responses.go | 6 + .../list_change_logs_parameters.go | 127 +++ .../list_change_logs_responses.go | 561 +++++++++++ .../server_service/server_service_client.go | 41 + api/server/v1/json/v1.json | 105 ++ api/server/v1/server.pb.go | 898 +++++++++++------- api/server/v1/server.pb.gw.go | 65 ++ api/server/v1/server.pb.validate.go | 271 ++++++ api/server/v1/server.proto | 22 + api/server/v1/server_grpc.pb.go | 39 + api/swagger/swagger-dev.json | 105 ++ api/swagger/swagger.json | 105 ++ docker-compose.yml | 3 +- managed/services/server/server.go | 32 +- managed/services/server/updater.go | 213 +++-- managed/services/server/updater_test.go | 109 ++- version/update.go | 21 +- 19 files changed, 2291 insertions(+), 468 deletions(-) create mode 100644 api/server/v1/json/client/server_service/list_change_logs_parameters.go create mode 100644 api/server/v1/json/client/server_service/list_change_logs_responses.go diff --git a/api-tests/server/updates_test.go b/api-tests/server/updates_test.go index 97ad81d822..e8ecd0c01b 100644 --- a/api-tests/server/updates_test.go +++ b/api-tests/server/updates_test.go @@ -71,6 +71,15 @@ func TestCheckUpdates(t *testing.T) { assert.NotEmpty(t, res.Payload.Installed.FullVersion) if res.Payload.UpdateAvailable { + require.NotEmpty(t, res.Payload.Latest) + assert.True(t, strings.HasPrefix(res.Payload.Latest.Version, "2.") || strings.HasPrefix(res.Payload.Installed.Version, "3."), + "latest.version = %q should have '2.' or '3.' prefix", res.Payload.Latest.Version) + require.NotEmpty(t, res.Payload.Latest.Timestamp) + ts = time.Time(res.Payload.Latest.Timestamp) + hour, min, _ = ts.Clock() + assert.Zero(t, hour, "latest.timestamp should contain only date") + assert.Zero(t, min, "latest.timestamp should contain only date") + assert.NotEmpty(t, res.Payload.Latest.Tag) require.NotEmpty(t, res.Payload.Latest.Timestamp) ts = time.Time(res.Payload.Latest.Timestamp) @@ -81,6 +90,7 @@ func TestCheckUpdates(t *testing.T) { assert.NotEqual(t, res.Payload.Installed.FullVersion, res.Payload.Latest.Version) assert.NotEqual(t, res.Payload.Installed.Timestamp, res.Payload.Latest.Timestamp) assert.True(t, strings.HasPrefix(res.Payload.LatestNewsURL, "https://per.co.na/pmm/2."), "latest_news_url = %q", res.Payload.LatestNewsURL) + assert.True(t, strings.HasPrefix(res.Payload.Latest.ReleaseNotesURL, "https://per.co.na/pmm/2."), "latest_news_url = %q", res.Payload.Latest.ReleaseNotesURL) } assert.NotEmpty(t, res.Payload.LastCheck) @@ -110,6 +120,32 @@ func TestCheckUpdates(t *testing.T) { }) } +func TestListUpdates(t *testing.T) { + const fast, slow = 5 * time.Second, 60 * time.Second + + if !pmmapitests.RunUpdateTest { + t.Skip("skipping PMM Server check update test") + } + + version, err := serverClient.Default.ServerService.Version(server.NewVersionParamsWithTimeout(fast)) + require.NoError(t, err) + if version.Payload.Server == nil || version.Payload.Server.Version == "" { + t.Skip("skipping test in developer's environment") + } + + params := &server.ListChangeLogsParams{ + Context: pmmapitests.Context, + } + params.SetTimeout(slow) + res, err := serverClient.Default.ServerService.ListChangeLogs(params) + require.NoError(t, err) + + if len(res.Payload.Updates) > 0 { + assert.True(t, strings.HasPrefix(res.Payload.Updates[0].Version, "3."), + "installed.version = %q should have '3.' prefix", res.Payload.Updates[0].Version) + } +} + func TestUpdate(t *testing.T) { // do not run this test in parallel with other tests diff --git a/api/descriptor.bin b/api/descriptor.bin index b6d43848715709a2fac2d22b535e79564fab075a..140f0af2728968e990965d413afe506aa707bb19 100644 GIT binary patch delta 6237 zcmb_geQ;FO72k9Bd~6=s5H}w@zC!{ek&l8(2N3BfV4Vom(pn~xl|({9lQmW; zT`Ca;1PmZgngAkDiWDtF5l0=tQHD~6VVHEZGYC>d+tj<{=8=YBeko0s7LgKd#s+k9=j*f6YYupQqH8{21cea&TE>*`Gi_F69Y+umX=8TojSA8?-A7sk% zlyl-*=lQT7|75u=q3mFpoZH%!xw)mOeQA1b$I`CG^!M*icV&icAX)m~D_tu(+Pl)u zWEr`CMROCfmXRB-j$dCfzAN3?o$egp-7tPu$C72~&V}jDuGWtBTifsLX!M<(sZzEz zb!8SWX-O|xRwke;?k!Eo%Hvnt<;u7?QFwgiL-PJ`?I9rxzna={ugP%jl2^D|mS(TD za0OcDumRdK<5_a<7KTU2lzOrz^`g0_yO$1ksvyM_GV zn=<0$g+k8>ui>~X@pi6@#E-wQT4o}2yI1>|d_Ox~T2@qqo$wqnBsIZp)ThW*r^sE< zIM=0X0woOUM`!3Z1ZB}CYyz9^QwkODTNhttUE&AA^Z+oF?ih(t&o$UA|^skxKUK3 zys7Ktq?$%ipvW-8sj+adj}WRcRW2te3YO-3PqF`eG01oj8%uPdF+uR3k3zq${Dl)< z=zY3QPOn)gY~wHBzcAv*=e{pQ{8`E$;4ZIey_{WhmnkhK!tlQF#Ky>QLOV7KhThLvh#_ zN2}x*gpYHFn#7n?g{v+`$2Gg|n&W0RKR!)_pruLZvjC>I^-gQxsyo6DdZ(xsX$2yoHZTw;sQd zB4bhj!7pP{03k)jq$uRJb*mJ&;x|~`ITp9AJICU-b%Pa$h9W2L!O&{bB8uSlAnw92 zh$vzaE4_k^vg+&jjh$R+b`l7|SH_D~+kn7Y>FA>dgy1W2&!(stSX$+^Zj=-2i4q)9UKg-Y7GREzx&XocE($Al z?2Q!K=DoXF-Z_}-Du(k$!dc;F6?0viy?IZ_5fktmVK@6>0pYos%Ezjb01I-QFw5O)M5%$JT(yb!-h1avfVa z;S|*2IJQTj7rdrkIbo0kM~|WjITjHeu3?9FpjTE;!0$W&!jAK{0K#(zMM`~$kUQwQ zl&Znue0`qSBFAL$8^peV$Tjp)q|6YxhCafS%vTvvLqCaeW|7MPEb$?z{gl+@JA%vT z=khfbXeWvB#y1QqU{)U^hetDT`51p$d5;}uxRzt>B9SzUc&`{neF*9Mj~o zVyN)lO=6^3L~9sIAJ(g7+)3TFJcQa!j_X5&+D*ep$XZoAB=7OQy;Y7zyKNBn1YNU1 z+!M6h25}F!`+JHQajd=G(XDb3h!GI?2I37$AjpW98xRk?CdNQKKvk}+Q$*=l z2ffGoWG#pi1s@FBj)xAgwAK(MhzDtWy_}?oc=`@`jZex35aY;rD3FSm5HR9*H4fq- z8a`59uZVbo4tp;=DaV7D58~l~hzAKUQeiUYgLs&R3{{^#j=)>~EIDWT62oDu3I-%u?I zM1&^oK{Q(UK>g)b=0%TV* z(0r-zqMhbFb5(Rqv@;||q?}yzwsdEvwS8$Wd<5a);)mz4cP7|I9(!jf zF~n%$v3G`s4Oi1EnI|y!&U$X295pj3q6l<02*hLXY|u|0gJ;PZVFK|OJWKc@=4qA` z7=!2ZG{bLnM z`tjFEQsg7fKoEy#=0FgKXXXGU^vHrU;tcS};tO5s*l$wkx8_2Z!t+hSUnqQcO8G*+ z<%xMbYn&b)zhn zF6n&d|BkFbk_}!&IcU&uZ|a-mW!9Q!hfe|nWq z%LUoXWUH?QxC$^YQ(3){$)oTx-8kQeQ2ilUw;0vJs8%MeTAL8$Lvn96sxb!bkI4E* zPPI^~jVU4PSR>m&`b(4bL1 z1nUYl+~Pxs{xmosVIx|Zv}kQYkWYgH5{Br1k@a~_bXbWtri9G0Xtsg&8QE1vG+U7V z-(*jdg-SHyTqV&X!bT3y`Kx5Bw+A6C@UK#`#$N^bDovW>Lumh!tl6gFmeCGVcDB^w zwGC0eBzKnSI9?iiwXoLUqhFtHONlooeU#Y*){lkVY_zil=^qw$i~O3>p6A$Wh1e{@ zsnPD8nWoOn0`;Fp7yqF1s-KZnS$=8O3R`_8qnJDdTr2d-no2Q~B!`JAqNQPl&^wwO>xj^839{BbYxGwrh4m+prS{f}P-KHyjk!&vO+; bRYk_6cY;mO^el%8EC_z+_$T}27lZ!;aD0!8 delta 5064 zcmYjUdvKK172k9B+q=7G^H{!3cqAcg2n0xYgz_k;bO05tIF2IH5vvRxM0_Bkbr?#= zMTxP935g-SA`=6p6lJs(ETj|}hM~0LjDvm6V6`pw32p75t!*9b<9F`8-+uikv%hoC z?{|OaKFukF zw>-!-G*s~rKa^9w6+@40;zyH1O`CZ@WiQ^q=`fW@JZDx+N!6Nxt?As*AD`ear|Aas z#i#k=SY{Pu!{Elm7l@gYL6*YgjhP0X%|Vb=i7i07jfhYZ zsIH!8*nAA#tj5%}m~~w|+I-N-X)}O7?O8=yh6pH6Y}z_G&;-TkSnm$S$q19!mHP)|xU)Jgh0R#KRizp)w5aPdw~A zR3hts9KNyeP$?ePs$yMj@#cru-ShC>k33R*VBI~%2kw3F?nkDwU0dW}H`l5%!klY! z!?ETp41`J7Hjd#rRvbg?%q_h<(|o+0TX>=k;^?h6hkJQkd!)yMNa zQ-Qgu%#55! z0AY8f2tZ_RqxA3yLUJ38sYgJB<6~RxJgoUJ8p5gj6pzkK;C5 zJS_K_C59(pxiyG=@v3PM`{L!+Aoj^}-(`vEFz7cg8(t1#8pQtCd>X`l%8u|era|l{ zJOploGhtxN+~;`W?7Yf=XyO?&AR590;+$tdG*s8Xt#(Gde>+JvnTA1b#-v$rfuj|} ziwKyl_uMSFJE^hA(<~S7!!GmqAh&_YsCies@^~%)hqrkmgSd;Pw(~4Y#7i(>7VqTg zAm%XRK?gSam?fPMp5Hc$=XJ~1%Q8pwyiesk+Co{Jlp2XTMA zJ95eQ6P|jvvw0Br6Iz@+Z^Odi03}A_y-o(hkavL4n=3F7hWcene4EG)g&2C7(Cp;u zh0-TpA>{;tu&03T4umD!Dqf*n!On+a%=Zf6DHGX3s9&YT54~&wvaeD`I(!fmMD`%5 zX3GP@G6FhTKooV5a@El&s0S(E7(q;OkebGFMafEG^iXt53yL5G7)eQoIuuJuhdM-g zcb1S0sY7x}ohfvv*P;$pu#FbbbtphkUyC{vAgKA*q(wbJ)&}rlGirbzD;1Pi<@^Hv!VL`g{QFGS|T)z;%p>s6Wk@j^oUQ%ga zN8{a*_H|Ttr)YK1zK)q=FK`2N($F~;>qs{{7VAhiJ4X32-kx-`V>GteHl>0>H#=@d z4RQ-~GSE35>qv7u9xstJx8oF!^E%Spj?;vRwm}sXn%fE2pzs?-o`@P0Ac!ZT1_cP> z329I*wh(l-ljhfhJQfBR22REX7zR$pg-D}2N%_ctG`f>CVG>WWI%ssK%+UKI_P_+&4JzcZZD_`=$wvqqz#^qb)*fRro8Jy zNQTa7=|XZxYeM}7CEoORv<8`PP^QsdhZ?z~XQHbQgw+CcrwI_bXXNJBNvi>d>>0WG z*Rj%xP`^d^FKg8vUKGAXnOgY=N++PG&yxDNd3_JhDxD==DVrp5+`O|?WjnP%Xq}}A zv!hXz_cjGr@-WWIXz=QruaEVikhvU!$lFw$%hgUZ2=$LC_!(*N(l+VYOgWV2_Kc5# z_7l=0InPl9)Blw8bbbRj8%Y%EbEJM{c7KC^R60l6_9cmfdCoTzfuNnEwyV5rX+-Z( zaD{hG-n9)m*DeH+cc?hWy9P`Df`VU`T~i>geaO3(7-;X3o&a@mEsSU-dkov0`wT~B-F5ny4 z+e(6XfeI}V1nUA#zczv}eK9^DNpISQoM{(=$i?`8Bw_kb6ns!NowTNX$S<|TK>IW4 zMsHdonEo%M=kaH)Y3N)c^$D3X-{R>dY0;NR+s{H&6o7rnwkldT zJ3JKZ;SQYlDCpd~Ad38mbPNA~4DI!Aavs3Y(1g$Y+h&! z(xL8D>KSw9MV?oZ7pqg1cSwWWsoaBs+T{W3RM;Wcn&k0&N(EQ>3!(klvLRQD3qj;5 zRlLG416cZND%e)`t*vhxnxXx=OANHFs=N~t!SqinJy*W<;3ggFZl#R*-b*~EBu`|w z()No)#z5{?wXNQ%yqMi;)?#k~udUvW8wLyRXr=v5_@FcIf?)P2UGzKQV%UjZRX$px jc152GzFw{ 0 { + return errors.CompositeValidationError(res...) + } + return nil +} diff --git a/api/server/v1/json/client/server_service/list_change_logs_responses.go b/api/server/v1/json/client/server_service/list_change_logs_responses.go new file mode 100644 index 0000000000..72af20d2a8 --- /dev/null +++ b/api/server/v1/json/client/server_service/list_change_logs_responses.go @@ -0,0 +1,561 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package server_service + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "context" + "fmt" + "io" + "strconv" + + "github.com/go-openapi/errors" + "github.com/go-openapi/runtime" + "github.com/go-openapi/strfmt" + "github.com/go-openapi/swag" + "github.com/go-openapi/validate" +) + +// ListChangeLogsReader is a Reader for the ListChangeLogs structure. +type ListChangeLogsReader struct { + formats strfmt.Registry +} + +// ReadResponse reads a server response into the received o. +func (o *ListChangeLogsReader) ReadResponse(response runtime.ClientResponse, consumer runtime.Consumer) (interface{}, error) { + switch response.Code() { + case 200: + result := NewListChangeLogsOK() + if err := result.readResponse(response, consumer, o.formats); err != nil { + return nil, err + } + return result, nil + default: + result := NewListChangeLogsDefault(response.Code()) + if err := result.readResponse(response, consumer, o.formats); err != nil { + return nil, err + } + if response.Code()/100 == 2 { + return result, nil + } + return nil, result + } +} + +// NewListChangeLogsOK creates a ListChangeLogsOK with default headers values +func NewListChangeLogsOK() *ListChangeLogsOK { + return &ListChangeLogsOK{} +} + +/* +ListChangeLogsOK describes a response with status code 200, with default header values. + +A successful response. +*/ +type ListChangeLogsOK struct { + Payload *ListChangeLogsOKBody +} + +func (o *ListChangeLogsOK) Error() string { + return fmt.Sprintf("[GET /v1/server/updates/changelogs][%d] listChangeLogsOk %+v", 200, o.Payload) +} + +func (o *ListChangeLogsOK) GetPayload() *ListChangeLogsOKBody { + return o.Payload +} + +func (o *ListChangeLogsOK) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error { + o.Payload = new(ListChangeLogsOKBody) + + // response payload + if err := consumer.Consume(response.Body(), o.Payload); err != nil && err != io.EOF { + return err + } + + return nil +} + +// NewListChangeLogsDefault creates a ListChangeLogsDefault with default headers values +func NewListChangeLogsDefault(code int) *ListChangeLogsDefault { + return &ListChangeLogsDefault{ + _statusCode: code, + } +} + +/* +ListChangeLogsDefault describes a response with status code -1, with default header values. + +An unexpected error response. +*/ +type ListChangeLogsDefault struct { + _statusCode int + + Payload *ListChangeLogsDefaultBody +} + +// Code gets the status code for the list change logs default response +func (o *ListChangeLogsDefault) Code() int { + return o._statusCode +} + +func (o *ListChangeLogsDefault) Error() string { + return fmt.Sprintf("[GET /v1/server/updates/changelogs][%d] ListChangeLogs default %+v", o._statusCode, o.Payload) +} + +func (o *ListChangeLogsDefault) GetPayload() *ListChangeLogsDefaultBody { + return o.Payload +} + +func (o *ListChangeLogsDefault) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error { + o.Payload = new(ListChangeLogsDefaultBody) + + // response payload + if err := consumer.Consume(response.Body(), o.Payload); err != nil && err != io.EOF { + return err + } + + return nil +} + +/* +ListChangeLogsDefaultBody list change logs default body +swagger:model ListChangeLogsDefaultBody +*/ +type ListChangeLogsDefaultBody struct { + // code + Code int32 `json:"code,omitempty"` + + // message + Message string `json:"message,omitempty"` + + // details + Details []*ListChangeLogsDefaultBodyDetailsItems0 `json:"details"` +} + +// Validate validates this list change logs default body +func (o *ListChangeLogsDefaultBody) Validate(formats strfmt.Registry) error { + var res []error + + if err := o.validateDetails(formats); err != nil { + res = append(res, err) + } + + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} + +func (o *ListChangeLogsDefaultBody) validateDetails(formats strfmt.Registry) error { + if swag.IsZero(o.Details) { // not required + return nil + } + + for i := 0; i < len(o.Details); i++ { + if swag.IsZero(o.Details[i]) { // not required + continue + } + + if o.Details[i] != nil { + if err := o.Details[i].Validate(formats); err != nil { + if ve, ok := err.(*errors.Validation); ok { + return ve.ValidateName("ListChangeLogs default" + "." + "details" + "." + strconv.Itoa(i)) + } else if ce, ok := err.(*errors.CompositeError); ok { + return ce.ValidateName("ListChangeLogs default" + "." + "details" + "." + strconv.Itoa(i)) + } + return err + } + } + + } + + return nil +} + +// ContextValidate validate this list change logs default body based on the context it is used +func (o *ListChangeLogsDefaultBody) ContextValidate(ctx context.Context, formats strfmt.Registry) error { + var res []error + + if err := o.contextValidateDetails(ctx, formats); err != nil { + res = append(res, err) + } + + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} + +func (o *ListChangeLogsDefaultBody) contextValidateDetails(ctx context.Context, formats strfmt.Registry) error { + for i := 0; i < len(o.Details); i++ { + if o.Details[i] != nil { + if err := o.Details[i].ContextValidate(ctx, formats); err != nil { + if ve, ok := err.(*errors.Validation); ok { + return ve.ValidateName("ListChangeLogs default" + "." + "details" + "." + strconv.Itoa(i)) + } else if ce, ok := err.(*errors.CompositeError); ok { + return ce.ValidateName("ListChangeLogs default" + "." + "details" + "." + strconv.Itoa(i)) + } + return err + } + } + } + + return nil +} + +// MarshalBinary interface implementation +func (o *ListChangeLogsDefaultBody) MarshalBinary() ([]byte, error) { + if o == nil { + return nil, nil + } + return swag.WriteJSON(o) +} + +// UnmarshalBinary interface implementation +func (o *ListChangeLogsDefaultBody) UnmarshalBinary(b []byte) error { + var res ListChangeLogsDefaultBody + if err := swag.ReadJSON(b, &res); err != nil { + return err + } + *o = res + return nil +} + +/* +ListChangeLogsDefaultBodyDetailsItems0 `Any` contains an arbitrary serialized protocol buffer message along with a +// URL that describes the type of the serialized message. +// +// Protobuf library provides support to pack/unpack Any values in the form +// of utility functions or additional generated methods of the Any type. +// +// Example 1: Pack and unpack a message in C++. +// +// Foo foo = ...; +// Any any; +// any.PackFrom(foo); +// ... +// if (any.UnpackTo(&foo)) { +// ... +// } +// +// Example 2: Pack and unpack a message in Java. +// +// Foo foo = ...; +// Any any = Any.pack(foo); +// ... +// if (any.is(Foo.class)) { +// foo = any.unpack(Foo.class); +// } +// // or ... +// if (any.isSameTypeAs(Foo.getDefaultInstance())) { +// foo = any.unpack(Foo.getDefaultInstance()); +// } +// +// Example 3: Pack and unpack a message in Python. +// +// foo = Foo(...) +// any = Any() +// any.Pack(foo) +// ... +// if any.Is(Foo.DESCRIPTOR): +// any.Unpack(foo) +// ... +// +// Example 4: Pack and unpack a message in Go +// +// foo := &pb.Foo{...} +// any, err := anypb.New(foo) +// if err != nil { +// ... +// } +// ... +// foo := &pb.Foo{} +// if err := any.UnmarshalTo(foo); err != nil { +// ... +// } +// +// The pack methods provided by protobuf library will by default use +// 'type.googleapis.com/full.type.name' as the type URL and the unpack +// methods only use the fully qualified type name after the last '/' +// in the type URL, for example "foo.bar.com/x/y.z" will yield type +// name "y.z". +// +// JSON +// ==== +// The JSON representation of an `Any` value uses the regular +// representation of the deserialized, embedded message, with an +// additional field `@type` which contains the type URL. Example: +// +// package google.profile; +// message Person { +// string first_name = 1; +// string last_name = 2; +// } +// +// { +// "@type": "type.googleapis.com/google.profile.Person", +// "firstName": , +// "lastName": +// } +// +// If the embedded message type is well-known and has a custom JSON +// representation, that representation will be embedded adding a field +// `value` which holds the custom JSON in addition to the `@type` +// field. Example (for message [google.protobuf.Duration][]): +// +// { +// "@type": "type.googleapis.com/google.protobuf.Duration", +// "value": "1.212s" +// } +swagger:model ListChangeLogsDefaultBodyDetailsItems0 +*/ +type ListChangeLogsDefaultBodyDetailsItems0 struct { + // A URL/resource name that uniquely identifies the type of the serialized + // protocol buffer message. This string must contain at least + // one "/" character. The last segment of the URL's path must represent + // the fully qualified name of the type (as in + // `path/google.protobuf.Duration`). The name should be in a canonical form + // (e.g., leading "." is not accepted). + // + // In practice, teams usually precompile into the binary all types that they + // expect it to use in the context of Any. However, for URLs which use the + // scheme `http`, `https`, or no scheme, one can optionally set up a type + // server that maps type URLs to message definitions as follows: + // + // * If no scheme is provided, `https` is assumed. + // * An HTTP GET on the URL must yield a [google.protobuf.Type][] + // value in binary format, or produce an error. + // * Applications are allowed to cache lookup results based on the + // URL, or have them precompiled into a binary to avoid any + // lookup. Therefore, binary compatibility needs to be preserved + // on changes to types. (Use versioned type names to manage + // breaking changes.) + // + // Note: this functionality is not currently available in the official + // protobuf release, and it is not used for type URLs beginning with + // type.googleapis.com. As of May 2023, there are no widely used type server + // implementations and no plans to implement one. + // + // Schemes other than `http`, `https` (or the empty scheme) might be + // used with implementation specific semantics. + AtType string `json:"@type,omitempty"` +} + +// Validate validates this list change logs default body details items0 +func (o *ListChangeLogsDefaultBodyDetailsItems0) Validate(formats strfmt.Registry) error { + return nil +} + +// ContextValidate validates this list change logs default body details items0 based on context it is used +func (o *ListChangeLogsDefaultBodyDetailsItems0) ContextValidate(ctx context.Context, formats strfmt.Registry) error { + return nil +} + +// MarshalBinary interface implementation +func (o *ListChangeLogsDefaultBodyDetailsItems0) MarshalBinary() ([]byte, error) { + if o == nil { + return nil, nil + } + return swag.WriteJSON(o) +} + +// UnmarshalBinary interface implementation +func (o *ListChangeLogsDefaultBodyDetailsItems0) UnmarshalBinary(b []byte) error { + var res ListChangeLogsDefaultBodyDetailsItems0 + if err := swag.ReadJSON(b, &res); err != nil { + return err + } + *o = res + return nil +} + +/* +ListChangeLogsOKBody list change logs OK body +swagger:model ListChangeLogsOKBody +*/ +type ListChangeLogsOKBody struct { + // List of available updates. + Updates []*ListChangeLogsOKBodyUpdatesItems0 `json:"updates"` + + // Last check time. + // Format: date-time + LastCheck strfmt.DateTime `json:"last_check,omitempty"` +} + +// Validate validates this list change logs OK body +func (o *ListChangeLogsOKBody) Validate(formats strfmt.Registry) error { + var res []error + + if err := o.validateUpdates(formats); err != nil { + res = append(res, err) + } + + if err := o.validateLastCheck(formats); err != nil { + res = append(res, err) + } + + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} + +func (o *ListChangeLogsOKBody) validateUpdates(formats strfmt.Registry) error { + if swag.IsZero(o.Updates) { // not required + return nil + } + + for i := 0; i < len(o.Updates); i++ { + if swag.IsZero(o.Updates[i]) { // not required + continue + } + + if o.Updates[i] != nil { + if err := o.Updates[i].Validate(formats); err != nil { + if ve, ok := err.(*errors.Validation); ok { + return ve.ValidateName("listChangeLogsOk" + "." + "updates" + "." + strconv.Itoa(i)) + } else if ce, ok := err.(*errors.CompositeError); ok { + return ce.ValidateName("listChangeLogsOk" + "." + "updates" + "." + strconv.Itoa(i)) + } + return err + } + } + + } + + return nil +} + +func (o *ListChangeLogsOKBody) validateLastCheck(formats strfmt.Registry) error { + if swag.IsZero(o.LastCheck) { // not required + return nil + } + + if err := validate.FormatOf("listChangeLogsOk"+"."+"last_check", "body", "date-time", o.LastCheck.String(), formats); err != nil { + return err + } + + return nil +} + +// ContextValidate validate this list change logs OK body based on the context it is used +func (o *ListChangeLogsOKBody) ContextValidate(ctx context.Context, formats strfmt.Registry) error { + var res []error + + if err := o.contextValidateUpdates(ctx, formats); err != nil { + res = append(res, err) + } + + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} + +func (o *ListChangeLogsOKBody) contextValidateUpdates(ctx context.Context, formats strfmt.Registry) error { + for i := 0; i < len(o.Updates); i++ { + if o.Updates[i] != nil { + if err := o.Updates[i].ContextValidate(ctx, formats); err != nil { + if ve, ok := err.(*errors.Validation); ok { + return ve.ValidateName("listChangeLogsOk" + "." + "updates" + "." + strconv.Itoa(i)) + } else if ce, ok := err.(*errors.CompositeError); ok { + return ce.ValidateName("listChangeLogsOk" + "." + "updates" + "." + strconv.Itoa(i)) + } + return err + } + } + } + + return nil +} + +// MarshalBinary interface implementation +func (o *ListChangeLogsOKBody) MarshalBinary() ([]byte, error) { + if o == nil { + return nil, nil + } + return swag.WriteJSON(o) +} + +// UnmarshalBinary interface implementation +func (o *ListChangeLogsOKBody) UnmarshalBinary(b []byte) error { + var res ListChangeLogsOKBody + if err := swag.ReadJSON(b, &res); err != nil { + return err + } + *o = res + return nil +} + +/* +ListChangeLogsOKBodyUpdatesItems0 list change logs OK body updates items0 +swagger:model ListChangeLogsOKBodyUpdatesItems0 +*/ +type ListChangeLogsOKBodyUpdatesItems0 struct { + // PMM Version. + Version string `json:"version,omitempty"` + + // Docker image tag. + Tag string `json:"tag,omitempty"` + + // Release date. + // Format: date-time + Timestamp strfmt.DateTime `json:"timestamp,omitempty"` + + // Release notes URL for the version (if available). + ReleaseNotesURL string `json:"release_notes_url,omitempty"` + + // Release notes text for the version (if available). + ReleaseNotesText string `json:"release_notes_text,omitempty"` +} + +// Validate validates this list change logs OK body updates items0 +func (o *ListChangeLogsOKBodyUpdatesItems0) Validate(formats strfmt.Registry) error { + var res []error + + if err := o.validateTimestamp(formats); err != nil { + res = append(res, err) + } + + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} + +func (o *ListChangeLogsOKBodyUpdatesItems0) validateTimestamp(formats strfmt.Registry) error { + if swag.IsZero(o.Timestamp) { // not required + return nil + } + + if err := validate.FormatOf("timestamp", "body", "date-time", o.Timestamp.String(), formats); err != nil { + return err + } + + return nil +} + +// ContextValidate validates this list change logs OK body updates items0 based on context it is used +func (o *ListChangeLogsOKBodyUpdatesItems0) ContextValidate(ctx context.Context, formats strfmt.Registry) error { + return nil +} + +// MarshalBinary interface implementation +func (o *ListChangeLogsOKBodyUpdatesItems0) MarshalBinary() ([]byte, error) { + if o == nil { + return nil, nil + } + return swag.WriteJSON(o) +} + +// UnmarshalBinary interface implementation +func (o *ListChangeLogsOKBodyUpdatesItems0) UnmarshalBinary(b []byte) error { + var res ListChangeLogsOKBodyUpdatesItems0 + if err := swag.ReadJSON(b, &res); err != nil { + return err + } + *o = res + return nil +} diff --git a/api/server/v1/json/client/server_service/server_service_client.go b/api/server/v1/json/client/server_service/server_service_client.go index 4d1cd044ff..15bd3eb6e5 100644 --- a/api/server/v1/json/client/server_service/server_service_client.go +++ b/api/server/v1/json/client/server_service/server_service_client.go @@ -38,6 +38,8 @@ type ClientService interface { LeaderHealthCheck(params *LeaderHealthCheckParams, opts ...ClientOption) (*LeaderHealthCheckOK, error) + ListChangeLogs(params *ListChangeLogsParams, opts ...ClientOption) (*ListChangeLogsOK, error) + Logs(params *LogsParams, writer io.Writer, opts ...ClientOption) (*LogsOK, error) Readiness(params *ReadinessParams, opts ...ClientOption) (*ReadinessOK, error) @@ -207,6 +209,45 @@ func (a *Client) LeaderHealthCheck(params *LeaderHealthCheckParams, opts ...Clie return nil, runtime.NewAPIError("unexpected success response: content available as default response in error", unexpectedSuccess, unexpectedSuccess.Code()) } +/* +ListChangeLogs lists all the changes between the installed version and the latest available version + +List all the changes between the installed version and the latest available version +*/ +func (a *Client) ListChangeLogs(params *ListChangeLogsParams, opts ...ClientOption) (*ListChangeLogsOK, error) { + // TODO: Validate the params before sending + if params == nil { + params = NewListChangeLogsParams() + } + op := &runtime.ClientOperation{ + ID: "ListChangeLogs", + Method: "GET", + PathPattern: "/v1/server/updates/changelogs", + ProducesMediaTypes: []string{"application/json"}, + ConsumesMediaTypes: []string{"application/json"}, + Schemes: []string{"http", "https"}, + Params: params, + Reader: &ListChangeLogsReader{formats: a.formats}, + Context: params.Context, + Client: params.HTTPClient, + } + for _, opt := range opts { + opt(op) + } + + result, err := a.transport.Submit(op) + if err != nil { + return nil, err + } + success, ok := result.(*ListChangeLogsOK) + if ok { + return success, nil + } + // unexpected success response + unexpectedSuccess := result.(*ListChangeLogsDefault) + return nil, runtime.NewAPIError("unexpected success response: content available as default response in error", unexpectedSuccess, unexpectedSuccess.Code()) +} + /* Logs logs diff --git a/api/server/v1/json/v1.json b/api/server/v1/json/v1.json index a47880959b..1a43beb50b 100644 --- a/api/server/v1/json/v1.json +++ b/api/server/v1/json/v1.json @@ -718,6 +718,16 @@ "latest": { "type": "object", "properties": { + "release_notes_text": { + "description": "Release notes text for the version (if available).", + "type": "string", + "x-order": 4 + }, + "release_notes_url": { + "description": "Release notes URL for the version (if available).", + "type": "string", + "x-order": 3 + }, "tag": { "description": "Docker image tag.", "type": "string", @@ -786,6 +796,101 @@ } } }, + "/v1/server/updates/changelogs": { + "get": { + "description": "List all the changes between the installed version and the latest available version", + "tags": [ + "ServerService" + ], + "summary": "List all the changes between the installed version and the latest available version", + "operationId": "ListChangeLogs", + "responses": { + "200": { + "description": "A successful response.", + "schema": { + "type": "object", + "properties": { + "last_check": { + "description": "Last check time.", + "type": "string", + "format": "date-time", + "x-order": 1 + }, + "updates": { + "description": "List of available updates.", + "type": "array", + "items": { + "type": "object", + "properties": { + "release_notes_text": { + "description": "Release notes text for the version (if available).", + "type": "string", + "x-order": 4 + }, + "release_notes_url": { + "description": "Release notes URL for the version (if available).", + "type": "string", + "x-order": 3 + }, + "tag": { + "description": "Docker image tag.", + "type": "string", + "x-order": 1 + }, + "timestamp": { + "description": "Release date.", + "type": "string", + "format": "date-time", + "x-order": 2 + }, + "version": { + "description": "PMM Version.", + "type": "string", + "x-order": 0 + } + } + }, + "x-order": 0 + } + } + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "type": "object", + "properties": { + "code": { + "type": "integer", + "format": "int32", + "x-order": 0 + }, + "details": { + "type": "array", + "items": { + "description": "`Any` contains an arbitrary serialized protocol buffer message along with a\nURL that describes the type of the serialized message.\n\nProtobuf library provides support to pack/unpack Any values in the form\nof utility functions or additional generated methods of the Any type.\n\nExample 1: Pack and unpack a message in C++.\n\n Foo foo = ...;\n Any any;\n any.PackFrom(foo);\n ...\n if (any.UnpackTo(\u0026foo)) {\n ...\n }\n\nExample 2: Pack and unpack a message in Java.\n\n Foo foo = ...;\n Any any = Any.pack(foo);\n ...\n if (any.is(Foo.class)) {\n foo = any.unpack(Foo.class);\n }\n // or ...\n if (any.isSameTypeAs(Foo.getDefaultInstance())) {\n foo = any.unpack(Foo.getDefaultInstance());\n }\n\n Example 3: Pack and unpack a message in Python.\n\n foo = Foo(...)\n any = Any()\n any.Pack(foo)\n ...\n if any.Is(Foo.DESCRIPTOR):\n any.Unpack(foo)\n ...\n\n Example 4: Pack and unpack a message in Go\n\n foo := \u0026pb.Foo{...}\n any, err := anypb.New(foo)\n if err != nil {\n ...\n }\n ...\n foo := \u0026pb.Foo{}\n if err := any.UnmarshalTo(foo); err != nil {\n ...\n }\n\nThe pack methods provided by protobuf library will by default use\n'type.googleapis.com/full.type.name' as the type URL and the unpack\nmethods only use the fully qualified type name after the last '/'\nin the type URL, for example \"foo.bar.com/x/y.z\" will yield type\nname \"y.z\".\n\nJSON\n====\nThe JSON representation of an `Any` value uses the regular\nrepresentation of the deserialized, embedded message, with an\nadditional field `@type` which contains the type URL. Example:\n\n package google.profile;\n message Person {\n string first_name = 1;\n string last_name = 2;\n }\n\n {\n \"@type\": \"type.googleapis.com/google.profile.Person\",\n \"firstName\": \u003cstring\u003e,\n \"lastName\": \u003cstring\u003e\n }\n\nIf the embedded message type is well-known and has a custom JSON\nrepresentation, that representation will be embedded adding a field\n`value` which holds the custom JSON in addition to the `@type`\nfield. Example (for message [google.protobuf.Duration][]):\n\n {\n \"@type\": \"type.googleapis.com/google.protobuf.Duration\",\n \"value\": \"1.212s\"\n }", + "type": "object", + "properties": { + "@type": { + "description": "A URL/resource name that uniquely identifies the type of the serialized\nprotocol buffer message. This string must contain at least\none \"/\" character. The last segment of the URL's path must represent\nthe fully qualified name of the type (as in\n`path/google.protobuf.Duration`). The name should be in a canonical form\n(e.g., leading \".\" is not accepted).\n\nIn practice, teams usually precompile into the binary all types that they\nexpect it to use in the context of Any. However, for URLs which use the\nscheme `http`, `https`, or no scheme, one can optionally set up a type\nserver that maps type URLs to message definitions as follows:\n\n* If no scheme is provided, `https` is assumed.\n* An HTTP GET on the URL must yield a [google.protobuf.Type][]\n value in binary format, or produce an error.\n* Applications are allowed to cache lookup results based on the\n URL, or have them precompiled into a binary to avoid any\n lookup. Therefore, binary compatibility needs to be preserved\n on changes to types. (Use versioned type names to manage\n breaking changes.)\n\nNote: this functionality is not currently available in the official\nprotobuf release, and it is not used for type URLs beginning with\ntype.googleapis.com. As of May 2023, there are no widely used type server\nimplementations and no plans to implement one.\n\nSchemes other than `http`, `https` (or the empty scheme) might be\nused with implementation specific semantics.", + "type": "string", + "x-order": 0 + } + }, + "additionalProperties": false + }, + "x-order": 2 + }, + "message": { + "type": "string", + "x-order": 1 + } + } + } + } + } + } + }, "/v1/server/updates:getStatus": { "post": { "description": "Returns PMM Server update status.", diff --git a/api/server/v1/server.pb.go b/api/server/v1/server.pb.go index 8315a4824b..076e4063a7 100644 --- a/api/server/v1/server.pb.go +++ b/api/server/v1/server.pb.go @@ -496,6 +496,10 @@ type DockerVersionInfo struct { Tag string `protobuf:"bytes,2,opt,name=tag,proto3" json:"tag,omitempty"` // Release date. Timestamp *timestamppb.Timestamp `protobuf:"bytes,3,opt,name=timestamp,proto3" json:"timestamp,omitempty"` + // Release notes URL for the version (if available). + ReleaseNotesUrl string `protobuf:"bytes,4,opt,name=release_notes_url,json=releaseNotesUrl,proto3" json:"release_notes_url,omitempty"` + // Release notes text for the version (if available). + ReleaseNotesText string `protobuf:"bytes,5,opt,name=release_notes_text,json=releaseNotesText,proto3" json:"release_notes_text,omitempty"` } func (x *DockerVersionInfo) Reset() { @@ -551,6 +555,20 @@ func (x *DockerVersionInfo) GetTimestamp() *timestamppb.Timestamp { return nil } +func (x *DockerVersionInfo) GetReleaseNotesUrl() string { + if x != nil { + return x.ReleaseNotesUrl + } + return "" +} + +func (x *DockerVersionInfo) GetReleaseNotesText() string { + if x != nil { + return x.ReleaseNotesText + } + return "" +} + type CheckUpdatesResponse struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -635,6 +653,101 @@ func (x *CheckUpdatesResponse) GetLastCheck() *timestamppb.Timestamp { return nil } +type ListChangeLogsRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields +} + +func (x *ListChangeLogsRequest) Reset() { + *x = ListChangeLogsRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_server_v1_server_proto_msgTypes[10] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ListChangeLogsRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ListChangeLogsRequest) ProtoMessage() {} + +func (x *ListChangeLogsRequest) ProtoReflect() protoreflect.Message { + mi := &file_server_v1_server_proto_msgTypes[10] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ListChangeLogsRequest.ProtoReflect.Descriptor instead. +func (*ListChangeLogsRequest) Descriptor() ([]byte, []int) { + return file_server_v1_server_proto_rawDescGZIP(), []int{10} +} + +type ListChangeLogsResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // List of available updates. + Updates []*DockerVersionInfo `protobuf:"bytes,1,rep,name=updates,proto3" json:"updates,omitempty"` + // Last check time. + LastCheck *timestamppb.Timestamp `protobuf:"bytes,2,opt,name=last_check,json=lastCheck,proto3" json:"last_check,omitempty"` +} + +func (x *ListChangeLogsResponse) Reset() { + *x = ListChangeLogsResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_server_v1_server_proto_msgTypes[11] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ListChangeLogsResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ListChangeLogsResponse) ProtoMessage() {} + +func (x *ListChangeLogsResponse) ProtoReflect() protoreflect.Message { + mi := &file_server_v1_server_proto_msgTypes[11] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ListChangeLogsResponse.ProtoReflect.Descriptor instead. +func (*ListChangeLogsResponse) Descriptor() ([]byte, []int) { + return file_server_v1_server_proto_rawDescGZIP(), []int{11} +} + +func (x *ListChangeLogsResponse) GetUpdates() []*DockerVersionInfo { + if x != nil { + return x.Updates + } + return nil +} + +func (x *ListChangeLogsResponse) GetLastCheck() *timestamppb.Timestamp { + if x != nil { + return x.LastCheck + } + return nil +} + type StartUpdateRequest struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -646,7 +759,7 @@ type StartUpdateRequest struct { func (x *StartUpdateRequest) Reset() { *x = StartUpdateRequest{} if protoimpl.UnsafeEnabled { - mi := &file_server_v1_server_proto_msgTypes[10] + mi := &file_server_v1_server_proto_msgTypes[12] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -659,7 +772,7 @@ func (x *StartUpdateRequest) String() string { func (*StartUpdateRequest) ProtoMessage() {} func (x *StartUpdateRequest) ProtoReflect() protoreflect.Message { - mi := &file_server_v1_server_proto_msgTypes[10] + mi := &file_server_v1_server_proto_msgTypes[12] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -672,7 +785,7 @@ func (x *StartUpdateRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use StartUpdateRequest.ProtoReflect.Descriptor instead. func (*StartUpdateRequest) Descriptor() ([]byte, []int) { - return file_server_v1_server_proto_rawDescGZIP(), []int{10} + return file_server_v1_server_proto_rawDescGZIP(), []int{12} } func (x *StartUpdateRequest) GetNewImage() string { @@ -696,7 +809,7 @@ type StartUpdateResponse struct { func (x *StartUpdateResponse) Reset() { *x = StartUpdateResponse{} if protoimpl.UnsafeEnabled { - mi := &file_server_v1_server_proto_msgTypes[11] + mi := &file_server_v1_server_proto_msgTypes[13] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -709,7 +822,7 @@ func (x *StartUpdateResponse) String() string { func (*StartUpdateResponse) ProtoMessage() {} func (x *StartUpdateResponse) ProtoReflect() protoreflect.Message { - mi := &file_server_v1_server_proto_msgTypes[11] + mi := &file_server_v1_server_proto_msgTypes[13] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -722,7 +835,7 @@ func (x *StartUpdateResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use StartUpdateResponse.ProtoReflect.Descriptor instead. func (*StartUpdateResponse) Descriptor() ([]byte, []int) { - return file_server_v1_server_proto_rawDescGZIP(), []int{11} + return file_server_v1_server_proto_rawDescGZIP(), []int{13} } func (x *StartUpdateResponse) GetAuthToken() string { @@ -753,7 +866,7 @@ type UpdateStatusRequest struct { func (x *UpdateStatusRequest) Reset() { *x = UpdateStatusRequest{} if protoimpl.UnsafeEnabled { - mi := &file_server_v1_server_proto_msgTypes[12] + mi := &file_server_v1_server_proto_msgTypes[14] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -766,7 +879,7 @@ func (x *UpdateStatusRequest) String() string { func (*UpdateStatusRequest) ProtoMessage() {} func (x *UpdateStatusRequest) ProtoReflect() protoreflect.Message { - mi := &file_server_v1_server_proto_msgTypes[12] + mi := &file_server_v1_server_proto_msgTypes[14] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -779,7 +892,7 @@ func (x *UpdateStatusRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use UpdateStatusRequest.ProtoReflect.Descriptor instead. func (*UpdateStatusRequest) Descriptor() ([]byte, []int) { - return file_server_v1_server_proto_rawDescGZIP(), []int{12} + return file_server_v1_server_proto_rawDescGZIP(), []int{14} } func (x *UpdateStatusRequest) GetAuthToken() string { @@ -812,7 +925,7 @@ type UpdateStatusResponse struct { func (x *UpdateStatusResponse) Reset() { *x = UpdateStatusResponse{} if protoimpl.UnsafeEnabled { - mi := &file_server_v1_server_proto_msgTypes[13] + mi := &file_server_v1_server_proto_msgTypes[15] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -825,7 +938,7 @@ func (x *UpdateStatusResponse) String() string { func (*UpdateStatusResponse) ProtoMessage() {} func (x *UpdateStatusResponse) ProtoReflect() protoreflect.Message { - mi := &file_server_v1_server_proto_msgTypes[13] + mi := &file_server_v1_server_proto_msgTypes[15] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -838,7 +951,7 @@ func (x *UpdateStatusResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use UpdateStatusResponse.ProtoReflect.Descriptor instead. func (*UpdateStatusResponse) Descriptor() ([]byte, []int) { - return file_server_v1_server_proto_rawDescGZIP(), []int{13} + return file_server_v1_server_proto_rawDescGZIP(), []int{15} } func (x *UpdateStatusResponse) GetLogLines() []string { @@ -879,7 +992,7 @@ type MetricsResolutions struct { func (x *MetricsResolutions) Reset() { *x = MetricsResolutions{} if protoimpl.UnsafeEnabled { - mi := &file_server_v1_server_proto_msgTypes[14] + mi := &file_server_v1_server_proto_msgTypes[16] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -892,7 +1005,7 @@ func (x *MetricsResolutions) String() string { func (*MetricsResolutions) ProtoMessage() {} func (x *MetricsResolutions) ProtoReflect() protoreflect.Message { - mi := &file_server_v1_server_proto_msgTypes[14] + mi := &file_server_v1_server_proto_msgTypes[16] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -905,7 +1018,7 @@ func (x *MetricsResolutions) ProtoReflect() protoreflect.Message { // Deprecated: Use MetricsResolutions.ProtoReflect.Descriptor instead. func (*MetricsResolutions) Descriptor() ([]byte, []int) { - return file_server_v1_server_proto_rawDescGZIP(), []int{14} + return file_server_v1_server_proto_rawDescGZIP(), []int{16} } func (x *MetricsResolutions) GetHr() *durationpb.Duration { @@ -946,7 +1059,7 @@ type AdvisorRunIntervals struct { func (x *AdvisorRunIntervals) Reset() { *x = AdvisorRunIntervals{} if protoimpl.UnsafeEnabled { - mi := &file_server_v1_server_proto_msgTypes[15] + mi := &file_server_v1_server_proto_msgTypes[17] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -959,7 +1072,7 @@ func (x *AdvisorRunIntervals) String() string { func (*AdvisorRunIntervals) ProtoMessage() {} func (x *AdvisorRunIntervals) ProtoReflect() protoreflect.Message { - mi := &file_server_v1_server_proto_msgTypes[15] + mi := &file_server_v1_server_proto_msgTypes[17] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -972,7 +1085,7 @@ func (x *AdvisorRunIntervals) ProtoReflect() protoreflect.Message { // Deprecated: Use AdvisorRunIntervals.ProtoReflect.Descriptor instead. func (*AdvisorRunIntervals) Descriptor() ([]byte, []int) { - return file_server_v1_server_proto_rawDescGZIP(), []int{15} + return file_server_v1_server_proto_rawDescGZIP(), []int{17} } func (x *AdvisorRunIntervals) GetStandardInterval() *durationpb.Duration { @@ -1037,7 +1150,7 @@ type Settings struct { func (x *Settings) Reset() { *x = Settings{} if protoimpl.UnsafeEnabled { - mi := &file_server_v1_server_proto_msgTypes[16] + mi := &file_server_v1_server_proto_msgTypes[18] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1050,7 +1163,7 @@ func (x *Settings) String() string { func (*Settings) ProtoMessage() {} func (x *Settings) ProtoReflect() protoreflect.Message { - mi := &file_server_v1_server_proto_msgTypes[16] + mi := &file_server_v1_server_proto_msgTypes[18] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1063,7 +1176,7 @@ func (x *Settings) ProtoReflect() protoreflect.Message { // Deprecated: Use Settings.ProtoReflect.Descriptor instead. func (*Settings) Descriptor() ([]byte, []int) { - return file_server_v1_server_proto_rawDescGZIP(), []int{16} + return file_server_v1_server_proto_rawDescGZIP(), []int{18} } func (x *Settings) GetUpdatesEnabled() bool { @@ -1194,7 +1307,7 @@ type GetSettingsRequest struct { func (x *GetSettingsRequest) Reset() { *x = GetSettingsRequest{} if protoimpl.UnsafeEnabled { - mi := &file_server_v1_server_proto_msgTypes[17] + mi := &file_server_v1_server_proto_msgTypes[19] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1207,7 +1320,7 @@ func (x *GetSettingsRequest) String() string { func (*GetSettingsRequest) ProtoMessage() {} func (x *GetSettingsRequest) ProtoReflect() protoreflect.Message { - mi := &file_server_v1_server_proto_msgTypes[17] + mi := &file_server_v1_server_proto_msgTypes[19] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1220,7 +1333,7 @@ func (x *GetSettingsRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use GetSettingsRequest.ProtoReflect.Descriptor instead. func (*GetSettingsRequest) Descriptor() ([]byte, []int) { - return file_server_v1_server_proto_rawDescGZIP(), []int{17} + return file_server_v1_server_proto_rawDescGZIP(), []int{19} } type GetSettingsResponse struct { @@ -1234,7 +1347,7 @@ type GetSettingsResponse struct { func (x *GetSettingsResponse) Reset() { *x = GetSettingsResponse{} if protoimpl.UnsafeEnabled { - mi := &file_server_v1_server_proto_msgTypes[18] + mi := &file_server_v1_server_proto_msgTypes[20] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1247,7 +1360,7 @@ func (x *GetSettingsResponse) String() string { func (*GetSettingsResponse) ProtoMessage() {} func (x *GetSettingsResponse) ProtoReflect() protoreflect.Message { - mi := &file_server_v1_server_proto_msgTypes[18] + mi := &file_server_v1_server_proto_msgTypes[20] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1260,7 +1373,7 @@ func (x *GetSettingsResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use GetSettingsResponse.ProtoReflect.Descriptor instead. func (*GetSettingsResponse) Descriptor() ([]byte, []int) { - return file_server_v1_server_proto_rawDescGZIP(), []int{18} + return file_server_v1_server_proto_rawDescGZIP(), []int{20} } func (x *GetSettingsResponse) GetSettings() *Settings { @@ -1301,7 +1414,7 @@ type ChangeSettingsRequest struct { func (x *ChangeSettingsRequest) Reset() { *x = ChangeSettingsRequest{} if protoimpl.UnsafeEnabled { - mi := &file_server_v1_server_proto_msgTypes[19] + mi := &file_server_v1_server_proto_msgTypes[21] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1314,7 +1427,7 @@ func (x *ChangeSettingsRequest) String() string { func (*ChangeSettingsRequest) ProtoMessage() {} func (x *ChangeSettingsRequest) ProtoReflect() protoreflect.Message { - mi := &file_server_v1_server_proto_msgTypes[19] + mi := &file_server_v1_server_proto_msgTypes[21] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1327,7 +1440,7 @@ func (x *ChangeSettingsRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ChangeSettingsRequest.ProtoReflect.Descriptor instead. func (*ChangeSettingsRequest) Descriptor() ([]byte, []int) { - return file_server_v1_server_proto_rawDescGZIP(), []int{19} + return file_server_v1_server_proto_rawDescGZIP(), []int{21} } func (x *ChangeSettingsRequest) GetEnableUpdates() bool { @@ -1432,7 +1545,7 @@ type ChangeSettingsResponse struct { func (x *ChangeSettingsResponse) Reset() { *x = ChangeSettingsResponse{} if protoimpl.UnsafeEnabled { - mi := &file_server_v1_server_proto_msgTypes[20] + mi := &file_server_v1_server_proto_msgTypes[22] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1445,7 +1558,7 @@ func (x *ChangeSettingsResponse) String() string { func (*ChangeSettingsResponse) ProtoMessage() {} func (x *ChangeSettingsResponse) ProtoReflect() protoreflect.Message { - mi := &file_server_v1_server_proto_msgTypes[20] + mi := &file_server_v1_server_proto_msgTypes[22] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1458,7 +1571,7 @@ func (x *ChangeSettingsResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ChangeSettingsResponse.ProtoReflect.Descriptor instead. func (*ChangeSettingsResponse) Descriptor() ([]byte, []int) { - return file_server_v1_server_proto_rawDescGZIP(), []int{20} + return file_server_v1_server_proto_rawDescGZIP(), []int{22} } func (x *ChangeSettingsResponse) GetSettings() *Settings { @@ -1520,270 +1633,305 @@ var file_server_v1_server_proto_rawDesc = []byte{ 0x66, 0x6f, 0x72, 0x63, 0x65, 0x12, 0x34, 0x0a, 0x16, 0x6f, 0x6e, 0x6c, 0x79, 0x5f, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x65, 0x64, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x14, 0x6f, 0x6e, 0x6c, 0x79, 0x49, 0x6e, 0x73, 0x74, 0x61, - 0x6c, 0x6c, 0x65, 0x64, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0x79, 0x0a, 0x11, 0x44, - 0x6f, 0x63, 0x6b, 0x65, 0x72, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x49, 0x6e, 0x66, 0x6f, - 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x10, 0x0a, 0x03, 0x74, 0x61, - 0x67, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x74, 0x61, 0x67, 0x12, 0x38, 0x0a, 0x09, - 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, - 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, 0x74, 0x69, 0x6d, - 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x22, 0x90, 0x02, 0x0a, 0x14, 0x43, 0x68, 0x65, 0x63, 0x6b, - 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, - 0x34, 0x0a, 0x09, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x56, - 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x09, 0x69, 0x6e, 0x73, 0x74, - 0x61, 0x6c, 0x6c, 0x65, 0x64, 0x12, 0x34, 0x0a, 0x06, 0x6c, 0x61, 0x74, 0x65, 0x73, 0x74, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x76, - 0x31, 0x2e, 0x44, 0x6f, 0x63, 0x6b, 0x65, 0x72, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x49, - 0x6e, 0x66, 0x6f, 0x52, 0x06, 0x6c, 0x61, 0x74, 0x65, 0x73, 0x74, 0x12, 0x29, 0x0a, 0x10, 0x75, - 0x70, 0x64, 0x61, 0x74, 0x65, 0x5f, 0x61, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x18, - 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0f, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x41, 0x76, 0x61, - 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x12, 0x26, 0x0a, 0x0f, 0x6c, 0x61, 0x74, 0x65, 0x73, 0x74, - 0x5f, 0x6e, 0x65, 0x77, 0x73, 0x5f, 0x75, 0x72, 0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x0d, 0x6c, 0x61, 0x74, 0x65, 0x73, 0x74, 0x4e, 0x65, 0x77, 0x73, 0x55, 0x72, 0x6c, 0x12, 0x39, - 0x0a, 0x0a, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x18, 0x05, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, - 0x6c, 0x61, 0x73, 0x74, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x22, 0x31, 0x0a, 0x12, 0x53, 0x74, 0x61, - 0x72, 0x74, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, - 0x1b, 0x0a, 0x09, 0x6e, 0x65, 0x77, 0x5f, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x08, 0x6e, 0x65, 0x77, 0x49, 0x6d, 0x61, 0x67, 0x65, 0x22, 0x53, 0x0a, 0x13, - 0x53, 0x74, 0x61, 0x72, 0x74, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x61, 0x75, 0x74, 0x68, 0x5f, 0x74, 0x6f, 0x6b, 0x65, - 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x61, 0x75, 0x74, 0x68, 0x54, 0x6f, 0x6b, - 0x65, 0x6e, 0x12, 0x1d, 0x0a, 0x0a, 0x6c, 0x6f, 0x67, 0x5f, 0x6f, 0x66, 0x66, 0x73, 0x65, 0x74, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x09, 0x6c, 0x6f, 0x67, 0x4f, 0x66, 0x66, 0x73, 0x65, - 0x74, 0x22, 0x53, 0x0a, 0x13, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x53, 0x74, 0x61, 0x74, 0x75, - 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x61, 0x75, 0x74, 0x68, - 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x61, 0x75, - 0x74, 0x68, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x1d, 0x0a, 0x0a, 0x6c, 0x6f, 0x67, 0x5f, 0x6f, - 0x66, 0x66, 0x73, 0x65, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x09, 0x6c, 0x6f, 0x67, - 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x22, 0x66, 0x0a, 0x14, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, - 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1b, - 0x0a, 0x09, 0x6c, 0x6f, 0x67, 0x5f, 0x6c, 0x69, 0x6e, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, - 0x09, 0x52, 0x08, 0x6c, 0x6f, 0x67, 0x4c, 0x69, 0x6e, 0x65, 0x73, 0x12, 0x1d, 0x0a, 0x0a, 0x6c, - 0x6f, 0x67, 0x5f, 0x6f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, - 0x09, 0x6c, 0x6f, 0x67, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x64, 0x6f, - 0x6e, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x04, 0x64, 0x6f, 0x6e, 0x65, 0x22, 0x95, - 0x01, 0x0a, 0x12, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x75, - 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x29, 0x0a, 0x02, 0x68, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x02, 0x68, 0x72, - 0x12, 0x29, 0x0a, 0x02, 0x6d, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, - 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, - 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x02, 0x6d, 0x72, 0x12, 0x29, 0x0a, 0x02, 0x6c, - 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, - 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x52, 0x02, 0x6c, 0x72, 0x22, 0xe5, 0x01, 0x0a, 0x13, 0x41, 0x64, 0x76, 0x69, 0x73, - 0x6f, 0x72, 0x52, 0x75, 0x6e, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x73, 0x12, 0x46, - 0x0a, 0x11, 0x73, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x5f, 0x69, 0x6e, 0x74, 0x65, 0x72, - 0x76, 0x61, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, - 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x10, 0x73, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x49, 0x6e, - 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x12, 0x3e, 0x0a, 0x0d, 0x72, 0x61, 0x72, 0x65, 0x5f, 0x69, - 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, + 0x6c, 0x6c, 0x65, 0x64, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0xd3, 0x01, 0x0a, 0x11, + 0x44, 0x6f, 0x63, 0x6b, 0x65, 0x72, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x49, 0x6e, 0x66, + 0x6f, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x10, 0x0a, 0x03, 0x74, + 0x61, 0x67, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x74, 0x61, 0x67, 0x12, 0x38, 0x0a, + 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, + 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, 0x74, 0x69, + 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x2a, 0x0a, 0x11, 0x72, 0x65, 0x6c, 0x65, 0x61, + 0x73, 0x65, 0x5f, 0x6e, 0x6f, 0x74, 0x65, 0x73, 0x5f, 0x75, 0x72, 0x6c, 0x18, 0x04, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x0f, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x4e, 0x6f, 0x74, 0x65, 0x73, + 0x55, 0x72, 0x6c, 0x12, 0x2c, 0x0a, 0x12, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x5f, 0x6e, + 0x6f, 0x74, 0x65, 0x73, 0x5f, 0x74, 0x65, 0x78, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x10, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x4e, 0x6f, 0x74, 0x65, 0x73, 0x54, 0x65, 0x78, + 0x74, 0x22, 0x90, 0x02, 0x0a, 0x14, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x55, 0x70, 0x64, 0x61, 0x74, + 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x34, 0x0a, 0x09, 0x69, 0x6e, + 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, + 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, + 0x6e, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x09, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x65, 0x64, + 0x12, 0x34, 0x0a, 0x06, 0x6c, 0x61, 0x74, 0x65, 0x73, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x1c, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x6f, 0x63, + 0x6b, 0x65, 0x72, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x06, + 0x6c, 0x61, 0x74, 0x65, 0x73, 0x74, 0x12, 0x29, 0x0a, 0x10, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, + 0x5f, 0x61, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, + 0x52, 0x0f, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x41, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, + 0x65, 0x12, 0x26, 0x0a, 0x0f, 0x6c, 0x61, 0x74, 0x65, 0x73, 0x74, 0x5f, 0x6e, 0x65, 0x77, 0x73, + 0x5f, 0x75, 0x72, 0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x6c, 0x61, 0x74, 0x65, + 0x73, 0x74, 0x4e, 0x65, 0x77, 0x73, 0x55, 0x72, 0x6c, 0x12, 0x39, 0x0a, 0x0a, 0x6c, 0x61, 0x73, + 0x74, 0x5f, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, - 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0c, 0x72, 0x61, 0x72, 0x65, 0x49, 0x6e, - 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x12, 0x46, 0x0a, 0x11, 0x66, 0x72, 0x65, 0x71, 0x75, 0x65, - 0x6e, 0x74, 0x5f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x18, 0x03, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x10, 0x66, 0x72, - 0x65, 0x71, 0x75, 0x65, 0x6e, 0x74, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x22, 0xe1, - 0x06, 0x0a, 0x08, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x27, 0x0a, 0x0f, 0x75, - 0x70, 0x64, 0x61, 0x74, 0x65, 0x73, 0x5f, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x08, 0x52, 0x0e, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x73, 0x45, 0x6e, 0x61, - 0x62, 0x6c, 0x65, 0x64, 0x12, 0x2b, 0x0a, 0x11, 0x74, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x74, 0x72, - 0x79, 0x5f, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, - 0x10, 0x74, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x74, 0x72, 0x79, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, - 0x64, 0x12, 0x4e, 0x0a, 0x13, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x5f, 0x72, 0x65, 0x73, - 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, - 0x2e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x65, 0x74, 0x72, 0x69, - 0x63, 0x73, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x12, 0x6d, - 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, - 0x73, 0x12, 0x40, 0x0a, 0x0e, 0x64, 0x61, 0x74, 0x61, 0x5f, 0x72, 0x65, 0x74, 0x65, 0x6e, 0x74, - 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, + 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, 0x6c, 0x61, 0x73, 0x74, 0x43, + 0x68, 0x65, 0x63, 0x6b, 0x22, 0x17, 0x0a, 0x15, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x68, 0x61, 0x6e, + 0x67, 0x65, 0x4c, 0x6f, 0x67, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x8b, 0x01, + 0x0a, 0x16, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x4c, 0x6f, 0x67, 0x73, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x36, 0x0a, 0x07, 0x75, 0x70, 0x64, 0x61, + 0x74, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x73, 0x65, 0x72, 0x76, + 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x6f, 0x63, 0x6b, 0x65, 0x72, 0x56, 0x65, 0x72, 0x73, + 0x69, 0x6f, 0x6e, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x07, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x73, + 0x12, 0x39, 0x0a, 0x0a, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, + 0x52, 0x09, 0x6c, 0x61, 0x73, 0x74, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x22, 0x31, 0x0a, 0x12, 0x53, + 0x74, 0x61, 0x72, 0x74, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x12, 0x1b, 0x0a, 0x09, 0x6e, 0x65, 0x77, 0x5f, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x6e, 0x65, 0x77, 0x49, 0x6d, 0x61, 0x67, 0x65, 0x22, 0x53, + 0x0a, 0x13, 0x53, 0x74, 0x61, 0x72, 0x74, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x61, 0x75, 0x74, 0x68, 0x5f, 0x74, 0x6f, + 0x6b, 0x65, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x61, 0x75, 0x74, 0x68, 0x54, + 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x1d, 0x0a, 0x0a, 0x6c, 0x6f, 0x67, 0x5f, 0x6f, 0x66, 0x66, 0x73, + 0x65, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x09, 0x6c, 0x6f, 0x67, 0x4f, 0x66, 0x66, + 0x73, 0x65, 0x74, 0x22, 0x53, 0x0a, 0x13, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x53, 0x74, 0x61, + 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x61, 0x75, + 0x74, 0x68, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, + 0x61, 0x75, 0x74, 0x68, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x1d, 0x0a, 0x0a, 0x6c, 0x6f, 0x67, + 0x5f, 0x6f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x09, 0x6c, + 0x6f, 0x67, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x22, 0x66, 0x0a, 0x14, 0x55, 0x70, 0x64, 0x61, + 0x74, 0x65, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x12, 0x1b, 0x0a, 0x09, 0x6c, 0x6f, 0x67, 0x5f, 0x6c, 0x69, 0x6e, 0x65, 0x73, 0x18, 0x01, 0x20, + 0x03, 0x28, 0x09, 0x52, 0x08, 0x6c, 0x6f, 0x67, 0x4c, 0x69, 0x6e, 0x65, 0x73, 0x12, 0x1d, 0x0a, + 0x0a, 0x6c, 0x6f, 0x67, 0x5f, 0x6f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x0d, 0x52, 0x09, 0x6c, 0x6f, 0x67, 0x4f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x12, 0x12, 0x0a, 0x04, + 0x64, 0x6f, 0x6e, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x04, 0x64, 0x6f, 0x6e, 0x65, + 0x22, 0x95, 0x01, 0x0a, 0x12, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x52, 0x65, 0x73, 0x6f, + 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x29, 0x0a, 0x02, 0x68, 0x72, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x02, + 0x68, 0x72, 0x12, 0x29, 0x0a, 0x02, 0x6d, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, + 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, + 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x02, 0x6d, 0x72, 0x12, 0x29, 0x0a, + 0x02, 0x6c, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0d, 0x64, 0x61, 0x74, 0x61, 0x52, 0x65, 0x74, 0x65, 0x6e, 0x74, - 0x69, 0x6f, 0x6e, 0x12, 0x17, 0x0a, 0x07, 0x73, 0x73, 0x68, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x05, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x73, 0x68, 0x4b, 0x65, 0x79, 0x12, 0x25, 0x0a, 0x0e, - 0x61, 0x77, 0x73, 0x5f, 0x70, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x06, - 0x20, 0x03, 0x28, 0x09, 0x52, 0x0d, 0x61, 0x77, 0x73, 0x50, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, - 0x6f, 0x6e, 0x73, 0x12, 0x27, 0x0a, 0x0f, 0x61, 0x64, 0x76, 0x69, 0x73, 0x6f, 0x72, 0x5f, 0x65, - 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18, 0x07, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0e, 0x61, 0x64, - 0x76, 0x69, 0x73, 0x6f, 0x72, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x12, 0x25, 0x0a, 0x0e, - 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x5f, 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x18, 0x08, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x45, 0x6d, - 0x61, 0x69, 0x6c, 0x12, 0x29, 0x0a, 0x10, 0x61, 0x6c, 0x65, 0x72, 0x74, 0x69, 0x6e, 0x67, 0x5f, - 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0f, 0x61, - 0x6c, 0x65, 0x72, 0x74, 0x69, 0x6e, 0x67, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x12, 0x2c, - 0x0a, 0x12, 0x70, 0x6d, 0x6d, 0x5f, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x61, 0x64, 0x64, - 0x72, 0x65, 0x73, 0x73, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, 0x70, 0x6d, 0x6d, 0x50, - 0x75, 0x62, 0x6c, 0x69, 0x63, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x52, 0x0a, 0x15, - 0x61, 0x64, 0x76, 0x69, 0x73, 0x6f, 0x72, 0x5f, 0x72, 0x75, 0x6e, 0x5f, 0x69, 0x6e, 0x74, 0x65, - 0x72, 0x76, 0x61, 0x6c, 0x73, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x73, 0x65, - 0x72, 0x76, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x64, 0x76, 0x69, 0x73, 0x6f, 0x72, 0x52, - 0x75, 0x6e, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x73, 0x52, 0x13, 0x61, 0x64, 0x76, + 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x02, 0x6c, 0x72, 0x22, 0xe5, 0x01, 0x0a, 0x13, 0x41, 0x64, 0x76, 0x69, 0x73, 0x6f, 0x72, 0x52, 0x75, 0x6e, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x73, - 0x12, 0x3a, 0x0a, 0x19, 0x62, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x5f, 0x6d, 0x61, 0x6e, 0x61, 0x67, - 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18, 0x0d, 0x20, - 0x01, 0x28, 0x08, 0x52, 0x17, 0x62, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x4d, 0x61, 0x6e, 0x61, 0x67, - 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x12, 0x33, 0x0a, 0x15, - 0x61, 0x7a, 0x75, 0x72, 0x65, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x5f, 0x65, 0x6e, - 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x08, 0x52, 0x14, 0x61, 0x7a, 0x75, - 0x72, 0x65, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, - 0x64, 0x12, 0x32, 0x0a, 0x15, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x65, 0x64, 0x5f, 0x74, - 0x6f, 0x5f, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x08, - 0x52, 0x13, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x65, 0x64, 0x54, 0x6f, 0x50, 0x6c, 0x61, - 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x12, 0x2f, 0x0a, 0x13, 0x74, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x74, - 0x72, 0x79, 0x5f, 0x73, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x69, 0x65, 0x73, 0x18, 0x10, 0x20, 0x03, - 0x28, 0x09, 0x52, 0x12, 0x74, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x74, 0x72, 0x79, 0x53, 0x75, 0x6d, - 0x6d, 0x61, 0x72, 0x69, 0x65, 0x73, 0x12, 0x32, 0x0a, 0x15, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, - 0x5f, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x18, - 0x11, 0x20, 0x01, 0x28, 0x08, 0x52, 0x13, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x41, 0x63, 0x63, - 0x65, 0x73, 0x73, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x12, 0x26, 0x0a, 0x0f, 0x64, 0x65, - 0x66, 0x61, 0x75, 0x6c, 0x74, 0x5f, 0x72, 0x6f, 0x6c, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x12, 0x20, - 0x01, 0x28, 0x0d, 0x52, 0x0d, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x52, 0x6f, 0x6c, 0x65, - 0x49, 0x64, 0x22, 0x14, 0x0a, 0x12, 0x47, 0x65, 0x74, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, - 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x46, 0x0a, 0x13, 0x47, 0x65, 0x74, 0x53, - 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, - 0x2f, 0x0a, 0x08, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x13, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, - 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x52, 0x08, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, - 0x22, 0xca, 0x07, 0x0a, 0x15, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x53, 0x65, 0x74, 0x74, 0x69, - 0x6e, 0x67, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2a, 0x0a, 0x0e, 0x65, 0x6e, - 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x73, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x08, 0x48, 0x00, 0x52, 0x0d, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x55, 0x70, 0x64, 0x61, - 0x74, 0x65, 0x73, 0x88, 0x01, 0x01, 0x12, 0x2e, 0x0a, 0x10, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, - 0x5f, 0x74, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x74, 0x72, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, - 0x48, 0x01, 0x52, 0x0f, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x54, 0x65, 0x6c, 0x65, 0x6d, 0x65, - 0x74, 0x72, 0x79, 0x88, 0x01, 0x01, 0x12, 0x4e, 0x0a, 0x13, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, - 0x73, 0x5f, 0x72, 0x65, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x03, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, - 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, - 0x6e, 0x73, 0x52, 0x12, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x52, 0x65, 0x73, 0x6f, 0x6c, - 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x40, 0x0a, 0x0e, 0x64, 0x61, 0x74, 0x61, 0x5f, 0x72, - 0x65, 0x74, 0x65, 0x6e, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, - 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, - 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0d, 0x64, 0x61, 0x74, 0x61, 0x52, - 0x65, 0x74, 0x65, 0x6e, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1c, 0x0a, 0x07, 0x73, 0x73, 0x68, 0x5f, - 0x6b, 0x65, 0x79, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x48, 0x02, 0x52, 0x06, 0x73, 0x73, 0x68, - 0x4b, 0x65, 0x79, 0x88, 0x01, 0x01, 0x12, 0x3f, 0x0a, 0x0e, 0x61, 0x77, 0x73, 0x5f, 0x70, 0x61, - 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, - 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x41, 0x72, - 0x72, 0x61, 0x79, 0x48, 0x03, 0x52, 0x0d, 0x61, 0x77, 0x73, 0x50, 0x61, 0x72, 0x74, 0x69, 0x74, - 0x69, 0x6f, 0x6e, 0x73, 0x88, 0x01, 0x01, 0x12, 0x2a, 0x0a, 0x0e, 0x65, 0x6e, 0x61, 0x62, 0x6c, - 0x65, 0x5f, 0x61, 0x64, 0x76, 0x69, 0x73, 0x6f, 0x72, 0x18, 0x07, 0x20, 0x01, 0x28, 0x08, 0x48, - 0x04, 0x52, 0x0d, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x41, 0x64, 0x76, 0x69, 0x73, 0x6f, 0x72, - 0x88, 0x01, 0x01, 0x12, 0x2c, 0x0a, 0x0f, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x61, 0x6c, - 0x65, 0x72, 0x74, 0x69, 0x6e, 0x67, 0x18, 0x08, 0x20, 0x01, 0x28, 0x08, 0x48, 0x05, 0x52, 0x0e, - 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x41, 0x6c, 0x65, 0x72, 0x74, 0x69, 0x6e, 0x67, 0x88, 0x01, - 0x01, 0x12, 0x31, 0x0a, 0x12, 0x70, 0x6d, 0x6d, 0x5f, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, - 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x48, 0x06, 0x52, - 0x10, 0x70, 0x6d, 0x6d, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, - 0x73, 0x88, 0x01, 0x01, 0x12, 0x52, 0x0a, 0x15, 0x61, 0x64, 0x76, 0x69, 0x73, 0x6f, 0x72, 0x5f, - 0x72, 0x75, 0x6e, 0x5f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x73, 0x18, 0x0a, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, - 0x41, 0x64, 0x76, 0x69, 0x73, 0x6f, 0x72, 0x52, 0x75, 0x6e, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x76, - 0x61, 0x6c, 0x73, 0x52, 0x13, 0x61, 0x64, 0x76, 0x69, 0x73, 0x6f, 0x72, 0x52, 0x75, 0x6e, 0x49, - 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x73, 0x12, 0x36, 0x0a, 0x14, 0x65, 0x6e, 0x61, 0x62, - 0x6c, 0x65, 0x5f, 0x61, 0x7a, 0x75, 0x72, 0x65, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, - 0x18, 0x0b, 0x20, 0x01, 0x28, 0x08, 0x48, 0x07, 0x52, 0x13, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, - 0x41, 0x7a, 0x75, 0x72, 0x65, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x88, 0x01, 0x01, - 0x12, 0x3d, 0x0a, 0x18, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x62, 0x61, 0x63, 0x6b, 0x75, - 0x70, 0x5f, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x18, 0x0c, 0x20, 0x01, - 0x28, 0x08, 0x48, 0x08, 0x52, 0x16, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x42, 0x61, 0x63, 0x6b, - 0x75, 0x70, 0x4d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x88, 0x01, 0x01, 0x12, - 0x37, 0x0a, 0x15, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, - 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x08, 0x48, 0x09, - 0x52, 0x13, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x43, 0x6f, - 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x88, 0x01, 0x01, 0x42, 0x11, 0x0a, 0x0f, 0x5f, 0x65, 0x6e, 0x61, - 0x62, 0x6c, 0x65, 0x5f, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x73, 0x42, 0x13, 0x0a, 0x11, 0x5f, - 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x74, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x74, 0x72, 0x79, - 0x42, 0x0a, 0x0a, 0x08, 0x5f, 0x73, 0x73, 0x68, 0x5f, 0x6b, 0x65, 0x79, 0x42, 0x11, 0x0a, 0x0f, - 0x5f, 0x61, 0x77, 0x73, 0x5f, 0x70, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x42, - 0x11, 0x0a, 0x0f, 0x5f, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x61, 0x64, 0x76, 0x69, 0x73, - 0x6f, 0x72, 0x42, 0x12, 0x0a, 0x10, 0x5f, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x61, 0x6c, - 0x65, 0x72, 0x74, 0x69, 0x6e, 0x67, 0x42, 0x15, 0x0a, 0x13, 0x5f, 0x70, 0x6d, 0x6d, 0x5f, 0x70, - 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x42, 0x17, 0x0a, - 0x15, 0x5f, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x61, 0x7a, 0x75, 0x72, 0x65, 0x64, 0x69, - 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x42, 0x1b, 0x0a, 0x19, 0x5f, 0x65, 0x6e, 0x61, 0x62, 0x6c, - 0x65, 0x5f, 0x62, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x5f, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, - 0x65, 0x6e, 0x74, 0x42, 0x18, 0x0a, 0x16, 0x5f, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x61, - 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x22, 0x49, 0x0a, - 0x16, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2f, 0x0a, 0x08, 0x73, 0x65, 0x74, 0x74, 0x69, - 0x6e, 0x67, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x73, 0x65, 0x72, 0x76, - 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x52, 0x08, - 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2a, 0xce, 0x01, 0x0a, 0x12, 0x44, 0x69, 0x73, - 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x12, - 0x23, 0x0a, 0x1f, 0x44, 0x49, 0x53, 0x54, 0x52, 0x49, 0x42, 0x55, 0x54, 0x49, 0x4f, 0x4e, 0x5f, - 0x4d, 0x45, 0x54, 0x48, 0x4f, 0x44, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, - 0x45, 0x44, 0x10, 0x00, 0x12, 0x1e, 0x0a, 0x1a, 0x44, 0x49, 0x53, 0x54, 0x52, 0x49, 0x42, 0x55, - 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x4d, 0x45, 0x54, 0x48, 0x4f, 0x44, 0x5f, 0x44, 0x4f, 0x43, 0x4b, - 0x45, 0x52, 0x10, 0x01, 0x12, 0x1b, 0x0a, 0x17, 0x44, 0x49, 0x53, 0x54, 0x52, 0x49, 0x42, 0x55, - 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x4d, 0x45, 0x54, 0x48, 0x4f, 0x44, 0x5f, 0x4f, 0x56, 0x46, 0x10, - 0x02, 0x12, 0x1b, 0x0a, 0x17, 0x44, 0x49, 0x53, 0x54, 0x52, 0x49, 0x42, 0x55, 0x54, 0x49, 0x4f, - 0x4e, 0x5f, 0x4d, 0x45, 0x54, 0x48, 0x4f, 0x44, 0x5f, 0x41, 0x4d, 0x49, 0x10, 0x03, 0x12, 0x1d, - 0x0a, 0x19, 0x44, 0x49, 0x53, 0x54, 0x52, 0x49, 0x42, 0x55, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x4d, - 0x45, 0x54, 0x48, 0x4f, 0x44, 0x5f, 0x41, 0x5a, 0x55, 0x52, 0x45, 0x10, 0x04, 0x12, 0x1a, 0x0a, - 0x16, 0x44, 0x49, 0x53, 0x54, 0x52, 0x49, 0x42, 0x55, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x4d, 0x45, - 0x54, 0x48, 0x4f, 0x44, 0x5f, 0x44, 0x4f, 0x10, 0x05, 0x32, 0x91, 0x0c, 0x0a, 0x0d, 0x53, 0x65, - 0x72, 0x76, 0x65, 0x72, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x86, 0x01, 0x0a, 0x07, - 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x19, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, - 0x2e, 0x76, 0x31, 0x2e, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x1a, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x56, - 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x44, - 0x92, 0x41, 0x27, 0x12, 0x07, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x1a, 0x1c, 0x52, 0x65, - 0x74, 0x75, 0x72, 0x6e, 0x73, 0x20, 0x50, 0x4d, 0x4d, 0x20, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, - 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x14, - 0x12, 0x12, 0x2f, 0x76, 0x31, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2f, 0x76, 0x65, 0x72, - 0x73, 0x69, 0x6f, 0x6e, 0x12, 0xab, 0x02, 0x0a, 0x09, 0x52, 0x65, 0x61, 0x64, 0x69, 0x6e, 0x65, - 0x73, 0x73, 0x12, 0x1b, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x52, - 0x65, 0x61, 0x64, 0x69, 0x6e, 0x65, 0x73, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x1c, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x61, 0x64, - 0x69, 0x6e, 0x65, 0x73, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0xe2, 0x01, - 0x92, 0x41, 0xc5, 0x01, 0x12, 0x16, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x20, 0x73, 0x65, 0x72, 0x76, - 0x65, 0x72, 0x20, 0x72, 0x65, 0x61, 0x64, 0x69, 0x6e, 0x65, 0x73, 0x73, 0x1a, 0xaa, 0x01, 0x52, - 0x65, 0x74, 0x75, 0x72, 0x6e, 0x73, 0x20, 0x61, 0x6e, 0x20, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x20, - 0x77, 0x68, 0x65, 0x6e, 0x20, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x63, 0x6f, 0x6d, 0x70, - 0x6f, 0x6e, 0x65, 0x6e, 0x74, 0x73, 0x20, 0x62, 0x65, 0x69, 0x6e, 0x67, 0x20, 0x72, 0x65, 0x73, - 0x74, 0x61, 0x72, 0x74, 0x65, 0x64, 0x20, 0x61, 0x72, 0x65, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x72, - 0x65, 0x61, 0x64, 0x79, 0x20, 0x79, 0x65, 0x74, 0x2e, 0x20, 0x55, 0x73, 0x65, 0x20, 0x74, 0x68, - 0x69, 0x73, 0x20, 0x41, 0x50, 0x49, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x63, 0x68, 0x65, 0x63, 0x6b, - 0x69, 0x6e, 0x67, 0x20, 0x74, 0x68, 0x65, 0x20, 0x68, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x20, 0x6f, - 0x66, 0x20, 0x44, 0x6f, 0x63, 0x6b, 0x65, 0x72, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, - 0x65, 0x72, 0x73, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x70, 0x72, 0x6f, 0x62, - 0x69, 0x6e, 0x67, 0x20, 0x4b, 0x75, 0x62, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x65, 0x73, 0x20, 0x72, - 0x65, 0x61, 0x64, 0x69, 0x6e, 0x65, 0x73, 0x73, 0x2e, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x13, 0x12, - 0x11, 0x2f, 0x76, 0x31, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2f, 0x72, 0x65, 0x61, 0x64, - 0x79, 0x7a, 0x12, 0x81, 0x02, 0x0a, 0x11, 0x4c, 0x65, 0x61, 0x64, 0x65, 0x72, 0x48, 0x65, 0x61, - 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x12, 0x23, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x65, - 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x65, 0x61, 0x64, 0x65, 0x72, 0x48, 0x65, 0x61, 0x6c, 0x74, - 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x24, 0x2e, - 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x65, 0x61, 0x64, 0x65, 0x72, - 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x22, 0xa0, 0x01, 0x92, 0x41, 0x79, 0x12, 0x10, 0x43, 0x68, 0x65, 0x63, 0x6b, - 0x20, 0x4c, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x68, 0x69, 0x70, 0x1a, 0x65, 0x43, 0x68, 0x65, - 0x63, 0x6b, 0x73, 0x20, 0x69, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x69, 0x6e, 0x73, 0x74, 0x61, - 0x6e, 0x63, 0x65, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6c, 0x65, 0x61, 0x64, 0x65, - 0x72, 0x20, 0x69, 0x6e, 0x20, 0x61, 0x20, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x2e, 0x20, - 0x52, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x73, 0x20, 0x61, 0x6e, 0x20, 0x65, 0x72, 0x72, 0x6f, 0x72, - 0x20, 0x69, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, - 0x20, 0x69, 0x73, 0x6e, 0x27, 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6c, 0x65, 0x61, 0x64, 0x65, - 0x72, 0x2e, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1e, 0x12, 0x1c, 0x2f, 0x76, 0x31, 0x2f, 0x73, 0x65, - 0x72, 0x76, 0x65, 0x72, 0x2f, 0x6c, 0x65, 0x61, 0x64, 0x65, 0x72, 0x48, 0x65, 0x61, 0x6c, 0x74, - 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x12, 0xa7, 0x01, 0x0a, 0x0c, 0x43, 0x68, 0x65, 0x63, 0x6b, - 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x73, 0x12, 0x1e, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, - 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x73, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1f, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, - 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x73, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x56, 0x92, 0x41, 0x39, 0x12, 0x0d, 0x43, - 0x68, 0x65, 0x63, 0x6b, 0x20, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x73, 0x1a, 0x28, 0x43, 0x68, - 0x65, 0x63, 0x6b, 0x73, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x61, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, - 0x6c, 0x65, 0x20, 0x50, 0x4d, 0x4d, 0x20, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x75, 0x70, - 0x64, 0x61, 0x74, 0x65, 0x73, 0x2e, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x14, 0x12, 0x12, 0x2f, 0x76, - 0x31, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2f, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x73, + 0x12, 0x46, 0x0a, 0x11, 0x73, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x5f, 0x69, 0x6e, 0x74, + 0x65, 0x72, 0x76, 0x61, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, + 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, + 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x10, 0x73, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, + 0x49, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x12, 0x3e, 0x0a, 0x0d, 0x72, 0x61, 0x72, 0x65, + 0x5f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, + 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0c, 0x72, 0x61, 0x72, 0x65, + 0x49, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x12, 0x46, 0x0a, 0x11, 0x66, 0x72, 0x65, 0x71, + 0x75, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x10, + 0x66, 0x72, 0x65, 0x71, 0x75, 0x65, 0x6e, 0x74, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, + 0x22, 0xe1, 0x06, 0x0a, 0x08, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x27, 0x0a, + 0x0f, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x73, 0x5f, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0e, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x73, 0x45, + 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x12, 0x2b, 0x0a, 0x11, 0x74, 0x65, 0x6c, 0x65, 0x6d, 0x65, + 0x74, 0x72, 0x79, 0x5f, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x08, 0x52, 0x10, 0x74, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x74, 0x72, 0x79, 0x45, 0x6e, 0x61, 0x62, + 0x6c, 0x65, 0x64, 0x12, 0x4e, 0x0a, 0x13, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x5f, 0x72, + 0x65, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x1d, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x65, 0x74, + 0x72, 0x69, 0x63, 0x73, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, + 0x12, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, + 0x6f, 0x6e, 0x73, 0x12, 0x40, 0x0a, 0x0e, 0x64, 0x61, 0x74, 0x61, 0x5f, 0x72, 0x65, 0x74, 0x65, + 0x6e, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, + 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, + 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0d, 0x64, 0x61, 0x74, 0x61, 0x52, 0x65, 0x74, 0x65, + 0x6e, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x17, 0x0a, 0x07, 0x73, 0x73, 0x68, 0x5f, 0x6b, 0x65, 0x79, + 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x73, 0x68, 0x4b, 0x65, 0x79, 0x12, 0x25, + 0x0a, 0x0e, 0x61, 0x77, 0x73, 0x5f, 0x70, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, + 0x18, 0x06, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0d, 0x61, 0x77, 0x73, 0x50, 0x61, 0x72, 0x74, 0x69, + 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x27, 0x0a, 0x0f, 0x61, 0x64, 0x76, 0x69, 0x73, 0x6f, 0x72, + 0x5f, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18, 0x07, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0e, + 0x61, 0x64, 0x76, 0x69, 0x73, 0x6f, 0x72, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x12, 0x25, + 0x0a, 0x0e, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x5f, 0x65, 0x6d, 0x61, 0x69, 0x6c, + 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, + 0x45, 0x6d, 0x61, 0x69, 0x6c, 0x12, 0x29, 0x0a, 0x10, 0x61, 0x6c, 0x65, 0x72, 0x74, 0x69, 0x6e, + 0x67, 0x5f, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x08, 0x52, + 0x0f, 0x61, 0x6c, 0x65, 0x72, 0x74, 0x69, 0x6e, 0x67, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, + 0x12, 0x2c, 0x0a, 0x12, 0x70, 0x6d, 0x6d, 0x5f, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x61, + 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, 0x70, 0x6d, + 0x6d, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x52, + 0x0a, 0x15, 0x61, 0x64, 0x76, 0x69, 0x73, 0x6f, 0x72, 0x5f, 0x72, 0x75, 0x6e, 0x5f, 0x69, 0x6e, + 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x73, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, + 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x64, 0x76, 0x69, 0x73, 0x6f, + 0x72, 0x52, 0x75, 0x6e, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x73, 0x52, 0x13, 0x61, + 0x64, 0x76, 0x69, 0x73, 0x6f, 0x72, 0x52, 0x75, 0x6e, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, + 0x6c, 0x73, 0x12, 0x3a, 0x0a, 0x19, 0x62, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x5f, 0x6d, 0x61, 0x6e, + 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18, + 0x0d, 0x20, 0x01, 0x28, 0x08, 0x52, 0x17, 0x62, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x4d, 0x61, 0x6e, + 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x12, 0x33, + 0x0a, 0x15, 0x61, 0x7a, 0x75, 0x72, 0x65, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x5f, + 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x08, 0x52, 0x14, 0x61, + 0x7a, 0x75, 0x72, 0x65, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x45, 0x6e, 0x61, 0x62, + 0x6c, 0x65, 0x64, 0x12, 0x32, 0x0a, 0x15, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x65, 0x64, + 0x5f, 0x74, 0x6f, 0x5f, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x18, 0x0f, 0x20, 0x01, + 0x28, 0x08, 0x52, 0x13, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x65, 0x64, 0x54, 0x6f, 0x50, + 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x12, 0x2f, 0x0a, 0x13, 0x74, 0x65, 0x6c, 0x65, 0x6d, + 0x65, 0x74, 0x72, 0x79, 0x5f, 0x73, 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x69, 0x65, 0x73, 0x18, 0x10, + 0x20, 0x03, 0x28, 0x09, 0x52, 0x12, 0x74, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x74, 0x72, 0x79, 0x53, + 0x75, 0x6d, 0x6d, 0x61, 0x72, 0x69, 0x65, 0x73, 0x12, 0x32, 0x0a, 0x15, 0x65, 0x6e, 0x61, 0x62, + 0x6c, 0x65, 0x5f, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, + 0x6c, 0x18, 0x11, 0x20, 0x01, 0x28, 0x08, 0x52, 0x13, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x41, + 0x63, 0x63, 0x65, 0x73, 0x73, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x12, 0x26, 0x0a, 0x0f, + 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x5f, 0x72, 0x6f, 0x6c, 0x65, 0x5f, 0x69, 0x64, 0x18, + 0x12, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0d, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x52, 0x6f, + 0x6c, 0x65, 0x49, 0x64, 0x22, 0x14, 0x0a, 0x12, 0x47, 0x65, 0x74, 0x53, 0x65, 0x74, 0x74, 0x69, + 0x6e, 0x67, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x46, 0x0a, 0x13, 0x47, 0x65, + 0x74, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x12, 0x2f, 0x0a, 0x08, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, + 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x52, 0x08, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, + 0x67, 0x73, 0x22, 0xca, 0x07, 0x0a, 0x15, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x53, 0x65, 0x74, + 0x74, 0x69, 0x6e, 0x67, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2a, 0x0a, 0x0e, + 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x73, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x08, 0x48, 0x00, 0x52, 0x0d, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x55, 0x70, + 0x64, 0x61, 0x74, 0x65, 0x73, 0x88, 0x01, 0x01, 0x12, 0x2e, 0x0a, 0x10, 0x65, 0x6e, 0x61, 0x62, + 0x6c, 0x65, 0x5f, 0x74, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x74, 0x72, 0x79, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x08, 0x48, 0x01, 0x52, 0x0f, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x54, 0x65, 0x6c, 0x65, + 0x6d, 0x65, 0x74, 0x72, 0x79, 0x88, 0x01, 0x01, 0x12, 0x4e, 0x0a, 0x13, 0x6d, 0x65, 0x74, 0x72, + 0x69, 0x63, 0x73, 0x5f, 0x72, 0x65, 0x73, 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, + 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x76, + 0x31, 0x2e, 0x4d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x75, 0x74, + 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x12, 0x6d, 0x65, 0x74, 0x72, 0x69, 0x63, 0x73, 0x52, 0x65, 0x73, + 0x6f, 0x6c, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x40, 0x0a, 0x0e, 0x64, 0x61, 0x74, 0x61, + 0x5f, 0x72, 0x65, 0x74, 0x65, 0x6e, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, + 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0d, 0x64, 0x61, 0x74, + 0x61, 0x52, 0x65, 0x74, 0x65, 0x6e, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1c, 0x0a, 0x07, 0x73, 0x73, + 0x68, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x48, 0x02, 0x52, 0x06, 0x73, + 0x73, 0x68, 0x4b, 0x65, 0x79, 0x88, 0x01, 0x01, 0x12, 0x3f, 0x0a, 0x0e, 0x61, 0x77, 0x73, 0x5f, + 0x70, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x13, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, + 0x41, 0x72, 0x72, 0x61, 0x79, 0x48, 0x03, 0x52, 0x0d, 0x61, 0x77, 0x73, 0x50, 0x61, 0x72, 0x74, + 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x88, 0x01, 0x01, 0x12, 0x2a, 0x0a, 0x0e, 0x65, 0x6e, 0x61, + 0x62, 0x6c, 0x65, 0x5f, 0x61, 0x64, 0x76, 0x69, 0x73, 0x6f, 0x72, 0x18, 0x07, 0x20, 0x01, 0x28, + 0x08, 0x48, 0x04, 0x52, 0x0d, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x41, 0x64, 0x76, 0x69, 0x73, + 0x6f, 0x72, 0x88, 0x01, 0x01, 0x12, 0x2c, 0x0a, 0x0f, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x5f, + 0x61, 0x6c, 0x65, 0x72, 0x74, 0x69, 0x6e, 0x67, 0x18, 0x08, 0x20, 0x01, 0x28, 0x08, 0x48, 0x05, + 0x52, 0x0e, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x41, 0x6c, 0x65, 0x72, 0x74, 0x69, 0x6e, 0x67, + 0x88, 0x01, 0x01, 0x12, 0x31, 0x0a, 0x12, 0x70, 0x6d, 0x6d, 0x5f, 0x70, 0x75, 0x62, 0x6c, 0x69, + 0x63, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x48, + 0x06, 0x52, 0x10, 0x70, 0x6d, 0x6d, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x41, 0x64, 0x64, 0x72, + 0x65, 0x73, 0x73, 0x88, 0x01, 0x01, 0x12, 0x52, 0x0a, 0x15, 0x61, 0x64, 0x76, 0x69, 0x73, 0x6f, + 0x72, 0x5f, 0x72, 0x75, 0x6e, 0x5f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x73, 0x18, + 0x0a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x76, + 0x31, 0x2e, 0x41, 0x64, 0x76, 0x69, 0x73, 0x6f, 0x72, 0x52, 0x75, 0x6e, 0x49, 0x6e, 0x74, 0x65, + 0x72, 0x76, 0x61, 0x6c, 0x73, 0x52, 0x13, 0x61, 0x64, 0x76, 0x69, 0x73, 0x6f, 0x72, 0x52, 0x75, + 0x6e, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x73, 0x12, 0x36, 0x0a, 0x14, 0x65, 0x6e, + 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x61, 0x7a, 0x75, 0x72, 0x65, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x76, + 0x65, 0x72, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x08, 0x48, 0x07, 0x52, 0x13, 0x65, 0x6e, 0x61, 0x62, + 0x6c, 0x65, 0x41, 0x7a, 0x75, 0x72, 0x65, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x88, + 0x01, 0x01, 0x12, 0x3d, 0x0a, 0x18, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x62, 0x61, 0x63, + 0x6b, 0x75, 0x70, 0x5f, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x18, 0x0c, + 0x20, 0x01, 0x28, 0x08, 0x48, 0x08, 0x52, 0x16, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x42, 0x61, + 0x63, 0x6b, 0x75, 0x70, 0x4d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x88, 0x01, + 0x01, 0x12, 0x37, 0x0a, 0x15, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x61, 0x63, 0x63, 0x65, + 0x73, 0x73, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x08, + 0x48, 0x09, 0x52, 0x13, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, + 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x88, 0x01, 0x01, 0x42, 0x11, 0x0a, 0x0f, 0x5f, 0x65, + 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x73, 0x42, 0x13, 0x0a, + 0x11, 0x5f, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x74, 0x65, 0x6c, 0x65, 0x6d, 0x65, 0x74, + 0x72, 0x79, 0x42, 0x0a, 0x0a, 0x08, 0x5f, 0x73, 0x73, 0x68, 0x5f, 0x6b, 0x65, 0x79, 0x42, 0x11, + 0x0a, 0x0f, 0x5f, 0x61, 0x77, 0x73, 0x5f, 0x70, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, + 0x73, 0x42, 0x11, 0x0a, 0x0f, 0x5f, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x61, 0x64, 0x76, + 0x69, 0x73, 0x6f, 0x72, 0x42, 0x12, 0x0a, 0x10, 0x5f, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x5f, + 0x61, 0x6c, 0x65, 0x72, 0x74, 0x69, 0x6e, 0x67, 0x42, 0x15, 0x0a, 0x13, 0x5f, 0x70, 0x6d, 0x6d, + 0x5f, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x42, + 0x17, 0x0a, 0x15, 0x5f, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x61, 0x7a, 0x75, 0x72, 0x65, + 0x64, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x42, 0x1b, 0x0a, 0x19, 0x5f, 0x65, 0x6e, 0x61, + 0x62, 0x6c, 0x65, 0x5f, 0x62, 0x61, 0x63, 0x6b, 0x75, 0x70, 0x5f, 0x6d, 0x61, 0x6e, 0x61, 0x67, + 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x42, 0x18, 0x0a, 0x16, 0x5f, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, + 0x5f, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x22, + 0x49, 0x0a, 0x16, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, + 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2f, 0x0a, 0x08, 0x73, 0x65, 0x74, + 0x74, 0x69, 0x6e, 0x67, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x73, 0x65, + 0x72, 0x76, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, + 0x52, 0x08, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2a, 0xce, 0x01, 0x0a, 0x12, 0x44, + 0x69, 0x73, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x65, 0x74, 0x68, 0x6f, + 0x64, 0x12, 0x23, 0x0a, 0x1f, 0x44, 0x49, 0x53, 0x54, 0x52, 0x49, 0x42, 0x55, 0x54, 0x49, 0x4f, + 0x4e, 0x5f, 0x4d, 0x45, 0x54, 0x48, 0x4f, 0x44, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, + 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x1e, 0x0a, 0x1a, 0x44, 0x49, 0x53, 0x54, 0x52, 0x49, + 0x42, 0x55, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x4d, 0x45, 0x54, 0x48, 0x4f, 0x44, 0x5f, 0x44, 0x4f, + 0x43, 0x4b, 0x45, 0x52, 0x10, 0x01, 0x12, 0x1b, 0x0a, 0x17, 0x44, 0x49, 0x53, 0x54, 0x52, 0x49, + 0x42, 0x55, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x4d, 0x45, 0x54, 0x48, 0x4f, 0x44, 0x5f, 0x4f, 0x56, + 0x46, 0x10, 0x02, 0x12, 0x1b, 0x0a, 0x17, 0x44, 0x49, 0x53, 0x54, 0x52, 0x49, 0x42, 0x55, 0x54, + 0x49, 0x4f, 0x4e, 0x5f, 0x4d, 0x45, 0x54, 0x48, 0x4f, 0x44, 0x5f, 0x41, 0x4d, 0x49, 0x10, 0x03, + 0x12, 0x1d, 0x0a, 0x19, 0x44, 0x49, 0x53, 0x54, 0x52, 0x49, 0x42, 0x55, 0x54, 0x49, 0x4f, 0x4e, + 0x5f, 0x4d, 0x45, 0x54, 0x48, 0x4f, 0x44, 0x5f, 0x41, 0x5a, 0x55, 0x52, 0x45, 0x10, 0x04, 0x12, + 0x1a, 0x0a, 0x16, 0x44, 0x49, 0x53, 0x54, 0x52, 0x49, 0x42, 0x55, 0x54, 0x49, 0x4f, 0x4e, 0x5f, + 0x4d, 0x45, 0x54, 0x48, 0x4f, 0x44, 0x5f, 0x44, 0x4f, 0x10, 0x05, 0x32, 0xbf, 0x0e, 0x0a, 0x0d, + 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x86, 0x01, + 0x0a, 0x07, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x19, 0x2e, 0x73, 0x65, 0x72, 0x76, + 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1a, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x76, 0x31, + 0x2e, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x22, 0x44, 0x92, 0x41, 0x27, 0x12, 0x07, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x1a, 0x1c, + 0x52, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x73, 0x20, 0x50, 0x4d, 0x4d, 0x20, 0x53, 0x65, 0x72, 0x76, + 0x65, 0x72, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x82, 0xd3, 0xe4, 0x93, + 0x02, 0x14, 0x12, 0x12, 0x2f, 0x76, 0x31, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2f, 0x76, + 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0xab, 0x02, 0x0a, 0x09, 0x52, 0x65, 0x61, 0x64, 0x69, + 0x6e, 0x65, 0x73, 0x73, 0x12, 0x1b, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x76, 0x31, + 0x2e, 0x52, 0x65, 0x61, 0x64, 0x69, 0x6e, 0x65, 0x73, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x1c, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, + 0x61, 0x64, 0x69, 0x6e, 0x65, 0x73, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, + 0xe2, 0x01, 0x92, 0x41, 0xc5, 0x01, 0x12, 0x16, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x20, 0x73, 0x65, + 0x72, 0x76, 0x65, 0x72, 0x20, 0x72, 0x65, 0x61, 0x64, 0x69, 0x6e, 0x65, 0x73, 0x73, 0x1a, 0xaa, + 0x01, 0x52, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x73, 0x20, 0x61, 0x6e, 0x20, 0x65, 0x72, 0x72, 0x6f, + 0x72, 0x20, 0x77, 0x68, 0x65, 0x6e, 0x20, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x63, 0x6f, + 0x6d, 0x70, 0x6f, 0x6e, 0x65, 0x6e, 0x74, 0x73, 0x20, 0x62, 0x65, 0x69, 0x6e, 0x67, 0x20, 0x72, + 0x65, 0x73, 0x74, 0x61, 0x72, 0x74, 0x65, 0x64, 0x20, 0x61, 0x72, 0x65, 0x20, 0x6e, 0x6f, 0x74, + 0x20, 0x72, 0x65, 0x61, 0x64, 0x79, 0x20, 0x79, 0x65, 0x74, 0x2e, 0x20, 0x55, 0x73, 0x65, 0x20, + 0x74, 0x68, 0x69, 0x73, 0x20, 0x41, 0x50, 0x49, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x63, 0x68, 0x65, + 0x63, 0x6b, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x68, 0x65, 0x20, 0x68, 0x65, 0x61, 0x6c, 0x74, 0x68, + 0x20, 0x6f, 0x66, 0x20, 0x44, 0x6f, 0x63, 0x6b, 0x65, 0x72, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x61, + 0x69, 0x6e, 0x65, 0x72, 0x73, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x70, 0x72, + 0x6f, 0x62, 0x69, 0x6e, 0x67, 0x20, 0x4b, 0x75, 0x62, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x65, 0x73, + 0x20, 0x72, 0x65, 0x61, 0x64, 0x69, 0x6e, 0x65, 0x73, 0x73, 0x2e, 0x82, 0xd3, 0xe4, 0x93, 0x02, + 0x13, 0x12, 0x11, 0x2f, 0x76, 0x31, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2f, 0x72, 0x65, + 0x61, 0x64, 0x79, 0x7a, 0x12, 0x81, 0x02, 0x0a, 0x11, 0x4c, 0x65, 0x61, 0x64, 0x65, 0x72, 0x48, + 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x12, 0x23, 0x2e, 0x73, 0x65, 0x72, + 0x76, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x65, 0x61, 0x64, 0x65, 0x72, 0x48, 0x65, 0x61, + 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x24, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x65, 0x61, 0x64, + 0x65, 0x72, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0xa0, 0x01, 0x92, 0x41, 0x79, 0x12, 0x10, 0x43, 0x68, 0x65, + 0x63, 0x6b, 0x20, 0x4c, 0x65, 0x61, 0x64, 0x65, 0x72, 0x73, 0x68, 0x69, 0x70, 0x1a, 0x65, 0x43, + 0x68, 0x65, 0x63, 0x6b, 0x73, 0x20, 0x69, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x69, 0x6e, 0x73, + 0x74, 0x61, 0x6e, 0x63, 0x65, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6c, 0x65, 0x61, + 0x64, 0x65, 0x72, 0x20, 0x69, 0x6e, 0x20, 0x61, 0x20, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, + 0x2e, 0x20, 0x52, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x73, 0x20, 0x61, 0x6e, 0x20, 0x65, 0x72, 0x72, + 0x6f, 0x72, 0x20, 0x69, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, + 0x63, 0x65, 0x20, 0x69, 0x73, 0x6e, 0x27, 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6c, 0x65, 0x61, + 0x64, 0x65, 0x72, 0x2e, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1e, 0x12, 0x1c, 0x2f, 0x76, 0x31, 0x2f, + 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2f, 0x6c, 0x65, 0x61, 0x64, 0x65, 0x72, 0x48, 0x65, 0x61, + 0x6c, 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x12, 0xa7, 0x01, 0x0a, 0x0c, 0x43, 0x68, 0x65, + 0x63, 0x6b, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x73, 0x12, 0x1e, 0x2e, 0x73, 0x65, 0x72, 0x76, + 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x55, 0x70, 0x64, 0x61, 0x74, + 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1f, 0x2e, 0x73, 0x65, 0x72, 0x76, + 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x55, 0x70, 0x64, 0x61, 0x74, + 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x56, 0x92, 0x41, 0x39, 0x12, + 0x0d, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x20, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x73, 0x1a, 0x28, + 0x43, 0x68, 0x65, 0x63, 0x6b, 0x73, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x61, 0x76, 0x61, 0x69, 0x6c, + 0x61, 0x62, 0x6c, 0x65, 0x20, 0x50, 0x4d, 0x4d, 0x20, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, + 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x73, 0x2e, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x14, 0x12, 0x12, + 0x2f, 0x76, 0x31, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2f, 0x75, 0x70, 0x64, 0x61, 0x74, + 0x65, 0x73, 0x12, 0xab, 0x02, 0x0a, 0x0e, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x68, 0x61, 0x6e, 0x67, + 0x65, 0x4c, 0x6f, 0x67, 0x73, 0x12, 0x20, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x76, + 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x4c, 0x6f, 0x67, 0x73, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x21, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, + 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x4c, 0x6f, + 0x67, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0xd3, 0x01, 0x92, 0x41, 0xaa, + 0x01, 0x12, 0x53, 0x4c, 0x69, 0x73, 0x74, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x74, 0x68, 0x65, 0x20, + 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x20, 0x62, 0x65, 0x74, 0x77, 0x65, 0x65, 0x6e, 0x20, + 0x74, 0x68, 0x65, 0x20, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x65, 0x64, 0x20, 0x76, 0x65, + 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6c, 0x61, + 0x74, 0x65, 0x73, 0x74, 0x20, 0x61, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x20, 0x76, + 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x1a, 0x53, 0x4c, 0x69, 0x73, 0x74, 0x20, 0x61, 0x6c, 0x6c, + 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x20, 0x62, 0x65, 0x74, + 0x77, 0x65, 0x65, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, + 0x65, 0x64, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, + 0x68, 0x65, 0x20, 0x6c, 0x61, 0x74, 0x65, 0x73, 0x74, 0x20, 0x61, 0x76, 0x61, 0x69, 0x6c, 0x61, + 0x62, 0x6c, 0x65, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x82, 0xd3, 0xe4, 0x93, 0x02, + 0x1f, 0x12, 0x1d, 0x2f, 0x76, 0x31, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2f, 0x75, 0x70, + 0x64, 0x61, 0x74, 0x65, 0x73, 0x2f, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x6c, 0x6f, 0x67, 0x73, 0x12, 0x9d, 0x01, 0x0a, 0x0b, 0x53, 0x74, 0x61, 0x72, 0x74, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x12, 0x1d, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x74, 0x61, 0x72, 0x74, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, @@ -1852,7 +2000,7 @@ func file_server_v1_server_proto_rawDescGZIP() []byte { var ( file_server_v1_server_proto_enumTypes = make([]protoimpl.EnumInfo, 1) - file_server_v1_server_proto_msgTypes = make([]protoimpl.MessageInfo, 21) + file_server_v1_server_proto_msgTypes = make([]protoimpl.MessageInfo, 23) file_server_v1_server_proto_goTypes = []any{ (DistributionMethod)(0), // 0: server.v1.DistributionMethod (*VersionInfo)(nil), // 1: server.v1.VersionInfo @@ -1865,68 +2013,74 @@ var ( (*CheckUpdatesRequest)(nil), // 8: server.v1.CheckUpdatesRequest (*DockerVersionInfo)(nil), // 9: server.v1.DockerVersionInfo (*CheckUpdatesResponse)(nil), // 10: server.v1.CheckUpdatesResponse - (*StartUpdateRequest)(nil), // 11: server.v1.StartUpdateRequest - (*StartUpdateResponse)(nil), // 12: server.v1.StartUpdateResponse - (*UpdateStatusRequest)(nil), // 13: server.v1.UpdateStatusRequest - (*UpdateStatusResponse)(nil), // 14: server.v1.UpdateStatusResponse - (*MetricsResolutions)(nil), // 15: server.v1.MetricsResolutions - (*AdvisorRunIntervals)(nil), // 16: server.v1.AdvisorRunIntervals - (*Settings)(nil), // 17: server.v1.Settings - (*GetSettingsRequest)(nil), // 18: server.v1.GetSettingsRequest - (*GetSettingsResponse)(nil), // 19: server.v1.GetSettingsResponse - (*ChangeSettingsRequest)(nil), // 20: server.v1.ChangeSettingsRequest - (*ChangeSettingsResponse)(nil), // 21: server.v1.ChangeSettingsResponse - (*timestamppb.Timestamp)(nil), // 22: google.protobuf.Timestamp - (*durationpb.Duration)(nil), // 23: google.protobuf.Duration - (*common.StringArray)(nil), // 24: common.StringArray + (*ListChangeLogsRequest)(nil), // 11: server.v1.ListChangeLogsRequest + (*ListChangeLogsResponse)(nil), // 12: server.v1.ListChangeLogsResponse + (*StartUpdateRequest)(nil), // 13: server.v1.StartUpdateRequest + (*StartUpdateResponse)(nil), // 14: server.v1.StartUpdateResponse + (*UpdateStatusRequest)(nil), // 15: server.v1.UpdateStatusRequest + (*UpdateStatusResponse)(nil), // 16: server.v1.UpdateStatusResponse + (*MetricsResolutions)(nil), // 17: server.v1.MetricsResolutions + (*AdvisorRunIntervals)(nil), // 18: server.v1.AdvisorRunIntervals + (*Settings)(nil), // 19: server.v1.Settings + (*GetSettingsRequest)(nil), // 20: server.v1.GetSettingsRequest + (*GetSettingsResponse)(nil), // 21: server.v1.GetSettingsResponse + (*ChangeSettingsRequest)(nil), // 22: server.v1.ChangeSettingsRequest + (*ChangeSettingsResponse)(nil), // 23: server.v1.ChangeSettingsResponse + (*timestamppb.Timestamp)(nil), // 24: google.protobuf.Timestamp + (*durationpb.Duration)(nil), // 25: google.protobuf.Duration + (*common.StringArray)(nil), // 26: common.StringArray } ) var file_server_v1_server_proto_depIdxs = []int32{ - 22, // 0: server.v1.VersionInfo.timestamp:type_name -> google.protobuf.Timestamp + 24, // 0: server.v1.VersionInfo.timestamp:type_name -> google.protobuf.Timestamp 1, // 1: server.v1.VersionResponse.server:type_name -> server.v1.VersionInfo 1, // 2: server.v1.VersionResponse.managed:type_name -> server.v1.VersionInfo 0, // 3: server.v1.VersionResponse.distribution_method:type_name -> server.v1.DistributionMethod - 22, // 4: server.v1.DockerVersionInfo.timestamp:type_name -> google.protobuf.Timestamp + 24, // 4: server.v1.DockerVersionInfo.timestamp:type_name -> google.protobuf.Timestamp 1, // 5: server.v1.CheckUpdatesResponse.installed:type_name -> server.v1.VersionInfo 9, // 6: server.v1.CheckUpdatesResponse.latest:type_name -> server.v1.DockerVersionInfo - 22, // 7: server.v1.CheckUpdatesResponse.last_check:type_name -> google.protobuf.Timestamp - 23, // 8: server.v1.MetricsResolutions.hr:type_name -> google.protobuf.Duration - 23, // 9: server.v1.MetricsResolutions.mr:type_name -> google.protobuf.Duration - 23, // 10: server.v1.MetricsResolutions.lr:type_name -> google.protobuf.Duration - 23, // 11: server.v1.AdvisorRunIntervals.standard_interval:type_name -> google.protobuf.Duration - 23, // 12: server.v1.AdvisorRunIntervals.rare_interval:type_name -> google.protobuf.Duration - 23, // 13: server.v1.AdvisorRunIntervals.frequent_interval:type_name -> google.protobuf.Duration - 15, // 14: server.v1.Settings.metrics_resolutions:type_name -> server.v1.MetricsResolutions - 23, // 15: server.v1.Settings.data_retention:type_name -> google.protobuf.Duration - 16, // 16: server.v1.Settings.advisor_run_intervals:type_name -> server.v1.AdvisorRunIntervals - 17, // 17: server.v1.GetSettingsResponse.settings:type_name -> server.v1.Settings - 15, // 18: server.v1.ChangeSettingsRequest.metrics_resolutions:type_name -> server.v1.MetricsResolutions - 23, // 19: server.v1.ChangeSettingsRequest.data_retention:type_name -> google.protobuf.Duration - 24, // 20: server.v1.ChangeSettingsRequest.aws_partitions:type_name -> common.StringArray - 16, // 21: server.v1.ChangeSettingsRequest.advisor_run_intervals:type_name -> server.v1.AdvisorRunIntervals - 17, // 22: server.v1.ChangeSettingsResponse.settings:type_name -> server.v1.Settings - 2, // 23: server.v1.ServerService.Version:input_type -> server.v1.VersionRequest - 4, // 24: server.v1.ServerService.Readiness:input_type -> server.v1.ReadinessRequest - 6, // 25: server.v1.ServerService.LeaderHealthCheck:input_type -> server.v1.LeaderHealthCheckRequest - 8, // 26: server.v1.ServerService.CheckUpdates:input_type -> server.v1.CheckUpdatesRequest - 11, // 27: server.v1.ServerService.StartUpdate:input_type -> server.v1.StartUpdateRequest - 13, // 28: server.v1.ServerService.UpdateStatus:input_type -> server.v1.UpdateStatusRequest - 18, // 29: server.v1.ServerService.GetSettings:input_type -> server.v1.GetSettingsRequest - 20, // 30: server.v1.ServerService.ChangeSettings:input_type -> server.v1.ChangeSettingsRequest - 3, // 31: server.v1.ServerService.Version:output_type -> server.v1.VersionResponse - 5, // 32: server.v1.ServerService.Readiness:output_type -> server.v1.ReadinessResponse - 7, // 33: server.v1.ServerService.LeaderHealthCheck:output_type -> server.v1.LeaderHealthCheckResponse - 10, // 34: server.v1.ServerService.CheckUpdates:output_type -> server.v1.CheckUpdatesResponse - 12, // 35: server.v1.ServerService.StartUpdate:output_type -> server.v1.StartUpdateResponse - 14, // 36: server.v1.ServerService.UpdateStatus:output_type -> server.v1.UpdateStatusResponse - 19, // 37: server.v1.ServerService.GetSettings:output_type -> server.v1.GetSettingsResponse - 21, // 38: server.v1.ServerService.ChangeSettings:output_type -> server.v1.ChangeSettingsResponse - 31, // [31:39] is the sub-list for method output_type - 23, // [23:31] is the sub-list for method input_type - 23, // [23:23] is the sub-list for extension type_name - 23, // [23:23] is the sub-list for extension extendee - 0, // [0:23] is the sub-list for field type_name + 24, // 7: server.v1.CheckUpdatesResponse.last_check:type_name -> google.protobuf.Timestamp + 9, // 8: server.v1.ListChangeLogsResponse.updates:type_name -> server.v1.DockerVersionInfo + 24, // 9: server.v1.ListChangeLogsResponse.last_check:type_name -> google.protobuf.Timestamp + 25, // 10: server.v1.MetricsResolutions.hr:type_name -> google.protobuf.Duration + 25, // 11: server.v1.MetricsResolutions.mr:type_name -> google.protobuf.Duration + 25, // 12: server.v1.MetricsResolutions.lr:type_name -> google.protobuf.Duration + 25, // 13: server.v1.AdvisorRunIntervals.standard_interval:type_name -> google.protobuf.Duration + 25, // 14: server.v1.AdvisorRunIntervals.rare_interval:type_name -> google.protobuf.Duration + 25, // 15: server.v1.AdvisorRunIntervals.frequent_interval:type_name -> google.protobuf.Duration + 17, // 16: server.v1.Settings.metrics_resolutions:type_name -> server.v1.MetricsResolutions + 25, // 17: server.v1.Settings.data_retention:type_name -> google.protobuf.Duration + 18, // 18: server.v1.Settings.advisor_run_intervals:type_name -> server.v1.AdvisorRunIntervals + 19, // 19: server.v1.GetSettingsResponse.settings:type_name -> server.v1.Settings + 17, // 20: server.v1.ChangeSettingsRequest.metrics_resolutions:type_name -> server.v1.MetricsResolutions + 25, // 21: server.v1.ChangeSettingsRequest.data_retention:type_name -> google.protobuf.Duration + 26, // 22: server.v1.ChangeSettingsRequest.aws_partitions:type_name -> common.StringArray + 18, // 23: server.v1.ChangeSettingsRequest.advisor_run_intervals:type_name -> server.v1.AdvisorRunIntervals + 19, // 24: server.v1.ChangeSettingsResponse.settings:type_name -> server.v1.Settings + 2, // 25: server.v1.ServerService.Version:input_type -> server.v1.VersionRequest + 4, // 26: server.v1.ServerService.Readiness:input_type -> server.v1.ReadinessRequest + 6, // 27: server.v1.ServerService.LeaderHealthCheck:input_type -> server.v1.LeaderHealthCheckRequest + 8, // 28: server.v1.ServerService.CheckUpdates:input_type -> server.v1.CheckUpdatesRequest + 11, // 29: server.v1.ServerService.ListChangeLogs:input_type -> server.v1.ListChangeLogsRequest + 13, // 30: server.v1.ServerService.StartUpdate:input_type -> server.v1.StartUpdateRequest + 15, // 31: server.v1.ServerService.UpdateStatus:input_type -> server.v1.UpdateStatusRequest + 20, // 32: server.v1.ServerService.GetSettings:input_type -> server.v1.GetSettingsRequest + 22, // 33: server.v1.ServerService.ChangeSettings:input_type -> server.v1.ChangeSettingsRequest + 3, // 34: server.v1.ServerService.Version:output_type -> server.v1.VersionResponse + 5, // 35: server.v1.ServerService.Readiness:output_type -> server.v1.ReadinessResponse + 7, // 36: server.v1.ServerService.LeaderHealthCheck:output_type -> server.v1.LeaderHealthCheckResponse + 10, // 37: server.v1.ServerService.CheckUpdates:output_type -> server.v1.CheckUpdatesResponse + 12, // 38: server.v1.ServerService.ListChangeLogs:output_type -> server.v1.ListChangeLogsResponse + 14, // 39: server.v1.ServerService.StartUpdate:output_type -> server.v1.StartUpdateResponse + 16, // 40: server.v1.ServerService.UpdateStatus:output_type -> server.v1.UpdateStatusResponse + 21, // 41: server.v1.ServerService.GetSettings:output_type -> server.v1.GetSettingsResponse + 23, // 42: server.v1.ServerService.ChangeSettings:output_type -> server.v1.ChangeSettingsResponse + 34, // [34:43] is the sub-list for method output_type + 25, // [25:34] is the sub-list for method input_type + 25, // [25:25] is the sub-list for extension type_name + 25, // [25:25] is the sub-list for extension extendee + 0, // [0:25] is the sub-list for field type_name } func init() { file_server_v1_server_proto_init() } @@ -2056,7 +2210,7 @@ func file_server_v1_server_proto_init() { } } file_server_v1_server_proto_msgTypes[10].Exporter = func(v any, i int) any { - switch v := v.(*StartUpdateRequest); i { + switch v := v.(*ListChangeLogsRequest); i { case 0: return &v.state case 1: @@ -2068,7 +2222,7 @@ func file_server_v1_server_proto_init() { } } file_server_v1_server_proto_msgTypes[11].Exporter = func(v any, i int) any { - switch v := v.(*StartUpdateResponse); i { + switch v := v.(*ListChangeLogsResponse); i { case 0: return &v.state case 1: @@ -2080,7 +2234,7 @@ func file_server_v1_server_proto_init() { } } file_server_v1_server_proto_msgTypes[12].Exporter = func(v any, i int) any { - switch v := v.(*UpdateStatusRequest); i { + switch v := v.(*StartUpdateRequest); i { case 0: return &v.state case 1: @@ -2092,7 +2246,7 @@ func file_server_v1_server_proto_init() { } } file_server_v1_server_proto_msgTypes[13].Exporter = func(v any, i int) any { - switch v := v.(*UpdateStatusResponse); i { + switch v := v.(*StartUpdateResponse); i { case 0: return &v.state case 1: @@ -2104,7 +2258,7 @@ func file_server_v1_server_proto_init() { } } file_server_v1_server_proto_msgTypes[14].Exporter = func(v any, i int) any { - switch v := v.(*MetricsResolutions); i { + switch v := v.(*UpdateStatusRequest); i { case 0: return &v.state case 1: @@ -2116,7 +2270,7 @@ func file_server_v1_server_proto_init() { } } file_server_v1_server_proto_msgTypes[15].Exporter = func(v any, i int) any { - switch v := v.(*AdvisorRunIntervals); i { + switch v := v.(*UpdateStatusResponse); i { case 0: return &v.state case 1: @@ -2128,7 +2282,7 @@ func file_server_v1_server_proto_init() { } } file_server_v1_server_proto_msgTypes[16].Exporter = func(v any, i int) any { - switch v := v.(*Settings); i { + switch v := v.(*MetricsResolutions); i { case 0: return &v.state case 1: @@ -2140,7 +2294,7 @@ func file_server_v1_server_proto_init() { } } file_server_v1_server_proto_msgTypes[17].Exporter = func(v any, i int) any { - switch v := v.(*GetSettingsRequest); i { + switch v := v.(*AdvisorRunIntervals); i { case 0: return &v.state case 1: @@ -2152,7 +2306,7 @@ func file_server_v1_server_proto_init() { } } file_server_v1_server_proto_msgTypes[18].Exporter = func(v any, i int) any { - switch v := v.(*GetSettingsResponse); i { + switch v := v.(*Settings); i { case 0: return &v.state case 1: @@ -2164,7 +2318,7 @@ func file_server_v1_server_proto_init() { } } file_server_v1_server_proto_msgTypes[19].Exporter = func(v any, i int) any { - switch v := v.(*ChangeSettingsRequest); i { + switch v := v.(*GetSettingsRequest); i { case 0: return &v.state case 1: @@ -2176,6 +2330,30 @@ func file_server_v1_server_proto_init() { } } file_server_v1_server_proto_msgTypes[20].Exporter = func(v any, i int) any { + switch v := v.(*GetSettingsResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_server_v1_server_proto_msgTypes[21].Exporter = func(v any, i int) any { + switch v := v.(*ChangeSettingsRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_server_v1_server_proto_msgTypes[22].Exporter = func(v any, i int) any { switch v := v.(*ChangeSettingsResponse); i { case 0: return &v.state @@ -2188,14 +2366,14 @@ func file_server_v1_server_proto_init() { } } } - file_server_v1_server_proto_msgTypes[19].OneofWrappers = []any{} + file_server_v1_server_proto_msgTypes[21].OneofWrappers = []any{} type x struct{} out := protoimpl.TypeBuilder{ File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_server_v1_server_proto_rawDesc, NumEnums: 1, - NumMessages: 21, + NumMessages: 23, NumExtensions: 0, NumServices: 1, }, diff --git a/api/server/v1/server.pb.gw.go b/api/server/v1/server.pb.gw.go index 07e35fb1ec..26253aedbb 100644 --- a/api/server/v1/server.pb.gw.go +++ b/api/server/v1/server.pb.gw.go @@ -129,6 +129,22 @@ func local_request_ServerService_CheckUpdates_0(ctx context.Context, marshaler r return msg, metadata, err } +func request_ServerService_ListChangeLogs_0(ctx context.Context, marshaler runtime.Marshaler, client ServerServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq ListChangeLogsRequest + var metadata runtime.ServerMetadata + + msg, err := client.ListChangeLogs(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err +} + +func local_request_ServerService_ListChangeLogs_0(ctx context.Context, marshaler runtime.Marshaler, server ServerServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var protoReq ListChangeLogsRequest + var metadata runtime.ServerMetadata + + msg, err := server.ListChangeLogs(ctx, &protoReq) + return msg, metadata, err +} + func request_ServerService_StartUpdate_0(ctx context.Context, marshaler runtime.Marshaler, client ServerServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { var protoReq StartUpdateRequest var metadata runtime.ServerMetadata @@ -319,6 +335,30 @@ func RegisterServerServiceHandlerServer(ctx context.Context, mux *runtime.ServeM forward_ServerService_CheckUpdates_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) }) + mux.Handle("GET", pattern_ServerService_ListChangeLogs_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + var stream runtime.ServerTransportStream + ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + var err error + var annotatedContext context.Context + annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/server.v1.ServerService/ListChangeLogs", runtime.WithHTTPPathPattern("/v1/server/updates/changelogs")) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_ServerService_ListChangeLogs_0(annotatedContext, inboundMarshaler, server, req, pathParams) + md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) + annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) + if err != nil { + runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) + return + } + + forward_ServerService_ListChangeLogs_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + }) + mux.Handle("POST", pattern_ServerService_StartUpdate_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() @@ -539,6 +579,27 @@ func RegisterServerServiceHandlerClient(ctx context.Context, mux *runtime.ServeM forward_ServerService_CheckUpdates_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) }) + mux.Handle("GET", pattern_ServerService_ListChangeLogs_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { + ctx, cancel := context.WithCancel(req.Context()) + defer cancel() + inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + var err error + var annotatedContext context.Context + annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/server.v1.ServerService/ListChangeLogs", runtime.WithHTTPPathPattern("/v1/server/updates/changelogs")) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := request_ServerService_ListChangeLogs_0(annotatedContext, inboundMarshaler, client, req, pathParams) + annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) + if err != nil { + runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) + return + } + + forward_ServerService_ListChangeLogs_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + }) + mux.Handle("POST", pattern_ServerService_StartUpdate_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() @@ -635,6 +696,8 @@ var ( pattern_ServerService_CheckUpdates_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v1", "server", "updates"}, "")) + pattern_ServerService_ListChangeLogs_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"v1", "server", "updates", "changelogs"}, "")) + pattern_ServerService_StartUpdate_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v1", "server", "updates"}, "start")) pattern_ServerService_UpdateStatus_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v1", "server", "updates"}, "getStatus")) @@ -653,6 +716,8 @@ var ( forward_ServerService_CheckUpdates_0 = runtime.ForwardResponseMessage + forward_ServerService_ListChangeLogs_0 = runtime.ForwardResponseMessage + forward_ServerService_StartUpdate_0 = runtime.ForwardResponseMessage forward_ServerService_UpdateStatus_0 = runtime.ForwardResponseMessage diff --git a/api/server/v1/server.pb.validate.go b/api/server/v1/server.pb.validate.go index 39897b8317..48dad7e546 100644 --- a/api/server/v1/server.pb.validate.go +++ b/api/server/v1/server.pb.validate.go @@ -998,6 +998,10 @@ func (m *DockerVersionInfo) validate(all bool) error { } } + // no validation rules for ReleaseNotesUrl + + // no validation rules for ReleaseNotesText + if len(errors) > 0 { return DockerVersionInfoMultiError(errors) } @@ -1271,6 +1275,273 @@ var _ interface { ErrorName() string } = CheckUpdatesResponseValidationError{} +// Validate checks the field values on ListChangeLogsRequest with the rules +// defined in the proto definition for this message. If any rules are +// violated, the first error encountered is returned, or nil if there are no violations. +func (m *ListChangeLogsRequest) Validate() error { + return m.validate(false) +} + +// ValidateAll checks the field values on ListChangeLogsRequest with the rules +// defined in the proto definition for this message. If any rules are +// violated, the result is a list of violation errors wrapped in +// ListChangeLogsRequestMultiError, or nil if none found. +func (m *ListChangeLogsRequest) ValidateAll() error { + return m.validate(true) +} + +func (m *ListChangeLogsRequest) validate(all bool) error { + if m == nil { + return nil + } + + var errors []error + + if len(errors) > 0 { + return ListChangeLogsRequestMultiError(errors) + } + + return nil +} + +// ListChangeLogsRequestMultiError is an error wrapping multiple validation +// errors returned by ListChangeLogsRequest.ValidateAll() if the designated +// constraints aren't met. +type ListChangeLogsRequestMultiError []error + +// Error returns a concatenation of all the error messages it wraps. +func (m ListChangeLogsRequestMultiError) Error() string { + var msgs []string + for _, err := range m { + msgs = append(msgs, err.Error()) + } + return strings.Join(msgs, "; ") +} + +// AllErrors returns a list of validation violation errors. +func (m ListChangeLogsRequestMultiError) AllErrors() []error { return m } + +// ListChangeLogsRequestValidationError is the validation error returned by +// ListChangeLogsRequest.Validate if the designated constraints aren't met. +type ListChangeLogsRequestValidationError struct { + field string + reason string + cause error + key bool +} + +// Field function returns field value. +func (e ListChangeLogsRequestValidationError) Field() string { return e.field } + +// Reason function returns reason value. +func (e ListChangeLogsRequestValidationError) Reason() string { return e.reason } + +// Cause function returns cause value. +func (e ListChangeLogsRequestValidationError) Cause() error { return e.cause } + +// Key function returns key value. +func (e ListChangeLogsRequestValidationError) Key() bool { return e.key } + +// ErrorName returns error name. +func (e ListChangeLogsRequestValidationError) ErrorName() string { + return "ListChangeLogsRequestValidationError" +} + +// Error satisfies the builtin error interface +func (e ListChangeLogsRequestValidationError) Error() string { + cause := "" + if e.cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.cause) + } + + key := "" + if e.key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sListChangeLogsRequest.%s: %s%s", + key, + e.field, + e.reason, + cause) +} + +var _ error = ListChangeLogsRequestValidationError{} + +var _ interface { + Field() string + Reason() string + Key() bool + Cause() error + ErrorName() string +} = ListChangeLogsRequestValidationError{} + +// Validate checks the field values on ListChangeLogsResponse with the rules +// defined in the proto definition for this message. If any rules are +// violated, the first error encountered is returned, or nil if there are no violations. +func (m *ListChangeLogsResponse) Validate() error { + return m.validate(false) +} + +// ValidateAll checks the field values on ListChangeLogsResponse with the rules +// defined in the proto definition for this message. If any rules are +// violated, the result is a list of violation errors wrapped in +// ListChangeLogsResponseMultiError, or nil if none found. +func (m *ListChangeLogsResponse) ValidateAll() error { + return m.validate(true) +} + +func (m *ListChangeLogsResponse) validate(all bool) error { + if m == nil { + return nil + } + + var errors []error + + for idx, item := range m.GetUpdates() { + _, _ = idx, item + + if all { + switch v := interface{}(item).(type) { + case interface{ ValidateAll() error }: + if err := v.ValidateAll(); err != nil { + errors = append(errors, ListChangeLogsResponseValidationError{ + field: fmt.Sprintf("Updates[%v]", idx), + reason: "embedded message failed validation", + cause: err, + }) + } + case interface{ Validate() error }: + if err := v.Validate(); err != nil { + errors = append(errors, ListChangeLogsResponseValidationError{ + field: fmt.Sprintf("Updates[%v]", idx), + reason: "embedded message failed validation", + cause: err, + }) + } + } + } else if v, ok := interface{}(item).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return ListChangeLogsResponseValidationError{ + field: fmt.Sprintf("Updates[%v]", idx), + reason: "embedded message failed validation", + cause: err, + } + } + } + + } + + if all { + switch v := interface{}(m.GetLastCheck()).(type) { + case interface{ ValidateAll() error }: + if err := v.ValidateAll(); err != nil { + errors = append(errors, ListChangeLogsResponseValidationError{ + field: "LastCheck", + reason: "embedded message failed validation", + cause: err, + }) + } + case interface{ Validate() error }: + if err := v.Validate(); err != nil { + errors = append(errors, ListChangeLogsResponseValidationError{ + field: "LastCheck", + reason: "embedded message failed validation", + cause: err, + }) + } + } + } else if v, ok := interface{}(m.GetLastCheck()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return ListChangeLogsResponseValidationError{ + field: "LastCheck", + reason: "embedded message failed validation", + cause: err, + } + } + } + + if len(errors) > 0 { + return ListChangeLogsResponseMultiError(errors) + } + + return nil +} + +// ListChangeLogsResponseMultiError is an error wrapping multiple validation +// errors returned by ListChangeLogsResponse.ValidateAll() if the designated +// constraints aren't met. +type ListChangeLogsResponseMultiError []error + +// Error returns a concatenation of all the error messages it wraps. +func (m ListChangeLogsResponseMultiError) Error() string { + var msgs []string + for _, err := range m { + msgs = append(msgs, err.Error()) + } + return strings.Join(msgs, "; ") +} + +// AllErrors returns a list of validation violation errors. +func (m ListChangeLogsResponseMultiError) AllErrors() []error { return m } + +// ListChangeLogsResponseValidationError is the validation error returned by +// ListChangeLogsResponse.Validate if the designated constraints aren't met. +type ListChangeLogsResponseValidationError struct { + field string + reason string + cause error + key bool +} + +// Field function returns field value. +func (e ListChangeLogsResponseValidationError) Field() string { return e.field } + +// Reason function returns reason value. +func (e ListChangeLogsResponseValidationError) Reason() string { return e.reason } + +// Cause function returns cause value. +func (e ListChangeLogsResponseValidationError) Cause() error { return e.cause } + +// Key function returns key value. +func (e ListChangeLogsResponseValidationError) Key() bool { return e.key } + +// ErrorName returns error name. +func (e ListChangeLogsResponseValidationError) ErrorName() string { + return "ListChangeLogsResponseValidationError" +} + +// Error satisfies the builtin error interface +func (e ListChangeLogsResponseValidationError) Error() string { + cause := "" + if e.cause != nil { + cause = fmt.Sprintf(" | caused by: %v", e.cause) + } + + key := "" + if e.key { + key = "key for " + } + + return fmt.Sprintf( + "invalid %sListChangeLogsResponse.%s: %s%s", + key, + e.field, + e.reason, + cause) +} + +var _ error = ListChangeLogsResponseValidationError{} + +var _ interface { + Field() string + Reason() string + Key() bool + Cause() error + ErrorName() string +} = ListChangeLogsResponseValidationError{} + // Validate checks the field values on StartUpdateRequest with the rules // defined in the proto definition for this message. If any rules are // violated, the first error encountered is returned, or nil if there are no violations. diff --git a/api/server/v1/server.proto b/api/server/v1/server.proto index a7785f2058..79841df710 100644 --- a/api/server/v1/server.proto +++ b/api/server/v1/server.proto @@ -71,6 +71,10 @@ message DockerVersionInfo { string tag = 2; // Release date. google.protobuf.Timestamp timestamp = 3; + // Release notes URL for the version (if available). + string release_notes_url = 4; + // Release notes text for the version (if available). + string release_notes_text = 5; } message CheckUpdatesResponse { @@ -86,6 +90,16 @@ message CheckUpdatesResponse { google.protobuf.Timestamp last_check = 5; } +message ListChangeLogsRequest {} + +message ListChangeLogsResponse { + // List of available updates. + repeated DockerVersionInfo updates = 1; + + // Last check time. + google.protobuf.Timestamp last_check = 2; +} + message StartUpdateRequest { string new_image = 1; } @@ -236,6 +250,14 @@ service ServerService { description: "Checks for available PMM Server updates." }; } + + rpc ListChangeLogs(ListChangeLogsRequest) returns (ListChangeLogsResponse) { + option (google.api.http) = {get: "/v1/server/updates/changelogs"}; + option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = { + summary: "List all the changes between the installed version and the latest available version" + description: "List all the changes between the installed version and the latest available version" + }; + } // StartUpdate starts PMM Server update. rpc StartUpdate(StartUpdateRequest) returns (StartUpdateResponse) { option (google.api.http) = { diff --git a/api/server/v1/server_grpc.pb.go b/api/server/v1/server_grpc.pb.go index 708f24cadf..0a33954455 100644 --- a/api/server/v1/server_grpc.pb.go +++ b/api/server/v1/server_grpc.pb.go @@ -24,6 +24,7 @@ const ( ServerService_Readiness_FullMethodName = "/server.v1.ServerService/Readiness" ServerService_LeaderHealthCheck_FullMethodName = "/server.v1.ServerService/LeaderHealthCheck" ServerService_CheckUpdates_FullMethodName = "/server.v1.ServerService/CheckUpdates" + ServerService_ListChangeLogs_FullMethodName = "/server.v1.ServerService/ListChangeLogs" ServerService_StartUpdate_FullMethodName = "/server.v1.ServerService/StartUpdate" ServerService_UpdateStatus_FullMethodName = "/server.v1.ServerService/UpdateStatus" ServerService_GetSettings_FullMethodName = "/server.v1.ServerService/GetSettings" @@ -45,6 +46,7 @@ type ServerServiceClient interface { LeaderHealthCheck(ctx context.Context, in *LeaderHealthCheckRequest, opts ...grpc.CallOption) (*LeaderHealthCheckResponse, error) // CheckUpdates checks for available PMM Server updates. CheckUpdates(ctx context.Context, in *CheckUpdatesRequest, opts ...grpc.CallOption) (*CheckUpdatesResponse, error) + ListChangeLogs(ctx context.Context, in *ListChangeLogsRequest, opts ...grpc.CallOption) (*ListChangeLogsResponse, error) // StartUpdate starts PMM Server update. StartUpdate(ctx context.Context, in *StartUpdateRequest, opts ...grpc.CallOption) (*StartUpdateResponse, error) // UpdateStatus returns PMM Server update status. @@ -103,6 +105,16 @@ func (c *serverServiceClient) CheckUpdates(ctx context.Context, in *CheckUpdates return out, nil } +func (c *serverServiceClient) ListChangeLogs(ctx context.Context, in *ListChangeLogsRequest, opts ...grpc.CallOption) (*ListChangeLogsResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(ListChangeLogsResponse) + err := c.cc.Invoke(ctx, ServerService_ListChangeLogs_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + func (c *serverServiceClient) StartUpdate(ctx context.Context, in *StartUpdateRequest, opts ...grpc.CallOption) (*StartUpdateResponse, error) { cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) out := new(StartUpdateResponse) @@ -158,6 +170,7 @@ type ServerServiceServer interface { LeaderHealthCheck(context.Context, *LeaderHealthCheckRequest) (*LeaderHealthCheckResponse, error) // CheckUpdates checks for available PMM Server updates. CheckUpdates(context.Context, *CheckUpdatesRequest) (*CheckUpdatesResponse, error) + ListChangeLogs(context.Context, *ListChangeLogsRequest) (*ListChangeLogsResponse, error) // StartUpdate starts PMM Server update. StartUpdate(context.Context, *StartUpdateRequest) (*StartUpdateResponse, error) // UpdateStatus returns PMM Server update status. @@ -192,6 +205,10 @@ func (UnimplementedServerServiceServer) CheckUpdates(context.Context, *CheckUpda return nil, status.Errorf(codes.Unimplemented, "method CheckUpdates not implemented") } +func (UnimplementedServerServiceServer) ListChangeLogs(context.Context, *ListChangeLogsRequest) (*ListChangeLogsResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method ListChangeLogs not implemented") +} + func (UnimplementedServerServiceServer) StartUpdate(context.Context, *StartUpdateRequest) (*StartUpdateResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method StartUpdate not implemented") } @@ -300,6 +317,24 @@ func _ServerService_CheckUpdates_Handler(srv interface{}, ctx context.Context, d return interceptor(ctx, in, info, handler) } +func _ServerService_ListChangeLogs_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(ListChangeLogsRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ServerServiceServer).ListChangeLogs(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: ServerService_ListChangeLogs_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ServerServiceServer).ListChangeLogs(ctx, req.(*ListChangeLogsRequest)) + } + return interceptor(ctx, in, info, handler) +} + func _ServerService_StartUpdate_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(StartUpdateRequest) if err := dec(in); err != nil { @@ -395,6 +430,10 @@ var ServerService_ServiceDesc = grpc.ServiceDesc{ MethodName: "CheckUpdates", Handler: _ServerService_CheckUpdates_Handler, }, + { + MethodName: "ListChangeLogs", + Handler: _ServerService_ListChangeLogs_Handler, + }, { MethodName: "StartUpdate", Handler: _ServerService_StartUpdate_Handler, diff --git a/api/swagger/swagger-dev.json b/api/swagger/swagger-dev.json index fa2acd03a6..c04bb18816 100644 --- a/api/swagger/swagger-dev.json +++ b/api/swagger/swagger-dev.json @@ -27418,6 +27418,16 @@ "type": "string", "format": "date-time", "x-order": 2 + }, + "release_notes_url": { + "description": "Release notes URL for the version (if available).", + "type": "string", + "x-order": 3 + }, + "release_notes_text": { + "description": "Release notes text for the version (if available).", + "type": "string", + "x-order": 4 } }, "x-order": 1 @@ -27477,6 +27487,101 @@ } } }, + "/v1/server/updates/changelogs": { + "get": { + "description": "List all the changes between the installed version and the latest available version", + "tags": [ + "ServerService" + ], + "summary": "List all the changes between the installed version and the latest available version", + "operationId": "ListChangeLogs", + "responses": { + "200": { + "description": "A successful response.", + "schema": { + "type": "object", + "properties": { + "updates": { + "description": "List of available updates.", + "type": "array", + "items": { + "type": "object", + "properties": { + "version": { + "description": "PMM Version.", + "type": "string", + "x-order": 0 + }, + "tag": { + "description": "Docker image tag.", + "type": "string", + "x-order": 1 + }, + "timestamp": { + "description": "Release date.", + "type": "string", + "format": "date-time", + "x-order": 2 + }, + "release_notes_url": { + "description": "Release notes URL for the version (if available).", + "type": "string", + "x-order": 3 + }, + "release_notes_text": { + "description": "Release notes text for the version (if available).", + "type": "string", + "x-order": 4 + } + } + }, + "x-order": 0 + }, + "last_check": { + "description": "Last check time.", + "type": "string", + "format": "date-time", + "x-order": 1 + } + } + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "type": "object", + "properties": { + "code": { + "type": "integer", + "format": "int32", + "x-order": 0 + }, + "message": { + "type": "string", + "x-order": 1 + }, + "details": { + "type": "array", + "items": { + "description": "`Any` contains an arbitrary serialized protocol buffer message along with a\nURL that describes the type of the serialized message.\n\nProtobuf library provides support to pack/unpack Any values in the form\nof utility functions or additional generated methods of the Any type.\n\nExample 1: Pack and unpack a message in C++.\n\n Foo foo = ...;\n Any any;\n any.PackFrom(foo);\n ...\n if (any.UnpackTo(\u0026foo)) {\n ...\n }\n\nExample 2: Pack and unpack a message in Java.\n\n Foo foo = ...;\n Any any = Any.pack(foo);\n ...\n if (any.is(Foo.class)) {\n foo = any.unpack(Foo.class);\n }\n // or ...\n if (any.isSameTypeAs(Foo.getDefaultInstance())) {\n foo = any.unpack(Foo.getDefaultInstance());\n }\n\n Example 3: Pack and unpack a message in Python.\n\n foo = Foo(...)\n any = Any()\n any.Pack(foo)\n ...\n if any.Is(Foo.DESCRIPTOR):\n any.Unpack(foo)\n ...\n\n Example 4: Pack and unpack a message in Go\n\n foo := \u0026pb.Foo{...}\n any, err := anypb.New(foo)\n if err != nil {\n ...\n }\n ...\n foo := \u0026pb.Foo{}\n if err := any.UnmarshalTo(foo); err != nil {\n ...\n }\n\nThe pack methods provided by protobuf library will by default use\n'type.googleapis.com/full.type.name' as the type URL and the unpack\nmethods only use the fully qualified type name after the last '/'\nin the type URL, for example \"foo.bar.com/x/y.z\" will yield type\nname \"y.z\".\n\nJSON\n====\nThe JSON representation of an `Any` value uses the regular\nrepresentation of the deserialized, embedded message, with an\nadditional field `@type` which contains the type URL. Example:\n\n package google.profile;\n message Person {\n string first_name = 1;\n string last_name = 2;\n }\n\n {\n \"@type\": \"type.googleapis.com/google.profile.Person\",\n \"firstName\": \u003cstring\u003e,\n \"lastName\": \u003cstring\u003e\n }\n\nIf the embedded message type is well-known and has a custom JSON\nrepresentation, that representation will be embedded adding a field\n`value` which holds the custom JSON in addition to the `@type`\nfield. Example (for message [google.protobuf.Duration][]):\n\n {\n \"@type\": \"type.googleapis.com/google.protobuf.Duration\",\n \"value\": \"1.212s\"\n }", + "type": "object", + "properties": { + "@type": { + "description": "A URL/resource name that uniquely identifies the type of the serialized\nprotocol buffer message. This string must contain at least\none \"/\" character. The last segment of the URL's path must represent\nthe fully qualified name of the type (as in\n`path/google.protobuf.Duration`). The name should be in a canonical form\n(e.g., leading \".\" is not accepted).\n\nIn practice, teams usually precompile into the binary all types that they\nexpect it to use in the context of Any. However, for URLs which use the\nscheme `http`, `https`, or no scheme, one can optionally set up a type\nserver that maps type URLs to message definitions as follows:\n\n* If no scheme is provided, `https` is assumed.\n* An HTTP GET on the URL must yield a [google.protobuf.Type][]\n value in binary format, or produce an error.\n* Applications are allowed to cache lookup results based on the\n URL, or have them precompiled into a binary to avoid any\n lookup. Therefore, binary compatibility needs to be preserved\n on changes to types. (Use versioned type names to manage\n breaking changes.)\n\nNote: this functionality is not currently available in the official\nprotobuf release, and it is not used for type URLs beginning with\ntype.googleapis.com. As of May 2023, there are no widely used type server\nimplementations and no plans to implement one.\n\nSchemes other than `http`, `https` (or the empty scheme) might be\nused with implementation specific semantics.", + "type": "string", + "x-order": 0 + } + }, + "additionalProperties": false + }, + "x-order": 2 + } + } + } + } + } + } + }, "/v1/server/updates:getStatus": { "post": { "description": "Returns PMM Server update status.", diff --git a/api/swagger/swagger.json b/api/swagger/swagger.json index 1a8543e12f..d4f0128cbb 100644 --- a/api/swagger/swagger.json +++ b/api/swagger/swagger.json @@ -26460,6 +26460,16 @@ "type": "string", "format": "date-time", "x-order": 2 + }, + "release_notes_url": { + "description": "Release notes URL for the version (if available).", + "type": "string", + "x-order": 3 + }, + "release_notes_text": { + "description": "Release notes text for the version (if available).", + "type": "string", + "x-order": 4 } }, "x-order": 1 @@ -26519,6 +26529,101 @@ } } }, + "/v1/server/updates/changelogs": { + "get": { + "description": "List all the changes between the installed version and the latest available version", + "tags": [ + "ServerService" + ], + "summary": "List all the changes between the installed version and the latest available version", + "operationId": "ListChangeLogs", + "responses": { + "200": { + "description": "A successful response.", + "schema": { + "type": "object", + "properties": { + "updates": { + "description": "List of available updates.", + "type": "array", + "items": { + "type": "object", + "properties": { + "version": { + "description": "PMM Version.", + "type": "string", + "x-order": 0 + }, + "tag": { + "description": "Docker image tag.", + "type": "string", + "x-order": 1 + }, + "timestamp": { + "description": "Release date.", + "type": "string", + "format": "date-time", + "x-order": 2 + }, + "release_notes_url": { + "description": "Release notes URL for the version (if available).", + "type": "string", + "x-order": 3 + }, + "release_notes_text": { + "description": "Release notes text for the version (if available).", + "type": "string", + "x-order": 4 + } + } + }, + "x-order": 0 + }, + "last_check": { + "description": "Last check time.", + "type": "string", + "format": "date-time", + "x-order": 1 + } + } + } + }, + "default": { + "description": "An unexpected error response.", + "schema": { + "type": "object", + "properties": { + "code": { + "type": "integer", + "format": "int32", + "x-order": 0 + }, + "message": { + "type": "string", + "x-order": 1 + }, + "details": { + "type": "array", + "items": { + "description": "`Any` contains an arbitrary serialized protocol buffer message along with a\nURL that describes the type of the serialized message.\n\nProtobuf library provides support to pack/unpack Any values in the form\nof utility functions or additional generated methods of the Any type.\n\nExample 1: Pack and unpack a message in C++.\n\n Foo foo = ...;\n Any any;\n any.PackFrom(foo);\n ...\n if (any.UnpackTo(\u0026foo)) {\n ...\n }\n\nExample 2: Pack and unpack a message in Java.\n\n Foo foo = ...;\n Any any = Any.pack(foo);\n ...\n if (any.is(Foo.class)) {\n foo = any.unpack(Foo.class);\n }\n // or ...\n if (any.isSameTypeAs(Foo.getDefaultInstance())) {\n foo = any.unpack(Foo.getDefaultInstance());\n }\n\n Example 3: Pack and unpack a message in Python.\n\n foo = Foo(...)\n any = Any()\n any.Pack(foo)\n ...\n if any.Is(Foo.DESCRIPTOR):\n any.Unpack(foo)\n ...\n\n Example 4: Pack and unpack a message in Go\n\n foo := \u0026pb.Foo{...}\n any, err := anypb.New(foo)\n if err != nil {\n ...\n }\n ...\n foo := \u0026pb.Foo{}\n if err := any.UnmarshalTo(foo); err != nil {\n ...\n }\n\nThe pack methods provided by protobuf library will by default use\n'type.googleapis.com/full.type.name' as the type URL and the unpack\nmethods only use the fully qualified type name after the last '/'\nin the type URL, for example \"foo.bar.com/x/y.z\" will yield type\nname \"y.z\".\n\nJSON\n====\nThe JSON representation of an `Any` value uses the regular\nrepresentation of the deserialized, embedded message, with an\nadditional field `@type` which contains the type URL. Example:\n\n package google.profile;\n message Person {\n string first_name = 1;\n string last_name = 2;\n }\n\n {\n \"@type\": \"type.googleapis.com/google.profile.Person\",\n \"firstName\": \u003cstring\u003e,\n \"lastName\": \u003cstring\u003e\n }\n\nIf the embedded message type is well-known and has a custom JSON\nrepresentation, that representation will be embedded adding a field\n`value` which holds the custom JSON in addition to the `@type`\nfield. Example (for message [google.protobuf.Duration][]):\n\n {\n \"@type\": \"type.googleapis.com/google.protobuf.Duration\",\n \"value\": \"1.212s\"\n }", + "type": "object", + "properties": { + "@type": { + "description": "A URL/resource name that uniquely identifies the type of the serialized\nprotocol buffer message. This string must contain at least\none \"/\" character. The last segment of the URL's path must represent\nthe fully qualified name of the type (as in\n`path/google.protobuf.Duration`). The name should be in a canonical form\n(e.g., leading \".\" is not accepted).\n\nIn practice, teams usually precompile into the binary all types that they\nexpect it to use in the context of Any. However, for URLs which use the\nscheme `http`, `https`, or no scheme, one can optionally set up a type\nserver that maps type URLs to message definitions as follows:\n\n* If no scheme is provided, `https` is assumed.\n* An HTTP GET on the URL must yield a [google.protobuf.Type][]\n value in binary format, or produce an error.\n* Applications are allowed to cache lookup results based on the\n URL, or have them precompiled into a binary to avoid any\n lookup. Therefore, binary compatibility needs to be preserved\n on changes to types. (Use versioned type names to manage\n breaking changes.)\n\nNote: this functionality is not currently available in the official\nprotobuf release, and it is not used for type URLs beginning with\ntype.googleapis.com. As of May 2023, there are no widely used type server\nimplementations and no plans to implement one.\n\nSchemes other than `http`, `https` (or the empty scheme) might be\nused with implementation specific semantics.", + "type": "string", + "x-order": 0 + } + }, + "additionalProperties": false + }, + "x-order": 2 + } + } + } + } + } + } + }, "/v1/server/updates:getStatus": { "post": { "description": "Returns PMM Server update status.", diff --git a/docker-compose.yml b/docker-compose.yml index be66d5f014..06341c92cd 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -25,8 +25,7 @@ services: - PMM_WATCHTOWER_HOST=${PMM_WATCHTOWER_HOST:-http://watchtower:8080} - PMM_WATCHTOWER_TOKEN=${PMM_WATCHTOWER_TOKEN:-INSECURE_TOKEN} - PMM_RELEASE_VERSION=3.0.0-alpha - # - PMM_DEV_PERCONA_PLATFORM_ADDRESS=https://check.localhost - # - PMM_DEV_PERCONA_PLATFORM_INSECURE=1 + # - PMM_DEV_VERSION_SERVICE_URL=http://localhost:11000 # - PMM_DEV_PERCONA_PLATFORM_PUBLIC_KEY= # - PMM_DEV_TELEMETRY_INTERVAL=10s # - PMM_DEV_TELEMETRY_DISABLE_START_DELAY=1 diff --git a/managed/services/server/server.go b/managed/services/server/server.go index 051214bf8c..2a2a358308 100644 --- a/managed/services/server/server.go +++ b/managed/services/server/server.go @@ -269,8 +269,10 @@ func (s *Server) CheckUpdates(ctx context.Context, req *serverv1.CheckUpdatesReq Timestamp: timestamppb.New(*v.Installed.BuildTime), }, Latest: &serverv1.DockerVersionInfo{ - Version: v.Latest.Version.String(), - Tag: v.Latest.DockerImage, + Version: v.Latest.Version.String(), + Tag: v.Latest.DockerImage, + ReleaseNotesUrl: v.Latest.ReleaseNotesURL, + ReleaseNotesText: v.Latest.ReleaseNotesText, }, UpdateAvailable: v.Latest.DockerImage != "", LatestNewsUrl: v.LatestNewsURL, @@ -295,6 +297,30 @@ func (s *Server) CheckUpdates(ctx context.Context, req *serverv1.CheckUpdatesReq return res, nil } +// ListChangeLogs lists PMM versions between currently installed version and the latest one. +func (s *Server) ListChangeLogs(ctx context.Context, req *serverv1.ListChangeLogsRequest) (*serverv1.ListChangeLogsResponse, error) { + versions, err := s.updater.ListUpdates(ctx) + if err != nil { + return nil, status.Error(codes.Unavailable, "failed to list available updates") + } + + updates := make([]*serverv1.DockerVersionInfo, 0, len(versions)) + for _, v := range versions { + updates = append(updates, &serverv1.DockerVersionInfo{ + Version: v.Version.String(), + Tag: v.DockerImage, + ReleaseNotesText: v.ReleaseNotesText, + ReleaseNotesUrl: v.ReleaseNotesURL, + }) + } + res := &serverv1.ListChangeLogsResponse{ + Updates: updates, + LastCheck: timestamppb.Now(), + } + + return res, nil +} + // StartUpdate starts PMM Server update. func (s *Server) StartUpdate(ctx context.Context, req *serverv1.StartUpdateRequest) (*serverv1.StartUpdateResponse, error) { s.envRW.RLock() @@ -307,7 +333,7 @@ func (s *Server) StartUpdate(ctx context.Context, req *serverv1.StartUpdateReque newImage := req.GetNewImage() if newImage == "" { - latest, err := s.updater.latest(ctx) + _, latest, err := s.updater.latest(ctx) if err != nil { s.l.WithError(err).Error("Failed to get latest version") newImage = defaultLatestPMMImage diff --git a/managed/services/server/updater.go b/managed/services/server/updater.go index 62683a7643..5f1a30fdc6 100644 --- a/managed/services/server/updater.go +++ b/managed/services/server/updater.go @@ -25,6 +25,7 @@ import ( "net/http" "net/url" "os" + "sort" "strings" "sync" "time" @@ -39,11 +40,12 @@ import ( // defaultLatestPMMImage is the default image name to use when the latest version cannot be determined. const ( - defaultLatestPMMImage = "perconalab/pmm-server:3-dev-latest" - pmmUpdatePerformLog = "/srv/logs/pmm-update-perform-init.log" - updateCheckInterval = 24 * time.Hour - updateCheckResultFresh = updateCheckInterval + 10*time.Minute - updateDefaultTimeout = 30 * time.Second + defaultLatestPMMImage = "perconalab/pmm-server:3-dev-latest" + pmmUpdatePerformLog = "/srv/logs/pmm-update-perform-init.log" + defaultVersionServiceAddress = "https://check-dev.percona.com" + updateCheckInterval = 24 * time.Hour + updateCheckResultFresh = updateCheckInterval + 10*time.Minute + updateDefaultTimeout = 30 * time.Second ) var fileName = "/etc/pmm-server-update-version.json" @@ -60,6 +62,10 @@ type Updater struct { checkRW sync.RWMutex lastCheckResult *version.DockerVersionInfo lastCheckTime time.Time + + // releaseNotes holds a map of PMM server versions to their release notes. + releaseNotes map[string]string + releaseNotesRW sync.RWMutex } // NewUpdater creates a new Updater service. @@ -68,6 +74,7 @@ func NewUpdater(watchtowerHost *url.URL, gRPCMessageMaxSize uint32) *Updater { l: logrus.WithField("service", "updater"), watchtowerHost: watchtowerHost, gRPCMessageMaxSize: gRPCMessageMaxSize, + releaseNotes: make(map[string]string), } return u } @@ -181,20 +188,29 @@ func (up *Updater) LastCheckUpdatesResult(ctx context.Context) (*version.UpdateC }, lastCheckTime } -func (up *Updater) latest(ctx context.Context) (*version.DockerVersionInfo, error) { +// ListUpdates returns the list of available versions between installed and latest. +func (up *Updater) ListUpdates(ctx context.Context) ([]*version.DockerVersionInfo, error) { + all, _, err := up.latest(ctx) + if err != nil { + return nil, err + } + return all, nil +} + +func (up *Updater) latest(ctx context.Context) ([]*version.DockerVersionInfo, *version.DockerVersionInfo, error) { info, err := up.readFromFile() if err != nil { - return nil, errors.Wrap(err, "failed to read from file") + return nil, nil, errors.Wrap(err, "failed to read from file") } if info != nil { - return info, nil + return nil, info, nil } if os.Getenv("PMM_DEV_UPDATE_DOCKER_IMAGE") != "" { return up.parseDockerTag(os.Getenv("PMM_DEV_UPDATE_DOCKER_IMAGE")) } - // If file does not exist, and ENV variable is not set, go get the latest tag from DockerHub - return up.latestAvailableFromDockerHub(ctx) + // If file does not exist, and ENV variable is not set, go get the latest versions from Percona version service. + return up.latestAvailableFromVersionService(ctx) } func (up *Updater) readFromFile() (*version.DockerVersionInfo, error) { @@ -217,104 +233,144 @@ func (up *Updater) readFromFile() (*version.DockerVersionInfo, error) { } type result struct { - Name string `json:"name"` - TagLastPushed time.Time `json:"tag_last_pushed"` + Version string `json:"version"` + ImageInfo imageInfo `json:"imageInfo"` } -// TagsResponse is a response from DockerHub. -type TagsResponse struct { - Results []result `json:"results"` +type imageInfo struct { + ImagePath string `json:"imagePath"` + ImageReleaseTimestamp time.Time `json:"imageReleaseTimestamp"` } -// latestAvailableFromDockerHub returns the latest available version from DockerHub. -// It returns the latest minor version for the current major version. -// If the current version is the latest minor version, it returns the next major version. -// If the current version is the latest version, it returns the current version. -func (up *Updater) latestAvailableFromDockerHub(ctx context.Context) (*version.DockerVersionInfo, error) { - repo := os.Getenv("PMM_DEV_UPDATE_DOCKER_REPO") - if repo == "" { - repo = "percona/pmm-server" - } - u := "https://registry.hub.docker.com/v2/repositories/" + repo + "/tags/?page_size=100" +// MetadataResponse is a response from the metadata endpoint on Percona version service. +type MetadataResponse struct { + Versions []result `json:"versions"` +} + +// ReleaseNotesResponse is a response from the release-notes endpoint on Percona version service. +type ReleaseNotesResponse struct { + ReleaseNote string `json:"releaseNote"` +} + +// latestAvailableFromVersionService queries Percona version service and returns: +// - list of versions between the installed version and the latest version (inclusive) +// - the latest available version (i.e., the latest minor version for the current major version). +// If the current version is the latest minor version, it returns the next major version as the latest. +// If the current version is the latest version, it returns the current version as the latest. +func (up *Updater) latestAvailableFromVersionService(ctx context.Context) ([]*version.DockerVersionInfo, *version.DockerVersionInfo, error) { + versionServiceUrl := os.Getenv("PMM_DEV_VERSION_SERVICE_URL") + if versionServiceUrl == "" { + versionServiceUrl = defaultVersionServiceAddress + } + u := versionServiceUrl + "/metadata/v1/pmm-server" req, err := http.NewRequestWithContext(ctx, http.MethodGet, u, nil) if err != nil { up.l.WithError(err).Error("Failed to create request") - return nil, errors.Wrap(err, "failed to create request") + return nil, nil, errors.Wrap(err, "failed to create request") } resp, err := http.DefaultClient.Do(req) if err != nil { - up.l.WithError(err).Error("Failed to get tags from DockerHub") - return nil, errors.Wrap(err, "failed to get tags from DockerHub") + up.l.WithError(err).Error("Failed to get PMM server versions") + return nil, nil, errors.Wrap(err, "failed to get PMM server versions") } defer resp.Body.Close() //nolint:errcheck - var tagsResponse TagsResponse - if err := json.NewDecoder(resp.Body).Decode(&tagsResponse); err != nil { + var metadataResponse MetadataResponse + if err := json.NewDecoder(resp.Body).Decode(&metadataResponse); err != nil { up.l.WithError(err).Error("Failed to decode response") - return nil, errors.Wrap(err, "failed to decode response") + return nil, nil, errors.Wrap(err, "failed to decode response") } - if len(tagsResponse.Results) != 0 { - up.l.Infof("Found %d tags", len(tagsResponse.Results)) - next := up.next(*up.currentVersion(), tagsResponse.Results) - if next.DockerImage != "" { - next.DockerImage = repo + ":" + next.DockerImage - } - return next, err + if len(metadataResponse.Versions) != 0 { + up.l.Infof("Found %d versions", len(metadataResponse.Versions)) + updates, next := up.next(*up.currentVersion(), metadataResponse.Versions) + return updates, next, err } - return nil, errors.New("no tags found") + return nil, nil, errors.New("no tags found") } -func (up *Updater) parseDockerTag(tag string) (*version.DockerVersionInfo, error) { +func (up *Updater) parseDockerTag(tag string) ([]*version.DockerVersionInfo, *version.DockerVersionInfo, error) { splitTag := strings.Split(tag, ":") if len(splitTag) != 2 { - return nil, fmt.Errorf("invalid tag: %s", tag) + return nil, nil, fmt.Errorf("invalid tag: %s", tag) } parsed, err := version.Parse(splitTag[1]) if err != nil { up.l.Debugf("Failed to parse version: %s", splitTag[1]) - return &version.DockerVersionInfo{DockerImage: tag}, nil //nolint:nilerr + return nil, &version.DockerVersionInfo{DockerImage: tag}, nil //nolint:nilerr } - return &version.DockerVersionInfo{ + return nil, &version.DockerVersionInfo{ Version: *parsed, DockerImage: tag, }, nil } -func (up *Updater) next(currentVersion version.Parsed, results []result) *version.DockerVersionInfo { +func (up *Updater) next(currentVersion version.Parsed, results []result) ([]*version.DockerVersionInfo, *version.DockerVersionInfo) { + repo := os.Getenv("PMM_DEV_UPDATE_DOCKER_REPO") + if repo == "" { + repo = "percona/pmm-server" + } nextMinor := &version.DockerVersionInfo{ Version: currentVersion, } + updates := version.DockerVersionsInfo{} var nextMajor *version.DockerVersionInfo for _, result := range results { - v, err := version.Parse(result.Name) + v, err := version.Parse(result.Version) if err != nil { - up.l.Debugf("Failed to parse version: %s", result.Name) + up.l.Debugf("Failed to parse version: %s", result.Version) continue } if !currentVersion.Less(v) { continue } - if v.Major == currentVersion.Major && nextMinor.Version.Less(v) { // next major + releaseNotesURL := "https://per.co.na/pmm/" + v.String() + releaseNote, err := up.getReleaseNotesText(context.Background(), *v) + if err != nil { + up.l.Errorf("Failed to get release notes for version: %s, %s", v.String(), err.Error()) + } + + dockerImage := result.ImageInfo.ImagePath + if dockerImage == "" { + dockerImage = repo + ":" + result.Version + } + // versions with pre-lease labels (e.g 2.40.1-rc) are not considered for the update diffs + if v.Rest == "" && currentVersion.Less(v) { + updates = append(updates, &version.DockerVersionInfo{ + Version: *v, + DockerImage: dockerImage, + BuildTime: result.ImageInfo.ImageReleaseTimestamp, + ReleaseNotesURL: releaseNotesURL, + ReleaseNotesText: releaseNote, + }) + } + + if v.Major == currentVersion.Major && nextMinor.Version.Less(v) { nextMinor = &version.DockerVersionInfo{ - Version: *v, - DockerImage: result.Name, - BuildTime: result.TagLastPushed, + Version: *v, + DockerImage: dockerImage, + BuildTime: result.ImageInfo.ImageReleaseTimestamp, + ReleaseNotesURL: releaseNotesURL, + ReleaseNotesText: releaseNote, } } if v.Major > currentVersion.Major && (nextMajor == nil || (nextMajor.Version.Less(v) && nextMajor.Version.Major == v.Major) || v.Major < nextMajor.Version.Major) { nextMajor = &version.DockerVersionInfo{ - Version: *v, - DockerImage: result.Name, - BuildTime: result.TagLastPushed, + Version: *v, + DockerImage: dockerImage, + BuildTime: result.ImageInfo.ImageReleaseTimestamp, + ReleaseNotesURL: releaseNotesURL, + ReleaseNotesText: releaseNote, } } } + + sort.Sort(updates) if nextMinor.Version == currentVersion && nextMajor != nil { - return nextMajor + return updates, nextMajor } - return nextMinor + return updates, nextMinor } // InstalledPMMVersion returns the currently installed PMM version. @@ -389,7 +445,7 @@ func (up *Updater) check(ctx context.Context) error { up.checkRW.Lock() defer up.checkRW.Unlock() - latest, err := up.latest(ctx) + _, latest, err := up.latest(ctx) if err != nil { return errors.Wrap(err, "failed to get latest version") } @@ -420,3 +476,48 @@ func isHostAvailable(host string, port string, timeout time.Duration) bool { } return false } + +// getReleaseNotesText is a placeholder for getting release notes in MarkDown format +// until we finalize the implementation on version service. +func (up *Updater) getReleaseNotesText(ctx context.Context, version version.Parsed) (string, error) { + if version.Rest != "" { + version.Rest = "" + } + + up.releaseNotesRW.Lock() + defer up.releaseNotesRW.Unlock() + versionString := version.String() + if releaseNotes, ok := up.releaseNotes[versionString]; ok { + return releaseNotes, nil + } + + versionServiceUrl := os.Getenv("PMM_DEV_VERSION_SERVICE_URL") + if versionServiceUrl == "" { + versionServiceUrl = defaultVersionServiceAddress + } + u := versionServiceUrl + "/release-notes/v1/pmm/" + versionString + req, err := http.NewRequestWithContext(ctx, http.MethodGet, u, nil) + if err != nil { + up.l.WithError(err).Error("Failed to create request") + return "", errors.Wrap(err, "failed to create request") + } + resp, err := http.DefaultClient.Do(req) + if err != nil { + up.l.WithError(err).Errorf("Failed to get release note for version: %s", versionString) + return "", errors.Wrapf(err, "failed to get release notes for version: %s", versionString) + } + + if resp.StatusCode != http.StatusOK { + up.l.Errorf("Failed to get release notes for PMM %s, got HTTP %d", version.String(), resp.StatusCode) + return "", nil + } + defer resp.Body.Close() //nolint:errcheck + var rnResponse ReleaseNotesResponse + if err := json.NewDecoder(resp.Body).Decode(&rnResponse); err != nil { + up.l.WithError(err).Error("Failed to decode response") + return "", errors.Wrap(err, "failed to decode response") + } + + up.releaseNotes[versionString] = rnResponse.ReleaseNote + return rnResponse.ReleaseNote, nil +} diff --git a/managed/services/server/updater_test.go b/managed/services/server/updater_test.go index 3f033bfbb9..8d5ff848c7 100644 --- a/managed/services/server/updater_test.go +++ b/managed/services/server/updater_test.go @@ -20,6 +20,7 @@ import ( "net/url" "os" "path/filepath" + "sort" "strings" "testing" "time" @@ -66,7 +67,7 @@ func TestUpdater(t *testing.T) { args: args{ currentVersion: "3.0.0", results: []result{ - {Name: "3.0.0"}, + {Version: "3.0.0"}, }, }, want: &versionInfo{ @@ -79,14 +80,14 @@ func TestUpdater(t *testing.T) { args: args{ currentVersion: "3.0.0", results: []result{ - {Name: "3.2.0"}, - {Name: "3.1.0"}, - {Name: "3.0.0"}, + {Version: "3.2.0"}, + {Version: "3.1.0"}, + {Version: "3.0.0"}, }, }, want: &versionInfo{ Version: "3.2.0", - DockerImage: "3.2.0", + DockerImage: "percona/pmm-server:3.2.0", }, }, { @@ -94,13 +95,18 @@ func TestUpdater(t *testing.T) { args: args{ currentVersion: "3.0.0", results: []result{ - {Name: "3.0.0"}, - {Name: "3.0.1", TagLastPushed: time.Date(2024, 3, 20, 15, 48, 7, 145620000, time.UTC)}, + {Version: "3.0.0"}, + { + Version: "3.0.1", + ImageInfo: imageInfo{ + ImageReleaseTimestamp: time.Date(2024, 3, 20, 15, 48, 7, 145620000, time.UTC), + }, + }, }, }, want: &versionInfo{ Version: "3.0.1", - DockerImage: "3.0.1", + DockerImage: "percona/pmm-server:3.0.1", BuildTime: pointer.To(time.Date(2024, 3, 20, 15, 48, 7, 145620000, time.UTC)), }, }, @@ -109,13 +115,13 @@ func TestUpdater(t *testing.T) { args: args{ currentVersion: "3.0.0", results: []result{ - {Name: "4.0.0"}, - {Name: "3.0.0"}, + {Version: "4.0.0"}, + {Version: "3.0.0"}, }, }, want: &versionInfo{ Version: "4.0.0", - DockerImage: "4.0.0", + DockerImage: "percona/pmm-server:4.0.0", }, }, { @@ -123,14 +129,14 @@ func TestUpdater(t *testing.T) { args: args{ currentVersion: "3.0.0", results: []result{ - {Name: "4.0.0"}, - {Name: "3.0.0"}, - {Name: "4.0.0-rc"}, + {Version: "4.0.0"}, + {Version: "3.0.0"}, + {Version: "4.0.0-rc"}, }, }, want: &versionInfo{ Version: "4.0.0", - DockerImage: "4.0.0", + DockerImage: "percona/pmm-server:4.0.0", }, }, { @@ -138,15 +144,15 @@ func TestUpdater(t *testing.T) { args: args{ currentVersion: "3.3.0", results: []result{ - {Name: "4.1.0"}, - {Name: "4.0.0"}, - {Name: "3.0.0"}, - {Name: "5.1.0"}, + {Version: "4.1.0"}, + {Version: "4.0.0"}, + {Version: "3.0.0"}, + {Version: "5.1.0"}, }, }, want: &versionInfo{ Version: "4.1.0", - DockerImage: "4.1.0", + DockerImage: "percona/pmm-server:4.1.0", }, }, { @@ -154,15 +160,15 @@ func TestUpdater(t *testing.T) { args: args{ currentVersion: "3.0.0", results: []result{ - {Name: "4.1.0"}, - {Name: "4.0.0"}, - {Name: "3.0.0"}, - {Name: "3.1.0"}, + {Version: "4.1.0"}, + {Version: "4.0.0"}, + {Version: "3.0.0"}, + {Version: "3.1.0"}, }, }, want: &versionInfo{ Version: "3.1.0", - DockerImage: "3.1.0", + DockerImage: "percona/pmm-server:3.1.0", }, }, { @@ -170,14 +176,14 @@ func TestUpdater(t *testing.T) { args: args{ currentVersion: "3.0.0", results: []result{ - {Name: "3.0.0"}, - {Name: "3.1.0"}, - {Name: "invalid"}, + {Version: "3.0.0"}, + {Version: "3.1.0"}, + {Version: "invalid"}, }, }, want: &versionInfo{ Version: "3.1.0", - DockerImage: "3.1.0", + DockerImage: "percona/pmm-server:3.1.0", }, }, { @@ -185,8 +191,8 @@ func TestUpdater(t *testing.T) { args: args{ currentVersion: "3.0.0", results: []result{ - {Name: "3.0.0"}, - {Name: "3.1"}, + {Version: "3.0.0"}, + {Version: "3.1"}, }, }, want: &versionInfo{ @@ -199,14 +205,14 @@ func TestUpdater(t *testing.T) { args: args{ currentVersion: "3.0.0", results: []result{ - {Name: "3.0.0"}, - {Name: "3.1.0-rc"}, - {Name: "3.1.0-rc757"}, + {Version: "3.0.0"}, + {Version: "3.1.0-rc"}, + {Version: "3.1.0-rc757"}, }, }, want: &versionInfo{ Version: "3.1.0-rc757", - DockerImage: "3.1.0-rc757", + DockerImage: "percona/pmm-server:3.1.0-rc757", }, }, { @@ -214,15 +220,15 @@ func TestUpdater(t *testing.T) { args: args{ currentVersion: "3.0.0", results: []result{ - {Name: "3.0.0"}, - {Name: "3.1.0"}, - {Name: "3.1.0-rc"}, - {Name: "3.1.0-rc757"}, + {Version: "3.0.0"}, + {Version: "3.1.0"}, + {Version: "3.1.0-rc"}, + {Version: "3.1.0-rc757"}, }, }, want: &versionInfo{ Version: "3.1.0", - DockerImage: "3.1.0", + DockerImage: "percona/pmm-server:3.1.0", }, }, } @@ -233,7 +239,7 @@ func TestUpdater(t *testing.T) { u := NewUpdater(watchtowerURL, gRPCMessageMaxSize) parsed, err := version.Parse(tt.args.currentVersion) require.NoError(t, err) - next := u.next(*parsed, tt.args.results) + _, next := u.next(*parsed, tt.args.results) require.NoError(t, err) assert.Equal(t, tt.want.Version, next.Version.String()) assert.Equal(t, tt.want.DockerImage, next.DockerImage) @@ -245,14 +251,29 @@ func TestUpdater(t *testing.T) { } }) + t.Run("TestSortedVersionList", func(t *testing.T) { + versions := version.DockerVersionsInfo{ + {Version: *version.MustParse("3.0.0")}, + {Version: *version.MustParse("3.1.0")}, + {Version: *version.MustParse("3.0.1")}, + {Version: *version.MustParse("3.0.0-rc")}, + } + + sort.Sort(versions) + assert.Equal(t, "3.0.0-rc", versions[0].Version.String()) + assert.Equal(t, "3.0.0", versions[1].Version.String()) + assert.Equal(t, "3.0.1", versions[2].Version.String()) + assert.Equal(t, "3.1.0", versions[3].Version.String()) + }) + t.Run("TestLatest", func(t *testing.T) { version.Version = "2.41.0" u := NewUpdater(watchtowerURL, gRPCMessageMaxSize) - latest, err := u.latest(context.Background()) + _, latest, err := u.latest(context.Background()) require.NoError(t, err) assert.NotNil(t, latest) assert.True(t, strings.HasPrefix(latest.Version.String(), "2.") || strings.HasPrefix(latest.Version.String(), "3."), - "latest version of PMM 2 should have prefix 2.") + "latest version of PMM should have either a '2.' or '3.' prefix") }) t.Run("TestParseFile", func(t *testing.T) { @@ -265,7 +286,7 @@ func TestUpdater(t *testing.T) { require.NoError(t, err) u := NewUpdater(watchtowerURL, gRPCMessageMaxSize) - latest, err := u.latest(context.Background()) + _, latest, err := u.latest(context.Background()) require.NoError(t, err) assert.Equal(t, "2.41.1", latest.Version.String()) assert.Equal(t, "2.41.1", latest.DockerImage) diff --git a/version/update.go b/version/update.go index 235004df4d..8c1e4967f3 100644 --- a/version/update.go +++ b/version/update.go @@ -40,7 +40,22 @@ type UpdateCheckResult struct { // DockerVersionInfo describes the version of the Docker image. type DockerVersionInfo struct { - Version Parsed `json:"version"` - DockerImage string `json:"docker_image"` - BuildTime time.Time `json:"build_time"` + Version Parsed `json:"version"` + DockerImage string `json:"docker_image"` + BuildTime time.Time `json:"build_time"` + ReleaseNotesURL string `json:"release_notes_url"` + ReleaseNotesText string `json:"release_notes_text"` +} + +// DockerVersionsInfo is a wrapper around a DockerVersionInfo array to implement sorting. +type DockerVersionsInfo []*DockerVersionInfo + +func (d DockerVersionsInfo) Len() int { return len(d) } + +func (d DockerVersionsInfo) Less(i, j int) bool { + return d[i].Version.Less(&d[j].Version) +} + +func (d DockerVersionsInfo) Swap(i, j int) { + d[i], d[j] = d[j], d[i] } From 8ad46db529170cfa68774a9384b3f7e95489d699 Mon Sep 17 00:00:00 2001 From: Alex Demidoff Date: Mon, 16 Sep 2024 12:35:30 +0300 Subject: [PATCH 3/5] PMM-13146 Fix v3 telemetry issues (#3154) * PMM-13146 Fix the collection of server settings * PMM-13146 remove a non-existent field * PMM-13146 update telemetry configuration * PMM-13146 rename the envvar for backups * PMM-13146 fix the error not being used * Update managed/services/telemetry/config.default.yml Co-authored-by: Nurlan Moldomurov * PMM-13146 put back PMMServerHAEnabled metric * PMM-13146 simplify boolean logic when reporting feature toggles * PMM-13146 add a test for a missing metric * Update managed/services/telemetry/config.default.yml Co-authored-by: Michael Okoko <10512379+idoqo@users.noreply.github.com> * Update managed/services/telemetry/config.default.yml Co-authored-by: Nurlan Moldomurov * Update managed/services/telemetry/config.default.yml Co-authored-by: Nurlan Moldomurov --------- Co-authored-by: Nurlan Moldomurov Co-authored-by: Michael Okoko <10512379+idoqo@users.noreply.github.com> --- .../process/v2_to_v3_environment_variables.md | 2 +- managed/services/telemetry/config.default.yml | 58 ++++++++++--------- managed/services/telemetry/transform_test.go | 29 +++++++++- managed/utils/envvars/parser.go | 4 +- 4 files changed, 62 insertions(+), 31 deletions(-) diff --git a/docs/process/v2_to_v3_environment_variables.md b/docs/process/v2_to_v3_environment_variables.md index 7b841c9135..fb0503494e 100644 --- a/docs/process/v2_to_v3_environment_variables.md +++ b/docs/process/v2_to_v3_environment_variables.md @@ -9,7 +9,7 @@ Below is a list of affected variables and their new names. | `DISABLE_UPDATES` | `PMM_ENABLE_UPDATES` | | | `DISABLE_TELEMETRY` | `PMM_ENABLE_TELEMETRY` | | | `PERCONA_PLATFORM_API_TIMEOUT` | `PMM_DEV_PERCONA_PLATFORM_API_TIMEOUT` | | -| `DISABLE_BACKUP_MANAGEMENT` | `PMM_DISABLE_BACKUP_MANAGEMENT` | | +| `DISABLE_BACKUP_MANAGEMENT` | `PMM_ENABLE_BACKUP_MANAGEMENT` | Note the reverted boolean | | `ENABLE_AZUREDISCOVER` | `PMM_ENABLE_AZURE_DISCOVER` | | | `ENABLE_RBAC` | `PMM_ENABLE_ACCESS_CONTROL` | | | `LESS_LOG_NOISE` | | Removed in PMM v3 | diff --git a/managed/services/telemetry/config.default.yml b/managed/services/telemetry/config.default.yml index 13f7bdac7b..2f11dfec59 100644 --- a/managed/services/telemetry/config.default.yml +++ b/managed/services/telemetry/config.default.yml @@ -1,12 +1,12 @@ telemetry: # PMM - generic information - - id: PMMServerIAEnabled + - id: PMMServerAlertingEnabled source: PMMDB_SELECT - query: (CASE WHEN alerting->'disabled' = 'false' THEN '1' ELSE '0' END) AS ia_enabled FROM settings s, jsonb_extract_path(s.settings, 'alerting') AS alerting + query: (CASE WHEN alerting->'enabled' = 'false' THEN '0' ELSE '1' END) AS alerting_enabled FROM settings s, jsonb_extract_path(s.settings, 'alerting') AS alerting summary: "PMM Server Integration Alerting feature enabled/disabled" data: - - metric_name: "pmm_server_ia_enabled" - column: "ia_enabled" + - metric_name: "pmm_server_alerting_enabled" + column: "alerting_enabled" - id: PMMServerAlertsFire source: VM @@ -24,25 +24,17 @@ telemetry: - metric_name: "pmm_server_alert_rules_number" value: 1 - - id: PMMServerSTTEnabled + - id: PMMServerAdvisorsEnabled source: PMMDB_SELECT - query: (CASE WHEN stt->'stt_disabled' = 'false' THEN '1' ELSE '0' END) AS stt_enabled FROM settings s, jsonb_extract_path(s.settings, 'sass') AS stt - summary: "PMM Server Security Thread Tool feature enabled/disabled" + query: (CASE WHEN advisors->'enabled' = 'false' THEN '0' ELSE '1' END) AS advisors_enabled FROM settings s, jsonb_extract_path(s.settings, 'sass') AS advisors + summary: "PMM Advisors Enabled" data: - - metric_name: "pmm_server_stt_enabled" - column: "stt_enabled" - - - id: PMMServerAdvisorsDisabled - source: PMMDB_SELECT - query: (CASE WHEN advisors->'enabled' = 'true' THEN '0' ELSE '1' END) AS advisors_disabled FROM settings s, jsonb_extract_path(s.settings, 'sass') AS advisors - summary: "PMM Advisors Disabled" - data: - - metric_name: "pmm_server_advisors_disabled" - column: "advisors_disabled" + - metric_name: "pmm_server_advisors_enabled" + column: "advisors_enabled" - id: PMMServerBackupManagementEnabled source: PMMDB_SELECT - query: (CASE WHEN backup_management->'disabled' = 'false' THEN '1' ELSE '0' END) AS backup_management_enabled FROM settings s, jsonb_extract_path(s.settings, 'backup_management') AS backup_management + query: (CASE WHEN backup_management->'enabled' = 'false' THEN '0' ELSE '1' END) AS backup_management_enabled FROM settings s, jsonb_extract_path(s.settings, 'backup_management') AS backup_management summary: "PMM Server Backup Management feature enabled" data: - metric_name: "pmm_server_backup_management_enabled" @@ -51,18 +43,26 @@ telemetry: - id: PMMServerAccessControlEnabled source: PMMDB_SELECT query: (CASE WHEN access_control->'enabled' = 'true' THEN '1' ELSE '0' END) AS access_control_enabled FROM settings s, jsonb_extract_path(s.settings, 'access_control') AS access_control - summary: "PMM Server Access Control feature enabled/disabled" + summary: "PMM Server Access Control feature enabled" data: - metric_name: "pmm_server_access_control_enabled" column: "access_control_enabled" - - id: PMMServerUpdatesDisabled + - id: PMMServerUpdatesEnabled + source: PMMDB_SELECT + query: (CASE WHEN updates->'enabled' = 'true' THEN '1' ELSE '0' END) AS updates_enabled FROM settings s, jsonb_extract_path(s.settings, 'updates') AS updates + summary: "PMM Server Check Updates feature enabled" + data: + - metric_name: "pmm_server_updates_enabled" + column: "updates_enabled" + + - id: PMMAzureMonitoringEnabled source: PMMDB_SELECT - query: (CASE WHEN updates->'disabled' = 'true' THEN '1' ELSE '0' END) AS updates_disabled FROM settings s, jsonb_extract_path(s.settings, 'updates') AS updates - summary: "PMM Server Check Updates feature disabled" + query: (CASE WHEN azure->'enabled' = 'true' THEN '1' ELSE '0' END) AS azure_enabled FROM settings s, jsonb_extract_path(s.settings, 'azure') AS azure + summary: "PMM Azure monitoring feature enabled" data: - - metric_name: "pmm_server_updates_disabled" - column: "updates_disabled" + - metric_name: "pmm_server_azure_enabled" + column: "azure_enabled" - id: PMMServerFirstServiceAdded source: PMMDB_SELECT @@ -911,7 +911,6 @@ telemetry: from dumps where created_at BETWEEN NOW() - INTERVAL '24 HOURS' AND NOW() group by status, services_count, timerange, ignore_load, export_qan; - transform: type: JSON metric: pmm_dumps_performed @@ -956,7 +955,14 @@ telemetry: summary: "Use of HA feature" data: - metric_name: "pmm_server_ha_enable" - column: "PERCONA_TEST_HA_ENABLE" + column: "PMM_TEST_HA_ENABLE" + + - id: PMMServerBuiltinDatabaseDisabled + source: ENV_VARS + summary: "Use of external PMM database" + data: + - metric_name: "pmm_server_builtin_postgres_disable" + column: "PMM_DISABLE_BUILTIN_POSTGRES" - id: PMMServerHAUseOfDBs source: ENV_VARS diff --git a/managed/services/telemetry/transform_test.go b/managed/services/telemetry/transform_test.go index 65a59fe6bd..a991333b27 100644 --- a/managed/services/telemetry/transform_test.go +++ b/managed/services/telemetry/transform_test.go @@ -125,10 +125,31 @@ func TestTransformToJSON(t *testing.T) { }, wantErr: assert.NoError, }, + { + name: "test_mysql_plugins_with_an_missing_metric", + args: args{ + config: configJSON().changeData([]ConfigData{ + {MetricName: "1", Label: "library"}, // this metric will be missing in the output + {MetricName: "2", Label: "licence"}, + {MetricName: "3", Label: "name"}, + {MetricName: "4", Label: "status"}, + {MetricName: "5", Label: "type"}, + }), + metrics: []*pmmv1.ServerMetric_Metric{ + {Key: "licence", Value: `GPL`}, + {Key: "name", Value: `INNODB_TABLES`}, + {Key: "status", Value: `ACTIVE`}, + {Key: "type", Value: `INFORMATION SCHEMA`}, + }, + }, + want: []*pmmv1.ServerMetric_Metric{ + {Key: "metric", Value: `{"v":[{"licence":"GPL","name":"INNODB_TABLES","status":"ACTIVE","type":"INFORMATION SCHEMA"}]}`}, + }, + wantErr: assert.NoError, + }, } for _, tt := range tests { - tt := tt t.Run(tt.name, func(t *testing.T) { got, err := transformToJSON(tt.args.config, tt.args.metrics) if !tt.wantErr(t, err) { @@ -220,7 +241,6 @@ func TestTransformExportValues(t *testing.T) { } for _, tt := range tests { - tt := tt t.Run(tt.name, func(t *testing.T) { got, err := transformExportValues(tt.args.config, tt.args.metrics) if !tt.wantErr(t, err) { @@ -273,6 +293,11 @@ func (c *Config) changeDataSource(s DataSourceName) *Config { return c } +func (c *Config) changeData(d []ConfigData) *Config { + c.Data = d + return c +} + func TestRemoveEmpty(t *testing.T) { type args struct { metrics []*pmmv1.ServerMetric_Metric diff --git a/managed/utils/envvars/parser.go b/managed/utils/envvars/parser.go index 6d68a85187..cd3bd4ca69 100644 --- a/managed/utils/envvars/parser.go +++ b/managed/utils/envvars/parser.go @@ -159,7 +159,7 @@ func ParseEnvVars(envs []string) (*models.ChangeSettingsParams, []error, []strin } envSettings.EnableAzurediscover = &b - case "ENABLE_BACKUP_MANAGEMENT": + case "PMM_ENABLE_BACKUP_MANAGEMENT": b, err := strconv.ParseBool(v) if err != nil { errs = append(errs, fmt.Errorf("invalid value %q for environment variable %q", v, k)) @@ -173,7 +173,7 @@ func ParseEnvVars(envs []string) (*models.ChangeSettingsParams, []error, []strin case "PMM_VM_URL": _, err = url.Parse(v) if err != nil { - err = fmt.Errorf("invalid value %q for environment variable %q", v, k) + errs = append(errs, fmt.Errorf("invalid value %q for environment variable %q", v, k)) } case "PMM_INSTALL_METHOD", "PMM_DISTRIBUTION_METHOD": From a0683941630bc4ca27a084f637e712adef80eed2 Mon Sep 17 00:00:00 2001 From: Alex Demidoff Date: Wed, 18 Sep 2024 09:56:28 +0300 Subject: [PATCH 4/5] PMM-13285 Short agent status in pmm-admin list output (#3123) --- admin/commands/list.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/admin/commands/list.go b/admin/commands/list.go index 193bebd3d7..e274d17da7 100644 --- a/admin/commands/list.go +++ b/admin/commands/list.go @@ -61,7 +61,7 @@ func (a listResultAgent) HumanReadableAgentType() string { } func (a listResultAgent) NiceAgentStatus() string { - res := a.Status + res, _ := strings.CutPrefix(a.Status, "AGENT_STATUS_") if res == "" { res = "unknown" //nolint:goconst } From 6d2825b7c4b1e833af99c0b0f19cfe8884b01002 Mon Sep 17 00:00:00 2001 From: Nurlan Moldomurov Date: Wed, 18 Sep 2024 11:48:47 +0300 Subject: [PATCH 5/5] PMM-7 fix SSH key test. (#3203) --- api-tests/Makefile | 3 +++ api-tests/server/settings_test.go | 6 +++--- managed/services/server/server.go | 3 ++- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/api-tests/Makefile b/api-tests/Makefile index 85af0f3609..4cbd6a120c 100644 --- a/api-tests/Makefile +++ b/api-tests/Makefile @@ -15,6 +15,9 @@ run: go test -count=1 -p 1 -v ./... 2>&1 | tee pmm-api-tests-output.txt cat pmm-api-tests-output.txt | bin/go-junit-report > pmm-api-tests-junit-report.xml +run-dev: + go test -count=1 -p 1 -v ./... + run-race: go test -count=1 -p 1 -v -race ./... 2>&1 | tee pmm-api-tests-output.txt cat pmm-api-tests-output.txt | bin/go-junit-report > pmm-api-tests-junit-report.xml diff --git a/api-tests/server/settings_test.go b/api-tests/server/settings_test.go index cae52f07ac..be972eee17 100644 --- a/api-tests/server/settings_test.go +++ b/api-tests/server/settings_test.go @@ -521,7 +521,7 @@ func TestSettings(t *testing.T) { assert.Empty(t, res) }) - t.Run("ChangeSSHKey", func(t *testing.T) { + t.Run("ChangeSSHKey only on AMI and OVF", func(t *testing.T) { defer restoreSettingsDefaults(t) sshKey := "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQClY/8sz3w03vA2bY6mBFgUzrvb2FIoHw8ZjUXGGClJzJg5HC" + @@ -535,8 +535,8 @@ func TestSettings(t *testing.T) { }, Context: pmmapitests.Context, }) - require.NoError(t, err) - assert.Equal(t, sshKey, res.Payload.Settings.SSHKey) + pmmapitests.AssertAPIErrorf(t, err, 500, codes.Internal, `SSH key can be set only on AMI and OVF distributions`) + assert.Empty(t, res) }) t.Run("OK", func(t *testing.T) { diff --git a/managed/services/server/server.go b/managed/services/server/server.go index 2a2a358308..9573164b66 100644 --- a/managed/services/server/server.go +++ b/managed/services/server/server.go @@ -600,7 +600,8 @@ func (s *Server) ChangeSettings(ctx context.Context, req *serverv1.ChangeSetting // absent value means "do not change" if req.SshKey != nil { if err = s.writeSSHKey(pointer.GetString(req.SshKey)); err != nil { - return errors.WithStack(err) + s.l.Error(errors.WithStack(err)) + return status.Errorf(codes.Internal, err.Error()) } }