From 232fa3cddb6a4f2df90bcb34d54a661eedc7cfdd Mon Sep 17 00:00:00 2001 From: Nurlan Moldomurov Date: Mon, 3 Mar 2025 15:17:50 +0300 Subject: [PATCH 1/5] PMM-13579 Fix truncate of queries. (#3419) * PMM-13579 Fix truncate of queries. * PMM-13579 Fix tests. --- .../pgstatstatements/pg_stat_statements_models.go | 1 + .../postgres/pgstatstatements/pgstatstatements.go | 13 +++++++------ .../pgstatstatements/pgstatstatements_test.go | 4 ++-- 3 files changed, 10 insertions(+), 8 deletions(-) diff --git a/agent/agents/postgres/pgstatstatements/pg_stat_statements_models.go b/agent/agents/postgres/pgstatstatements/pg_stat_statements_models.go index 6295b90092..8f360188bb 100644 --- a/agent/agents/postgres/pgstatstatements/pg_stat_statements_models.go +++ b/agent/agents/postgres/pgstatstatements/pg_stat_statements_models.go @@ -214,6 +214,7 @@ type pgStatStatementsExtended struct { Tables []string IsQueryTruncated bool Comments map[string]string + RealQuery string // RealQuery is a query which is not truncated, it's not sent to API and stored only locally in memory. } func (e *pgStatStatementsExtended) String() string { diff --git a/agent/agents/postgres/pgstatstatements/pgstatstatements.go b/agent/agents/postgres/pgstatstatements/pgstatstatements.go index 52bae79df4..9593d05bdd 100644 --- a/agent/agents/postgres/pgstatstatements/pgstatstatements.go +++ b/agent/agents/postgres/pgstatstatements/pgstatstatements.go @@ -143,7 +143,7 @@ func (m *PGStatStatementsQAN) Run(ctx context.Context) { var err error m.changes <- agents.Change{Status: inventoryv1.AgentStatus_AGENT_STATUS_STARTING} - if current, _, err := m.getStatStatementsExtended(ctx, m.q, m.maxQueryLength); err == nil { + if current, _, err := m.getStatStatementsExtended(ctx); err == nil { if err = m.statementsCache.Set(current); err == nil { m.l.Debugf("Got %d initial stat statements.", len(current)) running = true @@ -204,8 +204,6 @@ func (m *PGStatStatementsQAN) Run(ctx context.Context) { // and the previous cashed state. func (m *PGStatStatementsQAN) getStatStatementsExtended( ctx context.Context, - q *reform.Querier, - maxQueryLength int32, ) (statementsMap, statementsMap, error) { var totalN, newN, newSharedN, oldN int var err error @@ -221,6 +219,8 @@ func (m *PGStatStatementsQAN) getStatStatementsExtended( return nil, nil, err } + q := m.q + // load all databases and usernames first as we can't use querier while iterating over rows below databases := queryDatabases(q) usernames := queryUsernames(q) @@ -251,6 +251,7 @@ func (m *PGStatStatementsQAN) getStatStatementsExtended( pgStatStatements: *row, Database: databases[row.DBID], Username: usernames[row.UserID], + RealQuery: row.Query, } if p := prev[c.QueryID]; p != nil { @@ -262,7 +263,7 @@ func (m *PGStatStatementsQAN) getStatStatementsExtended( } else { newN++ - c.Query, c.IsQueryTruncated = truncate.Query(c.Query, maxQueryLength, truncate.GetDefaultMaxQueryLength()) + c.Query, c.IsQueryTruncated = truncate.Query(c.Query, m.maxQueryLength, truncate.GetDefaultMaxQueryLength()) } current[c.QueryID] = c @@ -278,7 +279,7 @@ func (m *PGStatStatementsQAN) getStatStatementsExtended( } func (m *PGStatStatementsQAN) getNewBuckets(ctx context.Context, periodStart time.Time, periodLengthSecs uint32) ([]*agentv1.MetricsBucket, error) { - current, prev, err := m.getStatStatementsExtended(ctx, m.q, m.maxQueryLength) + current, prev, err := m.getStatStatementsExtended(ctx) if err != nil { return nil, err } @@ -336,7 +337,7 @@ func (m *PGStatStatementsQAN) makeBuckets(current, prev statementsMap) []*agentv } if len(currentPSS.Tables) == 0 { - currentPSS.Tables = extractTables(currentPSS.Query, m.maxQueryLength, l) + currentPSS.Tables = extractTables(currentPSS.RealQuery, m.maxQueryLength, l) } if !m.disableCommentsParsing { diff --git a/agent/agents/postgres/pgstatstatements/pgstatstatements_test.go b/agent/agents/postgres/pgstatstatements/pgstatstatements_test.go index a71eeb6429..c52354252d 100644 --- a/agent/agents/postgres/pgstatstatements/pgstatstatements_test.go +++ b/agent/agents/postgres/pgstatstatements/pgstatstatements_test.go @@ -285,7 +285,7 @@ func TestPGStatStatementsQAN(t *testing.T) { Common: &agentv1.MetricsBucket_Common{ Fingerprint: selectAllCitiesLong, Database: "pmm-agent", - Tables: []string{}, + Tables: []string{"city"}, Comments: map[string]string{"controller": "test"}, Username: "pmm-agent", AgentId: "agent_id", @@ -331,7 +331,7 @@ func TestPGStatStatementsQAN(t *testing.T) { Common: &agentv1.MetricsBucket_Common{ Fingerprint: selectAllCitiesLong, Database: "pmm-agent", - Tables: []string{}, + Tables: []string{"city"}, Comments: map[string]string{"controller": "test"}, Username: "pmm-agent", AgentId: "agent_id", From 3112dead3433b9566c58474fc6bdb0304d21c363 Mon Sep 17 00:00:00 2001 From: Nurlan Moldomurov Date: Mon, 3 Mar 2025 15:19:09 +0300 Subject: [PATCH 2/5] PMM-13374 new mongodb fingerprints (#3271) * PMM-13374 new mongodb fingerprints. * PMM-13374 fix aggregator_test.go. * PMM-13374 fix aggregator_test.go. * PMM-13374 fix fingerprinter_test.go. * PMM-13374 Improve fingerprinter generation. * PMM-13374 fix linter and tests. * PMM-13374 fix linter and tests. * PMM-13374 fix linter. * PMM-13374 fix linter. * PMM-13374 fix linter. * PMM-13374 fix test for latest oracle. --- .../profiler/aggregator/aggregator.go | 2 +- .../profiler/aggregator/aggregator_test.go | 4 +- .../profiler/fingerprinter/fingerprinter.go | 263 ++++++++++++++++ .../fingerprinter/fingerprinter_test.go | 292 ++++++++++++++++++ .../internal/profiler/parser/parser_test.go | 8 +- .../internal/profiler/profiler_test.go | 23 +- .../mysql/perfschema/perfschema_test.go | 2 +- 7 files changed, 572 insertions(+), 22 deletions(-) create mode 100644 agent/agents/mongodb/internal/profiler/fingerprinter/fingerprinter.go create mode 100644 agent/agents/mongodb/internal/profiler/fingerprinter/fingerprinter_test.go diff --git a/agent/agents/mongodb/internal/profiler/aggregator/aggregator.go b/agent/agents/mongodb/internal/profiler/aggregator/aggregator.go index b24a9dc087..c9f44ca2a5 100644 --- a/agent/agents/mongodb/internal/profiler/aggregator/aggregator.go +++ b/agent/agents/mongodb/internal/profiler/aggregator/aggregator.go @@ -22,11 +22,11 @@ import ( "sync" "time" - "github.com/percona/percona-toolkit/src/go/mongolib/fingerprinter" "github.com/percona/percona-toolkit/src/go/mongolib/proto" mongostats "github.com/percona/percona-toolkit/src/go/mongolib/stats" "github.com/sirupsen/logrus" + "github.com/percona/pmm/agent/agents/mongodb/internal/profiler/fingerprinter" "github.com/percona/pmm/agent/agents/mongodb/internal/report" "github.com/percona/pmm/agent/utils/truncate" agentv1 "github.com/percona/pmm/api/agent/v1" diff --git a/agent/agents/mongodb/internal/profiler/aggregator/aggregator_test.go b/agent/agents/mongodb/internal/profiler/aggregator/aggregator_test.go index ca08443b57..becfa325b7 100644 --- a/agent/agents/mongodb/internal/profiler/aggregator/aggregator_test.go +++ b/agent/agents/mongodb/internal/profiler/aggregator/aggregator_test.go @@ -66,7 +66,7 @@ func TestAggregator(t *testing.T) { { Common: &agentv1.MetricsBucket_Common{ Queryid: result.Buckets[0].Common.Queryid, - Fingerprint: "INSERT people", + Fingerprint: "db.people.insert(?)", Database: "collection", Tables: []string{"people"}, AgentId: agentID, @@ -129,7 +129,7 @@ func TestAggregator(t *testing.T) { { Common: &agentv1.MetricsBucket_Common{ Queryid: result.Buckets[0].Common.Queryid, - Fingerprint: "FIND people name_\ufffd", + Fingerprint: "db.people.find({\"name_\\ufffd\":\"?\"})", Database: "collection", Tables: []string{"people"}, AgentId: agentID, diff --git a/agent/agents/mongodb/internal/profiler/fingerprinter/fingerprinter.go b/agent/agents/mongodb/internal/profiler/fingerprinter/fingerprinter.go new file mode 100644 index 0000000000..7bf8682128 --- /dev/null +++ b/agent/agents/mongodb/internal/profiler/fingerprinter/fingerprinter.go @@ -0,0 +1,263 @@ +// Copyright (C) 2023 Percona LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package fingerprinter + +import ( + "encoding/json" + "errors" + "fmt" + "strings" + + "github.com/percona/percona-toolkit/src/go/mongolib/fingerprinter" + "github.com/percona/percona-toolkit/src/go/mongolib/proto" + "go.mongodb.org/mongo-driver/bson" +) + +// ProfilerFingerprinter holds any necessary configuration or dependencies. +type ProfilerFingerprinter struct { + keyFilters []string + // Add fields here if you need to configure the fingerprinter +} + +// NewFingerprinter creates a new instance of ProfilerFingerprinter. +func NewFingerprinter(keyFilters []string) *ProfilerFingerprinter { + return &ProfilerFingerprinter{ + keyFilters: keyFilters, + } +} + +// Fingerprint generates a unique MongoDB command fingerprint from profiler output. +func (pf *ProfilerFingerprinter) Fingerprint(doc proto.SystemProfile) (fingerprinter.Fingerprint, error) { + fp := fingerprinter.Fingerprint{ + Namespace: doc.Ns, + Operation: doc.Op, + } + + // Parse the namespace to separate database and collection names + parts := strings.Split(doc.Ns, ".") + if len(parts) < 2 { + return fp, errors.New("invalid namespace format") + } + fp.Database = parts[0] + fp.Collection = parts[1] + + // Select operation type and build command with optional fields + switch doc.Op { + case "query": + return pf.fingerprintFind(fp, doc) + case "insert": + return pf.fingerprintInsert(fp) + case "update": + return pf.fingerprintUpdate(fp, doc) + case "delete", "remove": + return pf.fingerprintDelete(fp, doc) + case "command": + return pf.fingerprintCommand(fp, doc) + default: + return pf.fingerprintCommand(fp, doc) + } +} + +// Helper for find operations with optional parameters. +func (pf *ProfilerFingerprinter) fingerprintFind(fp fingerprinter.Fingerprint, doc proto.SystemProfile) (fingerprinter.Fingerprint, error) { + filter := "" + command := doc.Command.Map() + if f, ok := command["filter"]; ok { + values := maskValues(f, make(map[string]maskOption)) + filterJSON, _ := json.Marshal(values) + filter = string(filterJSON) + } + + // Initialize mongosh command with required fields + fp.Fingerprint = fmt.Sprintf(`db.%s.find(%s`, fp.Collection, filter) + fp.Keys = filter + + // Optional fields for find command + if command["project"] != nil { + projectionJSON, _ := json.Marshal(command["project"]) + fp.Fingerprint += fmt.Sprintf(`, %s`, projectionJSON) + } + fp.Fingerprint += ")" + + if sort, ok := command["sort"]; ok { + sortJSON, _ := json.Marshal(sort.(bson.D).Map()) + fp.Fingerprint += fmt.Sprintf(`.sort(%s)`, sortJSON) + } + if _, ok := command["limit"]; ok { + fp.Fingerprint += `.limit(?)` + } + if _, ok := command["skip"]; ok { + fp.Fingerprint += `.skip(?)` + } + if batchSize, ok := command["batchSize"]; ok { + fp.Fingerprint += fmt.Sprintf(`.batchSize(%d)`, batchSize) + } + + return fp, nil +} + +// Helper for insert operations +func (pf *ProfilerFingerprinter) fingerprintInsert(fp fingerprinter.Fingerprint) (fingerprinter.Fingerprint, error) { + fp.Fingerprint = fmt.Sprintf(`db.%s.insert(?)`, fp.Collection) + return fp, nil +} + +// Helper for update operations +func (pf *ProfilerFingerprinter) fingerprintUpdate(fp fingerprinter.Fingerprint, doc proto.SystemProfile) (fingerprinter.Fingerprint, error) { + command := doc.Command.Map() + filterJSON, _ := json.Marshal(maskValues(command["q"].(bson.D), make(map[string]maskOption))) + updateJSON, _ := json.Marshal(maskValues(command["u"].(bson.D), make(map[string]maskOption))) + + fp.Fingerprint = fmt.Sprintf(`db.%s.update(%s, %s`, fp.Collection, filterJSON, updateJSON) + fp.Keys = string(filterJSON) + + if command["upsert"] == true || command["multi"] == true { + options := make(map[string]interface{}) + if command["upsert"] == true { + options["upsert"] = true + } + if command["multi"] == true { + options["multi"] = true + } + optionsJSON, _ := json.Marshal(options) + fp.Fingerprint += fmt.Sprintf(`, %s`, optionsJSON) + } + fp.Fingerprint += ")" + + return fp, nil +} + +// Helper for delete operations +func (pf *ProfilerFingerprinter) fingerprintDelete(fp fingerprinter.Fingerprint, doc proto.SystemProfile) (fingerprinter.Fingerprint, error) { + command := doc.Command.Map() + method := "deleteMany" + if limit, ok := command["limit"]; ok && limit == int32(1) { + method = "deleteOne" + } + filterJSON, _ := json.Marshal(maskValues(command["q"], make(map[string]maskOption))) + fp.Fingerprint = fmt.Sprintf(`db.%s.%s(%s)`, fp.Collection, method, filterJSON) + fp.Keys = string(filterJSON) + return fp, nil +} + +// Helper for general command operations, including support for "aggregate" commands +func (pf *ProfilerFingerprinter) fingerprintCommand(fp fingerprinter.Fingerprint, doc proto.SystemProfile) (fingerprinter.Fingerprint, error) { + // Unmarshal the command into a map for easy access and manipulation + command := doc.Command.Map() + + maskOptions := map[string]maskOption{ + "$db": {remove: true}, + "$readPreference": {remove: true}, + "$readConcern": {remove: true}, + "$writeConcern": {remove: true}, + "$clusterTime": {remove: true}, + "$oplogQueryData": {remove: true}, + "$replData": {remove: true}, + "lastKnownCommittedOpTime": {remove: true}, + "lsid": {remove: true}, + "findAndModify": {skipMask: true}, + "remove": {skipMask: true}, + } + if _, exists := command["aggregate"]; exists { + // Set collection and initialize aggregation structure + fp.Fingerprint = fmt.Sprintf(`db.%s.aggregate([`, fp.Collection) + stageStrings := []string{} + + // Process pipeline stages, replacing all values with "?" + if pipeline, exists := command["pipeline"]; exists { + pipelineStages, _ := pipeline.(bson.A) + + for _, stage := range pipelineStages { + stageMap := stage.(bson.D).Map() + var stageJSON []byte + switch { + case stageMap["$match"] != nil: + stageJSON, _ = json.Marshal(maskValues(stageMap, maskOptions)) + default: + stageJSON, _ = bson.MarshalExtJSON(stageMap, false, false) + } + + stageStrings = append(stageStrings, string(stageJSON)) + } + + fp.Fingerprint += strings.Join(stageStrings, ", ") + } + fp.Fingerprint += "])" + if collation, exists := command["collation"]; exists { + collationMasked, _ := json.Marshal(maskValues(collation, maskOptions)) + fp.Fingerprint += fmt.Sprintf(`, collation: %s`, collationMasked) + } + + // Build a descriptive Keys field + fp.Keys = strings.Join(stageStrings, ", ") + } else { + // Handle other commands generically + commandMasked, _ := json.Marshal(maskValues(doc.Command, maskOptions)) + fp.Fingerprint = fmt.Sprintf(`db.runCommand(%s)`, commandMasked) + fp.Keys = string(commandMasked) + } + + return fp, nil +} + +type maskOption struct { + remove bool + skipMask bool +} + +// maskValues replaces all values within a map or slice with "?" recursively and removes keys in the filter. +func maskValues(data interface{}, options map[string]maskOption) interface{} { + switch v := data.(type) { + case bson.D: + masked := make(bson.M) + for _, value := range v { + option, ok := options[value.Key] + switch { + case ok && option.remove: + continue + case ok && option.skipMask: + masked[value.Key] = value.Value + default: + masked[value.Key] = maskValues(value.Value, options) + } + } + return masked + case bson.M: + masked := make(bson.M) + for key, value := range v { + option, ok := options[key] + switch { + case ok && option.remove: + continue + case ok && option.skipMask: + masked[key] = value + default: + masked[key] = maskValues(value, options) + } + } + return masked + case bson.A: + for i := range v { + v[i] = maskValues(v[i], options) + } + return v + default: + return "?" + } +} + +func DefaultKeyFilters() []string { + return []string{} +} diff --git a/agent/agents/mongodb/internal/profiler/fingerprinter/fingerprinter_test.go b/agent/agents/mongodb/internal/profiler/fingerprinter/fingerprinter_test.go new file mode 100644 index 0000000000..5d51ca87f0 --- /dev/null +++ b/agent/agents/mongodb/internal/profiler/fingerprinter/fingerprinter_test.go @@ -0,0 +1,292 @@ +// Copyright (C) 2023 Percona LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package fingerprinter + +import ( + "context" + "encoding/json" + "fmt" + "log" + "testing" + "time" + + "github.com/percona/percona-toolkit/src/go/mongolib/fingerprinter" + "github.com/percona/percona-toolkit/src/go/mongolib/proto" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "go.mongodb.org/mongo-driver/bson" + "go.mongodb.org/mongo-driver/bson/primitive" + "go.mongodb.org/mongo-driver/mongo" + "go.mongodb.org/mongo-driver/mongo/options" + "go.mongodb.org/mongo-driver/mongo/readpref" + + "github.com/percona/pmm/agent/utils/mongo_fix" +) + +const ( + MgoTimeoutDialInfo = 5 * time.Second + MgoTimeoutSessionSync = 5 * time.Second + MgoTimeoutSessionSocket = 5 * time.Second +) + +func createQuery(dbName string, startTime time.Time) bson.M { + return bson.M{ + "ns": bson.M{"$ne": dbName + ".system.profile"}, + "ts": bson.M{"$gt": startTime}, + } +} + +func createIterator(ctx context.Context, collection *mongo.Collection, query bson.M) (*mongo.Cursor, error) { + opts := options.Find().SetSort(bson.M{"$natural": 1}).SetCursorType(options.TailableAwait) + return collection.Find(ctx, query, opts) +} + +type ProfilerStatus struct { + Was int64 `bson:"was"` + SlowMs int64 `bson:"slowms"` + GleStats struct { + ElectionID string `bson:"electionId"` + LastOpTime int64 `bson:"lastOpTime"` + } `bson:"$gleStats"` +} + +func createSession(dsn string, agentID string) (*mongo.Client, error) { + ctx, cancel := context.WithTimeout(context.Background(), MgoTimeoutDialInfo) + defer cancel() + + opts, err := mongo_fix.ClientOptionsForDSN(dsn) + if err != nil { + return nil, err + } + + opts = opts. + SetDirect(true). + SetReadPreference(readpref.Nearest()). + SetSocketTimeout(MgoTimeoutSessionSocket). + SetAppName(fmt.Sprintf("QAN-mongodb-profiler-%s", agentID)) + + client, err := mongo.Connect(ctx, opts) + if err != nil { + return nil, err + } + + return client, nil +} + +func TestProfilerFingerprinter(t *testing.T) { + t.Run("CheckWithRealDB", func(t *testing.T) { + url := "mongodb://root:root-password@127.0.0.1:27017" + dbName := "test_fingerprint" + + client, err := createSession(url, "pmm-agent") + if err != nil { + return + } + + ctx, cancel := context.WithTimeout(context.Background(), MgoTimeoutSessionSync) + defer cancel() + _ = client.Database(dbName).Drop(ctx) + defer client.Database(dbName).Drop(context.TODO()) //nolint:errcheck + + ps := ProfilerStatus{} + err = client.Database("admin").RunCommand(ctx, primitive.M{"profile": -1}).Decode(&ps) + defer func() { // restore profiler status + client.Database("admin").RunCommand(ctx, primitive.D{{"profile", ps.Was}, {"slowms", ps.SlowMs}}) + }() + + // Enable profilling all queries (2, slowms = 0) + res := client.Database("admin").RunCommand(ctx, primitive.D{{"profile", 2}, {"slowms", 0}}) + if res.Err() != nil { + return + } + + database := client.Database(dbName) + _, err = database.Collection("test").InsertOne(ctx, bson.M{"id": 0, "name": "test", "value": 1, "time": time.Now()}) + assert.NoError(t, err) + _, err = database.Collection("secondcollection").InsertOne(ctx, bson.M{"id": 0, "name": "sec", "value": 2}) + assert.NoError(t, err) + database.Collection("test").FindOne(ctx, bson.M{"id": 0}) + database.Collection("test").FindOne(ctx, bson.M{"id": 1, "name": "test", "time": time.Now()}) + database.Collection("test").FindOneAndUpdate(ctx, bson.M{"id": 0}, bson.M{"$set": bson.M{"name": "new"}}) + database.Collection("test").FindOneAndDelete(ctx, bson.M{"id": 1}) + database.Collection("secondcollection").Find(ctx, bson.M{"name": "sec"}, options.Find().SetLimit(1).SetSort(bson.M{"id": -1})) + database.Collection("test").Aggregate(ctx, + []bson.M{ + { + "$match": bson.M{"id": 0, "time": bson.M{"$gt": time.Now().Add(-time.Hour)}}, + }, + { + "$group": bson.M{"_id": "$id", "count": bson.M{"$sum": 1}}, + }, + { + "$sort": bson.M{"_id": 1}, + }, + }, + ) + database.Collection("secondcollection").Aggregate(ctx, mongo.Pipeline{ + bson.D{ + { + Key: "$collStats", + Value: bson.M{ + // TODO: PMM-9568 : Add support to handle histogram metrics + "latencyStats": bson.M{"histograms": false}, + "storageStats": bson.M{"scale": 1}, + }, + }, + }, bson.D{ + { + Key: "$project", + Value: bson.M{ + "storageStats.wiredTiger": 0, + "storageStats.indexDetails": 0, + }, + }, + }, + }) + database.Collection("secondcollection").DeleteOne(ctx, bson.M{"id": 0}) + database.Collection("test").DeleteMany(ctx, bson.M{"name": "test"}) + profilerCollection := database.Collection("system.profile") + query := createQuery(dbName, time.Now().Add(-10*time.Minute)) + + cursor, err := createIterator(ctx, profilerCollection, query) + require.NoError(t, err) + // do not cancel cursor closing when ctx is canceled + defer cursor.Close(context.Background()) //nolint:errcheck + + pf := &ProfilerFingerprinter{} + + var fingerprints []string + for cursor.TryNext(ctx) { + doc := proto.SystemProfile{} + e := cursor.Decode(&doc) + require.NoError(t, e) + + b := bson.M{} + e = cursor.Decode(&b) + require.NoError(t, e) + + marshal, e := json.Marshal(b) + require.NoError(t, e) + log.Println(string(marshal)) + + fingerprint, err := pf.Fingerprint(doc) + require.NoError(t, err) + require.NotNil(t, fingerprint) + fingerprints = append(fingerprints, fingerprint.Fingerprint) + } + assert.NotEmpty(t, fingerprints) + expectedFingerprints := []string{ + `db.test.insert(?)`, + `db.secondcollection.insert(?)`, + `db.test.find({"id":"?"}).limit(?)`, + `db.test.find({"id":"?","name":"?","time":"?"}).limit(?)`, + `db.runCommand({"findAndModify":"test","query":{"id":"?"},"update":{"$set":{"name":"?"}}})`, + `db.runCommand({"findAndModify":"test","query":{"id":"?"},"remove":true})`, + `db.secondcollection.find({"name":"?"}).sort({"id":-1}).limit(?)`, + `db.test.aggregate([{"$match":{"id":"?","time":{"$gt":"?"}}}, {"$group":{"_id":"$id","count":{"$sum":1}}}, {"$sort":{"_id":1}}])`, + `db.test.aggregate([{"$match":{"id":"?","time":{"$gt":"?"}}}, {"$group":{"count":{"$sum":1},"_id":"$id"}}, {"$sort":{"_id":1}}])`, + `db.secondcollection.aggregate([{"$collStats":{"latencyStats":{"histograms":false},"storageStats":{"scale":1}}}, {"$project":{"storageStats.wiredTiger":0,"storageStats.indexDetails":0}}])`, + `db.secondcollection.aggregate([{"$collStats":{"latencyStats":{"histograms":false},"storageStats":{"scale":1}}}, {"$project":{"storageStats.indexDetails":0,"storageStats.wiredTiger":0}}])`, + `db.secondcollection.aggregate([{"$collStats":{"storageStats":{"scale":1},"latencyStats":{"histograms":false}}}, {"$project":{"storageStats.wiredTiger":0,"storageStats.indexDetails":0}}])`, + `db.secondcollection.aggregate([{"$collStats":{"storageStats":{"scale":1},"latencyStats":{"histograms":false}}}, {"$project":{"storageStats.indexDetails":0,"storageStats.wiredTiger":0}}])`, + `db.secondcollection.deleteOne({"id":"?"})`, + `db.test.deleteMany({"name":"?"})`, + } + for i, fingerprint := range fingerprints { + assert.Contains(t, expectedFingerprints, fingerprint, "fingerprint %d: %s", i, fingerprint) + } + }) + + type testCase struct { + name string + doc proto.SystemProfile + want fingerprinter.Fingerprint + } + tests := []testCase{ + { + name: "find", + doc: proto.SystemProfile{ + Ns: "test.collection", + Op: "query", + Command: bson.D{{Key: "filter", Value: bson.D{{Key: "name", Value: "test"}}}, {Key: "sort", Value: bson.D{{Key: "_id", Value: 1}}}, {Key: "limit", Value: 4}, {Key: "skip", Value: 5}}, + }, + want: fingerprinter.Fingerprint{ + Fingerprint: `db.collection.find({"name":"?"}).sort({"_id":1}).limit(?).skip(?)`, + Namespace: "test.collection", + Database: "test", + Collection: "collection", + Operation: "query", + }, + }, + { + name: "insert", + doc: proto.SystemProfile{ + Ns: "test.insert_collection", + Op: "insert", + Command: bson.D{}, + }, + want: fingerprinter.Fingerprint{ + Fingerprint: `db.insert_collection.insert(?)`, + Namespace: "test.insert_collection", + Database: "test", + Collection: "insert_collection", + Operation: "insert", + }, + }, + { + name: "update", + doc: proto.SystemProfile{ + Ns: "test.update_collection", + Op: "update", + Command: bson.D{{Key: "q", Value: bson.D{{Key: "name", Value: "test"}}}, {Key: "u", Value: bson.D{{Key: "$set", Value: bson.D{{Key: "name", Value: "new"}}}}}}, + }, + want: fingerprinter.Fingerprint{ + Fingerprint: `db.update_collection.update({"name":"?"}, {"$set":{"name":"?"}})`, + Namespace: "test.update_collection", + Database: "test", + Collection: "update_collection", + Operation: "update", + }, + }, + { + name: "delete", + doc: proto.SystemProfile{ + Ns: "test.delete_collection", + Op: "remove", + Command: bson.D{{Key: "q", Value: bson.D{{Key: "name", Value: "test"}}}}, + }, + want: fingerprinter.Fingerprint{ + Fingerprint: `db.delete_collection.deleteMany({"name":"?"})`, + Namespace: "test.delete_collection", + Database: "test", + Collection: "delete_collection", + Operation: "remove", + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + pf := &ProfilerFingerprinter{} + fingerprint, err := pf.Fingerprint(tt.doc) + require.NoError(t, err) + require.NotNil(t, fingerprint) + assert.Equal(t, tt.want.Fingerprint, fingerprint.Fingerprint) + assert.Equal(t, tt.want.Namespace, fingerprint.Namespace) + assert.Equal(t, tt.want.Database, fingerprint.Database) + assert.Equal(t, tt.want.Collection, fingerprint.Collection) + assert.Equal(t, tt.want.Operation, fingerprint.Operation) + }) + } +} diff --git a/agent/agents/mongodb/internal/profiler/parser/parser_test.go b/agent/agents/mongodb/internal/profiler/parser/parser_test.go index 9aff073334..e7490c139d 100644 --- a/agent/agents/mongodb/internal/profiler/parser/parser_test.go +++ b/agent/agents/mongodb/internal/profiler/parser/parser_test.go @@ -82,6 +82,9 @@ func TestParserStartStop(t *testing.T) { } func TestParserRunning(t *testing.T) { + oldInterval := aggregator.DefaultInterval + aggregator.DefaultInterval = 10 * time.Second + defer func() { aggregator.DefaultInterval = oldInterval }() docsChan := make(chan pm.SystemProfile) a := aggregator.New(time.Now(), "test-id", logrus.WithField("component", "aggregator"), truncate.GetMongoDBDefaultMaxQueryLength()) reportChan := a.Start() @@ -91,6 +94,7 @@ func TestParserRunning(t *testing.T) { parser1 := New(docsChan, a, logrus.WithField("component", "test-parser")) err := parser1.Start(context.TODO()) require.NoError(t, err) + defer parser1.Stop() now := time.Now().UTC() timeStart := now.Truncate(d).Add(d) @@ -98,10 +102,12 @@ func TestParserRunning(t *testing.T) { select { case docsChan <- pm.SystemProfile{ + Ns: "test.test", Ts: timeStart, Query: bson.D{ {"find", "test"}, }, + Op: "query", ResponseLength: 100, DocsExamined: 200, Nreturned: 300, @@ -135,6 +141,4 @@ func TestParserRunning(t *testing.T) { case <-time.After(d + 5*time.Second): t.Error("test timeout") } - - parser1.Stop() } diff --git a/agent/agents/mongodb/internal/profiler/profiler_test.go b/agent/agents/mongodb/internal/profiler/profiler_test.go index c344e6e836..c645ce6649 100644 --- a/agent/agents/mongodb/internal/profiler/profiler_test.go +++ b/agent/agents/mongodb/internal/profiler/profiler_test.go @@ -143,7 +143,7 @@ func testProfiler(t *testing.T, url string) { for _, r := range ms.reports { for _, bucket := range r.Buckets { switch bucket.Common.Fingerprint { - case "INSERT people": + case "db.people.insert(?)": key := fmt.Sprintf("%s:%s", bucket.Common.Database, bucket.Common.Fingerprint) if b, ok := bucketsMap[key]; ok { b.Mongodb.MDocsReturnedCnt += bucket.Mongodb.MDocsReturnedCnt @@ -153,24 +153,15 @@ func testProfiler(t *testing.T, url string) { } else { bucketsMap[key] = bucket } - case "FIND people name_00\ufffd": + case `db.people.find({"name_00\ufffd":"?"})`: findBucket = bucket + default: + t.Logf("unknown fingerprint: %s", bucket.Common.Fingerprint) } } } - version, err := GetMongoVersion(context.TODO(), sess) - require.NoError(t, err) - - var responseLength float32 - switch version { - case "3.4": - responseLength = 44 - case "3.6": - responseLength = 29 - default: - responseLength = 45 - } + responseLength := float32(45) assert.Equal(t, dbsCount, len(bucketsMap)) // 300 sample docs / 10 = different database names var buckets []*agentv1.MetricsBucket @@ -182,7 +173,7 @@ func testProfiler(t *testing.T, url string) { }) for i, bucket := range buckets { assert.Equal(t, bucket.Common.Database, fmt.Sprintf("test_%02d", i)) - assert.Equal(t, "INSERT people", bucket.Common.Fingerprint) + assert.Equal(t, "db.people.insert(?)", bucket.Common.Fingerprint) assert.Equal(t, []string{"people"}, bucket.Common.Tables) assert.Equal(t, "test-id", bucket.Common.AgentId) assert.Equal(t, inventoryv1.AgentType(9), bucket.Common.AgentType) @@ -205,7 +196,7 @@ func testProfiler(t *testing.T, url string) { assert.Equalf(t, expected.MDocsScannedCnt, bucket.Mongodb.MDocsScannedCnt, "wrong metrics for db %s", bucket.Common.Database) } require.NotNil(t, findBucket) - assert.Equal(t, "FIND people name_00\ufffd", findBucket.Common.Fingerprint) + assert.Equal(t, `db.people.find({"name_00\ufffd":"?"})`, findBucket.Common.Fingerprint) assert.Equal(t, docsCount, findBucket.Mongodb.MDocsReturnedSum) } diff --git a/agent/agents/mysql/perfschema/perfschema_test.go b/agent/agents/mysql/perfschema/perfschema_test.go index 6d60023df8..4a7dc9911c 100644 --- a/agent/agents/mysql/perfschema/perfschema_test.go +++ b/agent/agents/mysql/perfschema/perfschema_test.go @@ -328,7 +328,7 @@ func TestPerfSchema(t *testing.T) { } default: - t.Log("Unhandled version, assuming dummy digests.") + t.Logf("Unhandled version, assuming dummy digests. MySQL version: %s, vendor: %s", mySQLVersion, mySQLVendor) digests = map[string]string{ "SELECT `sleep` (?)": "TODO-sleep", "SELECT * FROM `city`": "TODO-star", From 6bf39104ab6709721f61f4af39028434a75cbc8a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 3 Mar 2025 20:15:26 +0300 Subject: [PATCH 3/5] Bump docker/setup-buildx-action from 3.9.0 to 3.10.0 (#3710) Bumps [docker/setup-buildx-action](https://github.com/docker/setup-buildx-action) from 3.9.0 to 3.10.0. - [Release notes](https://github.com/docker/setup-buildx-action/releases) - [Commits](https://github.com/docker/setup-buildx-action/compare/f7ce87c1d6bead3e36075b2ce75da1f6cc28aaca...b5ca514318bd6ebac0fb2aedd5d36ec1b5c232a2) --- updated-dependencies: - dependency-name: docker/setup-buildx-action dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/devcontainer.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/devcontainer.yml b/.github/workflows/devcontainer.yml index b0e731448d..54580aeeea 100644 --- a/.github/workflows/devcontainer.yml +++ b/.github/workflows/devcontainer.yml @@ -37,7 +37,7 @@ jobs: ref: ${{ github.event.inputs.branch }} - name: Set up Docker Buildx - uses: docker/setup-buildx-action@f7ce87c1d6bead3e36075b2ce75da1f6cc28aaca # v3.9.0 + uses: docker/setup-buildx-action@b5ca514318bd6ebac0fb2aedd5d36ec1b5c232a2 # v3.10.0 - name: Login to ghcr.io registry uses: docker/login-action@9780b0c442fbb1117ed29e0efdff1e18412f7567 # v3.3.0 From 2d5003f3ec39644f3e2a2c89ae5ceb6b5e7bae32 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 3 Mar 2025 17:28:18 +0000 Subject: [PATCH 4/5] Bump codecov/codecov-action from 5.3.1 to 5.4.0 (#3709) Bumps [codecov/codecov-action](https://github.com/codecov/codecov-action) from 5.3.1 to 5.4.0. - [Release notes](https://github.com/codecov/codecov-action/releases) - [Changelog](https://github.com/codecov/codecov-action/blob/main/CHANGELOG.md) - [Commits](https://github.com/codecov/codecov-action/compare/13ce06bfc6bbe3ecf90edbbf1bc32fe5978ca1d3...0565863a31f2c772f9f0395002a31e3f06189574) --- updated-dependencies: - dependency-name: codecov/codecov-action dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/admin.yml | 2 +- .github/workflows/agent.yml | 2 +- .github/workflows/managed.yml | 2 +- .github/workflows/vmproxy.yml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/admin.yml b/.github/workflows/admin.yml index 77c747537d..7ffcbf7c7e 100644 --- a/.github/workflows/admin.yml +++ b/.github/workflows/admin.yml @@ -71,7 +71,7 @@ jobs: run: make test-cover - name: Upload coverage results - uses: codecov/codecov-action@13ce06bfc6bbe3ecf90edbbf1bc32fe5978ca1d3 # v5.3.1 + uses: codecov/codecov-action@0565863a31f2c772f9f0395002a31e3f06189574 # v5.4.0 with: file: cover.out flags: admin diff --git a/.github/workflows/agent.yml b/.github/workflows/agent.yml index 880e189cb5..6f72946aad 100644 --- a/.github/workflows/agent.yml +++ b/.github/workflows/agent.yml @@ -113,7 +113,7 @@ jobs: run: make test-cover - name: Upload coverage results - uses: codecov/codecov-action@13ce06bfc6bbe3ecf90edbbf1bc32fe5978ca1d3 # v5.3.1 + uses: codecov/codecov-action@0565863a31f2c772f9f0395002a31e3f06189574 # v5.4.0 with: files: cover.out flags: agent diff --git a/.github/workflows/managed.yml b/.github/workflows/managed.yml index dbda78d10f..9c5e025bac 100644 --- a/.github/workflows/managed.yml +++ b/.github/workflows/managed.yml @@ -83,7 +83,7 @@ jobs: run: docker exec -i pmm-server make -C managed test-cover - name: Upload coverage results - uses: codecov/codecov-action@13ce06bfc6bbe3ecf90edbbf1bc32fe5978ca1d3 # v5.3.1 + uses: codecov/codecov-action@0565863a31f2c772f9f0395002a31e3f06189574 # v5.4.0 with: files: managed/cover.out flags: managed diff --git a/.github/workflows/vmproxy.yml b/.github/workflows/vmproxy.yml index e5929870dd..e7f05c8483 100644 --- a/.github/workflows/vmproxy.yml +++ b/.github/workflows/vmproxy.yml @@ -73,7 +73,7 @@ jobs: run: make test-cover - name: Upload coverage results - uses: codecov/codecov-action@13ce06bfc6bbe3ecf90edbbf1bc32fe5978ca1d3 # v5.3.1 + uses: codecov/codecov-action@0565863a31f2c772f9f0395002a31e3f06189574 # v5.4.0 with: file: cover.out flags: vmproxy From 51d5ed3e63ba13835c645ce81001ab040e36594f Mon Sep 17 00:00:00 2001 From: Michael Okoko <10512379+idoqo@users.noreply.github.com> Date: Tue, 4 Mar 2025 08:32:59 +0100 Subject: [PATCH 5/5] PMM-13715: allow viewers/editors access limited PMM settings (#3518) * add new map for failed services * add readonly settings endpoint * update method comment * drop retention data from readonly settings * drop unused fields from settings proto * use separate proto message --- api-tests/server/advisors_test.go | 6 +- .../get_read_only_settings_parameters.go | 127 +++ .../get_read_only_settings_responses.go | 724 ++++++++++++++++ .../server_service/server_service_client.go | 41 + api/server/v1/json/v1.json | 100 +++ api/server/v1/server.pb.go | 807 ++++++++++++------ api/server/v1/server.pb.gw.go | 93 +- api/server/v1/server.pb.validate.go | 350 ++++++++ api/server/v1/server.proto | 34 + api/server/v1/server_grpc.pb.go | 59 +- api/swagger/swagger-dev.json | 100 +++ api/swagger/swagger.json | 100 +++ managed/services/grafana/auth_server.go | 2 + managed/services/grafana/auth_server_test.go | 2 + managed/services/server/server.go | 31 + 15 files changed, 2261 insertions(+), 315 deletions(-) create mode 100644 api/server/v1/json/client/server_service/get_read_only_settings_parameters.go create mode 100644 api/server/v1/json/client/server_service/get_read_only_settings_responses.go diff --git a/api-tests/server/advisors_test.go b/api-tests/server/advisors_test.go index d49c1b2d66..1a387888ed 100644 --- a/api-tests/server/advisors_test.go +++ b/api-tests/server/advisors_test.go @@ -52,12 +52,8 @@ func TestStartChecks(t *testing.T) { } func TestGetAdvisorCheckResults(t *testing.T) { - if !pmmapitests.RunAdvisorTests { - t.Skip("Skipping Advisor tests until we have environment: https://jira.percona.com/browse/PMM-5106") - } - t.Run("with disabled Advisors", func(t *testing.T) { - toggleAdvisorChecks(t, true) + toggleAdvisorChecks(t, false) t.Cleanup(func() { restoreSettingsDefaults(t) }) results, err := advisorClient.Default.AdvisorService.GetFailedChecks(nil) diff --git a/api/server/v1/json/client/server_service/get_read_only_settings_parameters.go b/api/server/v1/json/client/server_service/get_read_only_settings_parameters.go new file mode 100644 index 0000000000..ce14210b12 --- /dev/null +++ b/api/server/v1/json/client/server_service/get_read_only_settings_parameters.go @@ -0,0 +1,127 @@ +// 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" + "net/http" + "time" + + "github.com/go-openapi/errors" + "github.com/go-openapi/runtime" + cr "github.com/go-openapi/runtime/client" + "github.com/go-openapi/strfmt" +) + +// NewGetReadOnlySettingsParams creates a new GetReadOnlySettingsParams object, +// with the default timeout for this client. +// +// Default values are not hydrated, since defaults are normally applied by the API server side. +// +// To enforce default values in parameter, use SetDefaults or WithDefaults. +func NewGetReadOnlySettingsParams() *GetReadOnlySettingsParams { + return &GetReadOnlySettingsParams{ + timeout: cr.DefaultTimeout, + } +} + +// NewGetReadOnlySettingsParamsWithTimeout creates a new GetReadOnlySettingsParams object +// with the ability to set a timeout on a request. +func NewGetReadOnlySettingsParamsWithTimeout(timeout time.Duration) *GetReadOnlySettingsParams { + return &GetReadOnlySettingsParams{ + timeout: timeout, + } +} + +// NewGetReadOnlySettingsParamsWithContext creates a new GetReadOnlySettingsParams object +// with the ability to set a context for a request. +func NewGetReadOnlySettingsParamsWithContext(ctx context.Context) *GetReadOnlySettingsParams { + return &GetReadOnlySettingsParams{ + Context: ctx, + } +} + +// NewGetReadOnlySettingsParamsWithHTTPClient creates a new GetReadOnlySettingsParams object +// with the ability to set a custom HTTPClient for a request. +func NewGetReadOnlySettingsParamsWithHTTPClient(client *http.Client) *GetReadOnlySettingsParams { + return &GetReadOnlySettingsParams{ + HTTPClient: client, + } +} + +/* +GetReadOnlySettingsParams contains all the parameters to send to the API endpoint + + for the get read only settings operation. + + Typically these are written to a http.Request. +*/ +type GetReadOnlySettingsParams struct { + timeout time.Duration + Context context.Context + HTTPClient *http.Client +} + +// WithDefaults hydrates default values in the get read only settings params (not the query body). +// +// All values with no default are reset to their zero value. +func (o *GetReadOnlySettingsParams) WithDefaults() *GetReadOnlySettingsParams { + o.SetDefaults() + return o +} + +// SetDefaults hydrates default values in the get read only settings params (not the query body). +// +// All values with no default are reset to their zero value. +func (o *GetReadOnlySettingsParams) SetDefaults() { + // no default values defined for this parameter +} + +// WithTimeout adds the timeout to the get read only settings params +func (o *GetReadOnlySettingsParams) WithTimeout(timeout time.Duration) *GetReadOnlySettingsParams { + o.SetTimeout(timeout) + return o +} + +// SetTimeout adds the timeout to the get read only settings params +func (o *GetReadOnlySettingsParams) SetTimeout(timeout time.Duration) { + o.timeout = timeout +} + +// WithContext adds the context to the get read only settings params +func (o *GetReadOnlySettingsParams) WithContext(ctx context.Context) *GetReadOnlySettingsParams { + o.SetContext(ctx) + return o +} + +// SetContext adds the context to the get read only settings params +func (o *GetReadOnlySettingsParams) SetContext(ctx context.Context) { + o.Context = ctx +} + +// WithHTTPClient adds the HTTPClient to the get read only settings params +func (o *GetReadOnlySettingsParams) WithHTTPClient(client *http.Client) *GetReadOnlySettingsParams { + o.SetHTTPClient(client) + return o +} + +// SetHTTPClient adds the HTTPClient to the get read only settings params +func (o *GetReadOnlySettingsParams) SetHTTPClient(client *http.Client) { + o.HTTPClient = client +} + +// WriteToRequest writes these params to a swagger request +func (o *GetReadOnlySettingsParams) WriteToRequest(r runtime.ClientRequest, reg strfmt.Registry) error { + if err := r.SetTimeout(o.timeout); err != nil { + return err + } + var res []error + + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} diff --git a/api/server/v1/json/client/server_service/get_read_only_settings_responses.go b/api/server/v1/json/client/server_service/get_read_only_settings_responses.go new file mode 100644 index 0000000000..2012bc3ad3 --- /dev/null +++ b/api/server/v1/json/client/server_service/get_read_only_settings_responses.go @@ -0,0 +1,724 @@ +// 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" + "encoding/json" + "fmt" + "io" + "strconv" + + "github.com/go-openapi/errors" + "github.com/go-openapi/runtime" + "github.com/go-openapi/strfmt" + "github.com/go-openapi/swag" +) + +// GetReadOnlySettingsReader is a Reader for the GetReadOnlySettings structure. +type GetReadOnlySettingsReader struct { + formats strfmt.Registry +} + +// ReadResponse reads a server response into the received o. +func (o *GetReadOnlySettingsReader) ReadResponse(response runtime.ClientResponse, consumer runtime.Consumer) (interface{}, error) { + switch response.Code() { + case 200: + result := NewGetReadOnlySettingsOK() + if err := result.readResponse(response, consumer, o.formats); err != nil { + return nil, err + } + return result, nil + default: + result := NewGetReadOnlySettingsDefault(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 + } +} + +// NewGetReadOnlySettingsOK creates a GetReadOnlySettingsOK with default headers values +func NewGetReadOnlySettingsOK() *GetReadOnlySettingsOK { + return &GetReadOnlySettingsOK{} +} + +/* +GetReadOnlySettingsOK describes a response with status code 200, with default header values. + +A successful response. +*/ +type GetReadOnlySettingsOK struct { + Payload *GetReadOnlySettingsOKBody +} + +// IsSuccess returns true when this get read only settings Ok response has a 2xx status code +func (o *GetReadOnlySettingsOK) IsSuccess() bool { + return true +} + +// IsRedirect returns true when this get read only settings Ok response has a 3xx status code +func (o *GetReadOnlySettingsOK) IsRedirect() bool { + return false +} + +// IsClientError returns true when this get read only settings Ok response has a 4xx status code +func (o *GetReadOnlySettingsOK) IsClientError() bool { + return false +} + +// IsServerError returns true when this get read only settings Ok response has a 5xx status code +func (o *GetReadOnlySettingsOK) IsServerError() bool { + return false +} + +// IsCode returns true when this get read only settings Ok response a status code equal to that given +func (o *GetReadOnlySettingsOK) IsCode(code int) bool { + return code == 200 +} + +// Code gets the status code for the get read only settings Ok response +func (o *GetReadOnlySettingsOK) Code() int { + return 200 +} + +func (o *GetReadOnlySettingsOK) Error() string { + payload, _ := json.Marshal(o.Payload) + return fmt.Sprintf("[GET /v1/server/settings/readonly][%d] getReadOnlySettingsOk %s", 200, payload) +} + +func (o *GetReadOnlySettingsOK) String() string { + payload, _ := json.Marshal(o.Payload) + return fmt.Sprintf("[GET /v1/server/settings/readonly][%d] getReadOnlySettingsOk %s", 200, payload) +} + +func (o *GetReadOnlySettingsOK) GetPayload() *GetReadOnlySettingsOKBody { + return o.Payload +} + +func (o *GetReadOnlySettingsOK) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error { + o.Payload = new(GetReadOnlySettingsOKBody) + + // response payload + if err := consumer.Consume(response.Body(), o.Payload); err != nil && err != io.EOF { + return err + } + + return nil +} + +// NewGetReadOnlySettingsDefault creates a GetReadOnlySettingsDefault with default headers values +func NewGetReadOnlySettingsDefault(code int) *GetReadOnlySettingsDefault { + return &GetReadOnlySettingsDefault{ + _statusCode: code, + } +} + +/* +GetReadOnlySettingsDefault describes a response with status code -1, with default header values. + +An unexpected error response. +*/ +type GetReadOnlySettingsDefault struct { + _statusCode int + + Payload *GetReadOnlySettingsDefaultBody +} + +// IsSuccess returns true when this get read only settings default response has a 2xx status code +func (o *GetReadOnlySettingsDefault) IsSuccess() bool { + return o._statusCode/100 == 2 +} + +// IsRedirect returns true when this get read only settings default response has a 3xx status code +func (o *GetReadOnlySettingsDefault) IsRedirect() bool { + return o._statusCode/100 == 3 +} + +// IsClientError returns true when this get read only settings default response has a 4xx status code +func (o *GetReadOnlySettingsDefault) IsClientError() bool { + return o._statusCode/100 == 4 +} + +// IsServerError returns true when this get read only settings default response has a 5xx status code +func (o *GetReadOnlySettingsDefault) IsServerError() bool { + return o._statusCode/100 == 5 +} + +// IsCode returns true when this get read only settings default response a status code equal to that given +func (o *GetReadOnlySettingsDefault) IsCode(code int) bool { + return o._statusCode == code +} + +// Code gets the status code for the get read only settings default response +func (o *GetReadOnlySettingsDefault) Code() int { + return o._statusCode +} + +func (o *GetReadOnlySettingsDefault) Error() string { + payload, _ := json.Marshal(o.Payload) + return fmt.Sprintf("[GET /v1/server/settings/readonly][%d] GetReadOnlySettings default %s", o._statusCode, payload) +} + +func (o *GetReadOnlySettingsDefault) String() string { + payload, _ := json.Marshal(o.Payload) + return fmt.Sprintf("[GET /v1/server/settings/readonly][%d] GetReadOnlySettings default %s", o._statusCode, payload) +} + +func (o *GetReadOnlySettingsDefault) GetPayload() *GetReadOnlySettingsDefaultBody { + return o.Payload +} + +func (o *GetReadOnlySettingsDefault) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error { + o.Payload = new(GetReadOnlySettingsDefaultBody) + + // response payload + if err := consumer.Consume(response.Body(), o.Payload); err != nil && err != io.EOF { + return err + } + + return nil +} + +/* +GetReadOnlySettingsDefaultBody get read only settings default body +swagger:model GetReadOnlySettingsDefaultBody +*/ +type GetReadOnlySettingsDefaultBody struct { + // code + Code int32 `json:"code,omitempty"` + + // message + Message string `json:"message,omitempty"` + + // details + Details []*GetReadOnlySettingsDefaultBodyDetailsItems0 `json:"details"` +} + +// Validate validates this get read only settings default body +func (o *GetReadOnlySettingsDefaultBody) 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 *GetReadOnlySettingsDefaultBody) 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("GetReadOnlySettings default" + "." + "details" + "." + strconv.Itoa(i)) + } else if ce, ok := err.(*errors.CompositeError); ok { + return ce.ValidateName("GetReadOnlySettings default" + "." + "details" + "." + strconv.Itoa(i)) + } + return err + } + } + + } + + return nil +} + +// ContextValidate validate this get read only settings default body based on the context it is used +func (o *GetReadOnlySettingsDefaultBody) 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 *GetReadOnlySettingsDefaultBody) contextValidateDetails(ctx context.Context, formats strfmt.Registry) error { + for i := 0; i < len(o.Details); i++ { + if o.Details[i] != nil { + + if swag.IsZero(o.Details[i]) { // not required + return nil + } + + if err := o.Details[i].ContextValidate(ctx, formats); err != nil { + if ve, ok := err.(*errors.Validation); ok { + return ve.ValidateName("GetReadOnlySettings default" + "." + "details" + "." + strconv.Itoa(i)) + } else if ce, ok := err.(*errors.CompositeError); ok { + return ce.ValidateName("GetReadOnlySettings default" + "." + "details" + "." + strconv.Itoa(i)) + } + return err + } + } + } + + return nil +} + +// MarshalBinary interface implementation +func (o *GetReadOnlySettingsDefaultBody) MarshalBinary() ([]byte, error) { + if o == nil { + return nil, nil + } + return swag.WriteJSON(o) +} + +// UnmarshalBinary interface implementation +func (o *GetReadOnlySettingsDefaultBody) UnmarshalBinary(b []byte) error { + var res GetReadOnlySettingsDefaultBody + if err := swag.ReadJSON(b, &res); err != nil { + return err + } + *o = res + return nil +} + +/* +GetReadOnlySettingsDefaultBodyDetailsItems0 `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 GetReadOnlySettingsDefaultBodyDetailsItems0 +*/ +type GetReadOnlySettingsDefaultBodyDetailsItems0 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"` + + // get read only settings default body details items0 + GetReadOnlySettingsDefaultBodyDetailsItems0 map[string]interface{} `json:"-"` +} + +// UnmarshalJSON unmarshals this object with additional properties from JSON +func (o *GetReadOnlySettingsDefaultBodyDetailsItems0) UnmarshalJSON(data []byte) error { + // stage 1, bind the properties + var stage1 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"` + } + if err := json.Unmarshal(data, &stage1); err != nil { + return err + } + var rcv GetReadOnlySettingsDefaultBodyDetailsItems0 + + rcv.AtType = stage1.AtType + *o = rcv + + // stage 2, remove properties and add to map + stage2 := make(map[string]json.RawMessage) + if err := json.Unmarshal(data, &stage2); err != nil { + return err + } + + delete(stage2, "@type") + // stage 3, add additional properties values + if len(stage2) > 0 { + result := make(map[string]interface{}) + for k, v := range stage2 { + var toadd interface{} + if err := json.Unmarshal(v, &toadd); err != nil { + return err + } + result[k] = toadd + } + o.GetReadOnlySettingsDefaultBodyDetailsItems0 = result + } + + return nil +} + +// MarshalJSON marshals this object with additional properties into a JSON object +func (o GetReadOnlySettingsDefaultBodyDetailsItems0) MarshalJSON() ([]byte, error) { + var stage1 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"` + } + + stage1.AtType = o.AtType + + // make JSON object for known properties + props, err := json.Marshal(stage1) + if err != nil { + return nil, err + } + + if len(o.GetReadOnlySettingsDefaultBodyDetailsItems0) == 0 { // no additional properties + return props, nil + } + + // make JSON object for the additional properties + additional, err := json.Marshal(o.GetReadOnlySettingsDefaultBodyDetailsItems0) + if err != nil { + return nil, err + } + + if len(props) < 3 { // "{}": only additional properties + return additional, nil + } + + // concatenate the 2 objects + return swag.ConcatJSON(props, additional), nil +} + +// Validate validates this get read only settings default body details items0 +func (o *GetReadOnlySettingsDefaultBodyDetailsItems0) Validate(formats strfmt.Registry) error { + return nil +} + +// ContextValidate validates this get read only settings default body details items0 based on context it is used +func (o *GetReadOnlySettingsDefaultBodyDetailsItems0) ContextValidate(ctx context.Context, formats strfmt.Registry) error { + return nil +} + +// MarshalBinary interface implementation +func (o *GetReadOnlySettingsDefaultBodyDetailsItems0) MarshalBinary() ([]byte, error) { + if o == nil { + return nil, nil + } + return swag.WriteJSON(o) +} + +// UnmarshalBinary interface implementation +func (o *GetReadOnlySettingsDefaultBodyDetailsItems0) UnmarshalBinary(b []byte) error { + var res GetReadOnlySettingsDefaultBodyDetailsItems0 + if err := swag.ReadJSON(b, &res); err != nil { + return err + } + *o = res + return nil +} + +/* +GetReadOnlySettingsOKBody get read only settings OK body +swagger:model GetReadOnlySettingsOKBody +*/ +type GetReadOnlySettingsOKBody struct { + // settings + Settings *GetReadOnlySettingsOKBodySettings `json:"settings,omitempty"` +} + +// Validate validates this get read only settings OK body +func (o *GetReadOnlySettingsOKBody) Validate(formats strfmt.Registry) error { + var res []error + + if err := o.validateSettings(formats); err != nil { + res = append(res, err) + } + + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} + +func (o *GetReadOnlySettingsOKBody) validateSettings(formats strfmt.Registry) error { + if swag.IsZero(o.Settings) { // not required + return nil + } + + if o.Settings != nil { + if err := o.Settings.Validate(formats); err != nil { + if ve, ok := err.(*errors.Validation); ok { + return ve.ValidateName("getReadOnlySettingsOk" + "." + "settings") + } else if ce, ok := err.(*errors.CompositeError); ok { + return ce.ValidateName("getReadOnlySettingsOk" + "." + "settings") + } + return err + } + } + + return nil +} + +// ContextValidate validate this get read only settings OK body based on the context it is used +func (o *GetReadOnlySettingsOKBody) ContextValidate(ctx context.Context, formats strfmt.Registry) error { + var res []error + + if err := o.contextValidateSettings(ctx, formats); err != nil { + res = append(res, err) + } + + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} + +func (o *GetReadOnlySettingsOKBody) contextValidateSettings(ctx context.Context, formats strfmt.Registry) error { + if o.Settings != nil { + + if swag.IsZero(o.Settings) { // not required + return nil + } + + if err := o.Settings.ContextValidate(ctx, formats); err != nil { + if ve, ok := err.(*errors.Validation); ok { + return ve.ValidateName("getReadOnlySettingsOk" + "." + "settings") + } else if ce, ok := err.(*errors.CompositeError); ok { + return ce.ValidateName("getReadOnlySettingsOk" + "." + "settings") + } + return err + } + } + + return nil +} + +// MarshalBinary interface implementation +func (o *GetReadOnlySettingsOKBody) MarshalBinary() ([]byte, error) { + if o == nil { + return nil, nil + } + return swag.WriteJSON(o) +} + +// UnmarshalBinary interface implementation +func (o *GetReadOnlySettingsOKBody) UnmarshalBinary(b []byte) error { + var res GetReadOnlySettingsOKBody + if err := swag.ReadJSON(b, &res); err != nil { + return err + } + *o = res + return nil +} + +/* +GetReadOnlySettingsOKBodySettings ReadOnlySettings represents a stripped-down version of PMM Server settings that can be accessed by users of all roles. +swagger:model GetReadOnlySettingsOKBodySettings +*/ +type GetReadOnlySettingsOKBodySettings struct { + // True if updates are enabled. + UpdatesEnabled bool `json:"updates_enabled,omitempty"` + + // True if telemetry is enabled. + TelemetryEnabled bool `json:"telemetry_enabled,omitempty"` + + // True if Advisor is enabled. + AdvisorEnabled bool `json:"advisor_enabled,omitempty"` + + // True if Alerting is enabled. + AlertingEnabled bool `json:"alerting_enabled,omitempty"` + + // PMM Server public address. + PMMPublicAddress string `json:"pmm_public_address,omitempty"` + + // True if Backup Management is enabled. + BackupManagementEnabled bool `json:"backup_management_enabled,omitempty"` + + // True if Azure Discover is enabled. + AzurediscoverEnabled bool `json:"azurediscover_enabled,omitempty"` + + // True if Access Control is enabled. + EnableAccessControl bool `json:"enable_access_control,omitempty"` +} + +// Validate validates this get read only settings OK body settings +func (o *GetReadOnlySettingsOKBodySettings) Validate(formats strfmt.Registry) error { + return nil +} + +// ContextValidate validates this get read only settings OK body settings based on context it is used +func (o *GetReadOnlySettingsOKBodySettings) ContextValidate(ctx context.Context, formats strfmt.Registry) error { + return nil +} + +// MarshalBinary interface implementation +func (o *GetReadOnlySettingsOKBodySettings) MarshalBinary() ([]byte, error) { + if o == nil { + return nil, nil + } + return swag.WriteJSON(o) +} + +// UnmarshalBinary interface implementation +func (o *GetReadOnlySettingsOKBodySettings) UnmarshalBinary(b []byte) error { + var res GetReadOnlySettingsOKBodySettings + 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 2a845ec6d4..6f4064d0c4 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 @@ -84,6 +84,8 @@ type ClientService interface { CheckUpdates(params *CheckUpdatesParams, opts ...ClientOption) (*CheckUpdatesOK, error) + GetReadOnlySettings(params *GetReadOnlySettingsParams, opts ...ClientOption) (*GetReadOnlySettingsOK, error) + GetSettings(params *GetSettingsParams, opts ...ClientOption) (*GetSettingsOK, error) LeaderHealthCheck(params *LeaderHealthCheckParams, opts ...ClientOption) (*LeaderHealthCheckOK, error) @@ -181,6 +183,45 @@ func (a *Client) CheckUpdates(params *CheckUpdatesParams, opts ...ClientOption) return nil, runtime.NewAPIError("unexpected success response: content available as default response in error", unexpectedSuccess, unexpectedSuccess.Code()) } +/* +GetReadOnlySettings gets read only settings + +Returns a stripped version of PMM Server settings. +*/ +func (a *Client) GetReadOnlySettings(params *GetReadOnlySettingsParams, opts ...ClientOption) (*GetReadOnlySettingsOK, error) { + // TODO: Validate the params before sending + if params == nil { + params = NewGetReadOnlySettingsParams() + } + op := &runtime.ClientOperation{ + ID: "GetReadOnlySettings", + Method: "GET", + PathPattern: "/v1/server/settings/readonly", + ProducesMediaTypes: []string{"application/json"}, + ConsumesMediaTypes: []string{"application/json"}, + Schemes: []string{"http", "https"}, + Params: params, + Reader: &GetReadOnlySettingsReader{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.(*GetReadOnlySettingsOK) + if ok { + return success, nil + } + // unexpected success response + unexpectedSuccess := result.(*GetReadOnlySettingsDefault) + return nil, runtime.NewAPIError("unexpected success response: content available as default response in error", unexpectedSuccess, unexpectedSuccess.Code()) +} + /* GetSettings gets settings diff --git a/api/server/v1/json/v1.json b/api/server/v1/json/v1.json index 3679b17766..101f026dc0 100644 --- a/api/server/v1/json/v1.json +++ b/api/server/v1/json/v1.json @@ -658,6 +658,106 @@ } } }, + "/v1/server/settings/readonly": { + "get": { + "description": "Returns a stripped version of PMM Server settings.", + "tags": [ + "ServerService" + ], + "summary": "Get read-only settings", + "operationId": "GetReadOnlySettings", + "responses": { + "200": { + "description": "A successful response.", + "schema": { + "type": "object", + "properties": { + "settings": { + "description": "ReadOnlySettings represents a stripped-down version of PMM Server settings that can be accessed by users of all roles.", + "type": "object", + "properties": { + "updates_enabled": { + "description": "True if updates are enabled.", + "type": "boolean", + "x-order": 0 + }, + "telemetry_enabled": { + "description": "True if telemetry is enabled.", + "type": "boolean", + "x-order": 1 + }, + "advisor_enabled": { + "description": "True if Advisor is enabled.", + "type": "boolean", + "x-order": 2 + }, + "alerting_enabled": { + "description": "True if Alerting is enabled.", + "type": "boolean", + "x-order": 3 + }, + "pmm_public_address": { + "description": "PMM Server public address.", + "type": "string", + "x-order": 4 + }, + "backup_management_enabled": { + "description": "True if Backup Management is enabled.", + "type": "boolean", + "x-order": 5 + }, + "azurediscover_enabled": { + "description": "True if Azure Discover is enabled.", + "type": "boolean", + "x-order": 6 + }, + "enable_access_control": { + "description": "True if Access Control is enabled.", + "type": "boolean", + "x-order": 7 + } + }, + "x-order": 0 + } + } + } + }, + "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": {} + }, + "x-order": 2 + } + } + } + } + } + } + }, "/v1/server/updates": { "get": { "description": "Checks for available PMM Server updates.", diff --git a/api/server/v1/server.pb.go b/api/server/v1/server.pb.go index 6ef852521f..78dc79db27 100644 --- a/api/server/v1/server.pb.go +++ b/api/server/v1/server.pb.go @@ -1247,6 +1247,115 @@ func (x *Settings) GetDefaultRoleId() uint32 { return 0 } +// ReadOnlySettings represents a stripped-down version of PMM Server settings that can be accessed by users of all roles. +type ReadOnlySettings struct { + state protoimpl.MessageState `protogen:"open.v1"` + // True if updates are enabled. + UpdatesEnabled bool `protobuf:"varint,1,opt,name=updates_enabled,json=updatesEnabled,proto3" json:"updates_enabled,omitempty"` + // True if telemetry is enabled. + TelemetryEnabled bool `protobuf:"varint,2,opt,name=telemetry_enabled,json=telemetryEnabled,proto3" json:"telemetry_enabled,omitempty"` + // True if Advisor is enabled. + AdvisorEnabled bool `protobuf:"varint,3,opt,name=advisor_enabled,json=advisorEnabled,proto3" json:"advisor_enabled,omitempty"` + // True if Alerting is enabled. + AlertingEnabled bool `protobuf:"varint,4,opt,name=alerting_enabled,json=alertingEnabled,proto3" json:"alerting_enabled,omitempty"` + // PMM Server public address. + PmmPublicAddress string `protobuf:"bytes,5,opt,name=pmm_public_address,json=pmmPublicAddress,proto3" json:"pmm_public_address,omitempty"` + // True if Backup Management is enabled. + BackupManagementEnabled bool `protobuf:"varint,6,opt,name=backup_management_enabled,json=backupManagementEnabled,proto3" json:"backup_management_enabled,omitempty"` + // True if Azure Discover is enabled. + AzurediscoverEnabled bool `protobuf:"varint,7,opt,name=azurediscover_enabled,json=azurediscoverEnabled,proto3" json:"azurediscover_enabled,omitempty"` + // True if Access Control is enabled. + EnableAccessControl bool `protobuf:"varint,8,opt,name=enable_access_control,json=enableAccessControl,proto3" json:"enable_access_control,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ReadOnlySettings) Reset() { + *x = ReadOnlySettings{} + mi := &file_server_v1_server_proto_msgTypes[19] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ReadOnlySettings) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ReadOnlySettings) ProtoMessage() {} + +func (x *ReadOnlySettings) ProtoReflect() protoreflect.Message { + mi := &file_server_v1_server_proto_msgTypes[19] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ReadOnlySettings.ProtoReflect.Descriptor instead. +func (*ReadOnlySettings) Descriptor() ([]byte, []int) { + return file_server_v1_server_proto_rawDescGZIP(), []int{19} +} + +func (x *ReadOnlySettings) GetUpdatesEnabled() bool { + if x != nil { + return x.UpdatesEnabled + } + return false +} + +func (x *ReadOnlySettings) GetTelemetryEnabled() bool { + if x != nil { + return x.TelemetryEnabled + } + return false +} + +func (x *ReadOnlySettings) GetAdvisorEnabled() bool { + if x != nil { + return x.AdvisorEnabled + } + return false +} + +func (x *ReadOnlySettings) GetAlertingEnabled() bool { + if x != nil { + return x.AlertingEnabled + } + return false +} + +func (x *ReadOnlySettings) GetPmmPublicAddress() string { + if x != nil { + return x.PmmPublicAddress + } + return "" +} + +func (x *ReadOnlySettings) GetBackupManagementEnabled() bool { + if x != nil { + return x.BackupManagementEnabled + } + return false +} + +func (x *ReadOnlySettings) GetAzurediscoverEnabled() bool { + if x != nil { + return x.AzurediscoverEnabled + } + return false +} + +func (x *ReadOnlySettings) GetEnableAccessControl() bool { + if x != nil { + return x.EnableAccessControl + } + return false +} + type GetSettingsRequest struct { state protoimpl.MessageState `protogen:"open.v1"` unknownFields protoimpl.UnknownFields @@ -1255,7 +1364,7 @@ type GetSettingsRequest struct { func (x *GetSettingsRequest) Reset() { *x = GetSettingsRequest{} - mi := &file_server_v1_server_proto_msgTypes[19] + mi := &file_server_v1_server_proto_msgTypes[20] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1267,7 +1376,7 @@ func (x *GetSettingsRequest) String() string { func (*GetSettingsRequest) ProtoMessage() {} func (x *GetSettingsRequest) ProtoReflect() protoreflect.Message { - mi := &file_server_v1_server_proto_msgTypes[19] + mi := &file_server_v1_server_proto_msgTypes[20] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1280,7 +1389,43 @@ 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{19} + return file_server_v1_server_proto_rawDescGZIP(), []int{20} +} + +type GetReadOnlySettingsRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *GetReadOnlySettingsRequest) Reset() { + *x = GetReadOnlySettingsRequest{} + mi := &file_server_v1_server_proto_msgTypes[21] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *GetReadOnlySettingsRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetReadOnlySettingsRequest) ProtoMessage() {} + +func (x *GetReadOnlySettingsRequest) ProtoReflect() protoreflect.Message { + mi := &file_server_v1_server_proto_msgTypes[21] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetReadOnlySettingsRequest.ProtoReflect.Descriptor instead. +func (*GetReadOnlySettingsRequest) Descriptor() ([]byte, []int) { + return file_server_v1_server_proto_rawDescGZIP(), []int{21} } type GetSettingsResponse struct { @@ -1292,7 +1437,7 @@ type GetSettingsResponse struct { func (x *GetSettingsResponse) Reset() { *x = GetSettingsResponse{} - 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) } @@ -1304,7 +1449,7 @@ func (x *GetSettingsResponse) String() string { func (*GetSettingsResponse) ProtoMessage() {} func (x *GetSettingsResponse) ProtoReflect() protoreflect.Message { - mi := &file_server_v1_server_proto_msgTypes[20] + mi := &file_server_v1_server_proto_msgTypes[22] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1317,7 +1462,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{20} + return file_server_v1_server_proto_rawDescGZIP(), []int{22} } func (x *GetSettingsResponse) GetSettings() *Settings { @@ -1327,6 +1472,50 @@ func (x *GetSettingsResponse) GetSettings() *Settings { return nil } +type GetReadOnlySettingsResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + Settings *ReadOnlySettings `protobuf:"bytes,1,opt,name=settings,proto3" json:"settings,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *GetReadOnlySettingsResponse) Reset() { + *x = GetReadOnlySettingsResponse{} + mi := &file_server_v1_server_proto_msgTypes[23] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *GetReadOnlySettingsResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetReadOnlySettingsResponse) ProtoMessage() {} + +func (x *GetReadOnlySettingsResponse) ProtoReflect() protoreflect.Message { + mi := &file_server_v1_server_proto_msgTypes[23] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetReadOnlySettingsResponse.ProtoReflect.Descriptor instead. +func (*GetReadOnlySettingsResponse) Descriptor() ([]byte, []int) { + return file_server_v1_server_proto_rawDescGZIP(), []int{23} +} + +func (x *GetReadOnlySettingsResponse) GetSettings() *ReadOnlySettings { + if x != nil { + return x.Settings + } + return nil +} + type ChangeSettingsRequest struct { state protoimpl.MessageState `protogen:"open.v1"` EnableUpdates *bool `protobuf:"varint,1,opt,name=enable_updates,json=enableUpdates,proto3,oneof" json:"enable_updates,omitempty"` @@ -1356,7 +1545,7 @@ type ChangeSettingsRequest struct { func (x *ChangeSettingsRequest) Reset() { *x = ChangeSettingsRequest{} - mi := &file_server_v1_server_proto_msgTypes[21] + mi := &file_server_v1_server_proto_msgTypes[24] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1368,7 +1557,7 @@ func (x *ChangeSettingsRequest) String() string { func (*ChangeSettingsRequest) ProtoMessage() {} func (x *ChangeSettingsRequest) ProtoReflect() protoreflect.Message { - mi := &file_server_v1_server_proto_msgTypes[21] + mi := &file_server_v1_server_proto_msgTypes[24] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1381,7 +1570,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{21} + return file_server_v1_server_proto_rawDescGZIP(), []int{24} } func (x *ChangeSettingsRequest) GetEnableUpdates() bool { @@ -1484,7 +1673,7 @@ type ChangeSettingsResponse struct { func (x *ChangeSettingsResponse) Reset() { *x = ChangeSettingsResponse{} - mi := &file_server_v1_server_proto_msgTypes[22] + mi := &file_server_v1_server_proto_msgTypes[25] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1496,7 +1685,7 @@ func (x *ChangeSettingsResponse) String() string { func (*ChangeSettingsResponse) ProtoMessage() {} func (x *ChangeSettingsResponse) ProtoReflect() protoreflect.Message { - mi := &file_server_v1_server_proto_msgTypes[22] + mi := &file_server_v1_server_proto_msgTypes[25] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1509,7 +1698,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{22} + return file_server_v1_server_proto_rawDescGZIP(), []int{25} } func (x *ChangeSettingsResponse) GetSettings() *Settings { @@ -1711,213 +1900,259 @@ var file_server_v1_server_proto_rawDesc = string([]byte{ 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, + 0x6c, 0x65, 0x49, 0x64, 0x22, 0x8f, 0x03, 0x0a, 0x10, 0x52, 0x65, 0x61, 0x64, 0x4f, 0x6e, 0x6c, + 0x79, 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, + 0x27, 0x0a, 0x0f, 0x61, 0x64, 0x76, 0x69, 0x73, 0x6f, 0x72, 0x5f, 0x65, 0x6e, 0x61, 0x62, 0x6c, + 0x65, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0e, 0x61, 0x64, 0x76, 0x69, 0x73, 0x6f, + 0x72, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x12, 0x29, 0x0a, 0x10, 0x61, 0x6c, 0x65, 0x72, + 0x74, 0x69, 0x6e, 0x67, 0x5f, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18, 0x04, 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, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x10, 0x70, 0x6d, 0x6d, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, + 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, 0x06, + 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, 0x07, 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, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x61, 0x63, 0x63, + 0x65, 0x73, 0x73, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x18, 0x08, 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, 0x22, 0x14, 0x0a, 0x12, 0x47, 0x65, 0x74, 0x53, 0x65, 0x74, + 0x74, 0x69, 0x6e, 0x67, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x1c, 0x0a, 0x1a, + 0x47, 0x65, 0x74, 0x52, 0x65, 0x61, 0x64, 0x4f, 0x6e, 0x6c, 0x79, 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, 0xfd, 0x0d, 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, 0xe9, 0x01, 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, 0x91, 0x01, 0x92, 0x41, 0x69, - 0x12, 0x11, 0x47, 0x65, 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, - 0x6c, 0x6f, 0x67, 0x1a, 0x54, 0x44, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x20, 0x61, 0x20, 0x63, - 0x68, 0x61, 0x6e, 0x67, 0x65, 0x6c, 0x6f, 0x67, 0x20, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x72, 0x69, - 0x6e, 0x67, 0x20, 0x74, 0x68, 0x65, 0x20, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x65, 0x64, - 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x74, 0x6f, 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, 0x2e, 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, 0x1e, 0x2e, - 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x74, 0x61, 0x72, 0x74, 0x55, - 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x4f, 0x92, - 0x41, 0x29, 0x12, 0x0c, 0x53, 0x74, 0x61, 0x72, 0x74, 0x20, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, - 0x1a, 0x19, 0x53, 0x74, 0x61, 0x72, 0x74, 0x73, 0x20, 0x50, 0x4d, 0x4d, 0x20, 0x53, 0x65, 0x72, - 0x76, 0x65, 0x72, 0x20, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x2e, 0x82, 0xd3, 0xe4, 0x93, 0x02, - 0x1d, 0x3a, 0x01, 0x2a, 0x22, 0x18, 0x2f, 0x76, 0x31, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, - 0x2f, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x73, 0x3a, 0x73, 0x74, 0x61, 0x72, 0x74, 0x12, 0xad, - 0x01, 0x0a, 0x0c, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, - 0x1e, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x70, 0x64, 0x61, - 0x74, 0x65, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x1f, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x70, 0x64, 0x61, - 0x74, 0x65, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x22, 0x5c, 0x92, 0x41, 0x32, 0x12, 0x0d, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x20, 0x73, 0x74, - 0x61, 0x74, 0x75, 0x73, 0x1a, 0x21, 0x52, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x73, 0x20, 0x50, 0x4d, - 0x4d, 0x20, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x20, - 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x2e, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x21, 0x3a, 0x01, 0x2a, - 0x22, 0x1c, 0x2f, 0x76, 0x31, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2f, 0x75, 0x70, 0x64, - 0x61, 0x74, 0x65, 0x73, 0x3a, 0x67, 0x65, 0x74, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0xa0, - 0x01, 0x0a, 0x0b, 0x47, 0x65, 0x74, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x1d, - 0x2e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x65, - 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, - 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x65, 0x74, - 0x74, 0x69, 0x6e, 0x67, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x52, 0x92, - 0x41, 0x34, 0x12, 0x0c, 0x47, 0x65, 0x74, 0x20, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, - 0x1a, 0x24, 0x52, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x73, 0x20, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, - 0x74, 0x20, 0x50, 0x4d, 0x4d, 0x20, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x73, 0x65, 0x74, - 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x15, 0x12, 0x13, 0x2f, 0x76, - 0x31, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2f, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, - 0x73, 0x12, 0xa7, 0x01, 0x0a, 0x0e, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x53, 0x65, 0x74, 0x74, - 0x69, 0x6e, 0x67, 0x73, 0x12, 0x20, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x76, 0x31, - 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x21, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, - 0x76, 0x31, 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, - 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x50, 0x92, 0x41, 0x2f, 0x12, 0x0f, - 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x20, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x1a, - 0x1c, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x20, 0x50, 0x4d, 0x4d, 0x20, 0x53, 0x65, 0x72, - 0x76, 0x65, 0x72, 0x20, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x82, 0xd3, 0xe4, - 0x93, 0x02, 0x18, 0x3a, 0x01, 0x2a, 0x1a, 0x13, 0x2f, 0x76, 0x31, 0x2f, 0x73, 0x65, 0x72, 0x76, - 0x65, 0x72, 0x2f, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x42, 0x90, 0x01, 0x0a, 0x0d, - 0x63, 0x6f, 0x6d, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x42, 0x0b, 0x53, - 0x65, 0x72, 0x76, 0x65, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x2d, 0x67, 0x69, - 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x65, 0x72, 0x63, 0x6f, 0x6e, 0x61, - 0x2f, 0x70, 0x6d, 0x6d, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2f, - 0x76, 0x31, 0x3b, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x76, 0x31, 0xa2, 0x02, 0x03, 0x53, 0x58, - 0x58, 0xaa, 0x02, 0x09, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x56, 0x31, 0xca, 0x02, 0x09, - 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x5c, 0x56, 0x31, 0xe2, 0x02, 0x15, 0x53, 0x65, 0x72, 0x76, - 0x65, 0x72, 0x5c, 0x56, 0x31, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, - 0x61, 0xea, 0x02, 0x0a, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x3a, 0x3a, 0x56, 0x31, 0x62, 0x06, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x67, 0x73, 0x22, 0x56, 0x0a, 0x1b, 0x47, 0x65, 0x74, 0x52, 0x65, 0x61, 0x64, 0x4f, 0x6e, 0x6c, + 0x79, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x12, 0x37, 0x0a, 0x08, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, + 0x52, 0x65, 0x61, 0x64, 0x4f, 0x6e, 0x6c, 0x79, 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, 0xd9, 0x0f, 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, 0xe9, 0x01, 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, 0x91, 0x01, 0x92, 0x41, 0x69, 0x12, 0x11, 0x47, 0x65, 0x74, 0x20, 0x74, 0x68, + 0x65, 0x20, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x6c, 0x6f, 0x67, 0x1a, 0x54, 0x44, 0x69, 0x73, + 0x70, 0x6c, 0x61, 0x79, 0x20, 0x61, 0x20, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x6c, 0x6f, 0x67, + 0x20, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x72, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x68, 0x65, 0x20, 0x69, + 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x65, 0x64, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, + 0x20, 0x74, 0x6f, 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, + 0x2e, 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, 0x1e, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x76, + 0x31, 0x2e, 0x53, 0x74, 0x61, 0x72, 0x74, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x4f, 0x92, 0x41, 0x29, 0x12, 0x0c, 0x53, 0x74, 0x61, 0x72, + 0x74, 0x20, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x1a, 0x19, 0x53, 0x74, 0x61, 0x72, 0x74, 0x73, + 0x20, 0x50, 0x4d, 0x4d, 0x20, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x75, 0x70, 0x64, 0x61, + 0x74, 0x65, 0x2e, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1d, 0x3a, 0x01, 0x2a, 0x22, 0x18, 0x2f, 0x76, + 0x31, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2f, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x73, + 0x3a, 0x73, 0x74, 0x61, 0x72, 0x74, 0x12, 0xad, 0x01, 0x0a, 0x0c, 0x55, 0x70, 0x64, 0x61, 0x74, + 0x65, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x1e, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, + 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1f, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, + 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x5c, 0x92, 0x41, 0x32, 0x12, 0x0d, 0x55, + 0x70, 0x64, 0x61, 0x74, 0x65, 0x20, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x1a, 0x21, 0x52, 0x65, + 0x74, 0x75, 0x72, 0x6e, 0x73, 0x20, 0x50, 0x4d, 0x4d, 0x20, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, + 0x20, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x20, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x2e, 0x82, + 0xd3, 0xe4, 0x93, 0x02, 0x21, 0x3a, 0x01, 0x2a, 0x22, 0x1c, 0x2f, 0x76, 0x31, 0x2f, 0x73, 0x65, + 0x72, 0x76, 0x65, 0x72, 0x2f, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x73, 0x3a, 0x67, 0x65, 0x74, + 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0xa0, 0x01, 0x0a, 0x0b, 0x47, 0x65, 0x74, 0x53, 0x65, + 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x1d, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, + 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x76, + 0x31, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x52, 0x92, 0x41, 0x34, 0x12, 0x0c, 0x47, 0x65, 0x74, 0x20, + 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x1a, 0x24, 0x52, 0x65, 0x74, 0x75, 0x72, 0x6e, + 0x73, 0x20, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x20, 0x50, 0x4d, 0x4d, 0x20, 0x53, 0x65, + 0x72, 0x76, 0x65, 0x72, 0x20, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2e, 0x82, 0xd3, + 0xe4, 0x93, 0x02, 0x15, 0x12, 0x13, 0x2f, 0x76, 0x31, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, + 0x2f, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x12, 0xd9, 0x01, 0x0a, 0x13, 0x47, 0x65, + 0x74, 0x52, 0x65, 0x61, 0x64, 0x4f, 0x6e, 0x6c, 0x79, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, + 0x73, 0x12, 0x25, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, + 0x74, 0x52, 0x65, 0x61, 0x64, 0x4f, 0x6e, 0x6c, 0x79, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, + 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x26, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x65, + 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x65, 0x61, 0x64, 0x4f, 0x6e, 0x6c, 0x79, + 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x22, 0x73, 0x92, 0x41, 0x4c, 0x12, 0x16, 0x47, 0x65, 0x74, 0x20, 0x72, 0x65, 0x61, 0x64, 0x2d, + 0x6f, 0x6e, 0x6c, 0x79, 0x20, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x1a, 0x32, 0x52, + 0x65, 0x74, 0x75, 0x72, 0x6e, 0x73, 0x20, 0x61, 0x20, 0x73, 0x74, 0x72, 0x69, 0x70, 0x70, 0x65, + 0x64, 0x20, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x6f, 0x66, 0x20, 0x50, 0x4d, 0x4d, + 0x20, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, + 0x2e, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1e, 0x12, 0x1c, 0x2f, 0x76, 0x31, 0x2f, 0x73, 0x65, 0x72, + 0x76, 0x65, 0x72, 0x2f, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x2f, 0x72, 0x65, 0x61, + 0x64, 0x6f, 0x6e, 0x6c, 0x79, 0x12, 0xa7, 0x01, 0x0a, 0x0e, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, + 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x20, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x65, + 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x53, 0x65, 0x74, 0x74, 0x69, + 0x6e, 0x67, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x21, 0x2e, 0x73, 0x65, 0x72, + 0x76, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x53, 0x65, 0x74, + 0x74, 0x69, 0x6e, 0x67, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x50, 0x92, + 0x41, 0x2f, 0x12, 0x0f, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x20, 0x73, 0x65, 0x74, 0x74, 0x69, + 0x6e, 0x67, 0x73, 0x1a, 0x1c, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x20, 0x50, 0x4d, 0x4d, + 0x20, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, + 0x2e, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x18, 0x3a, 0x01, 0x2a, 0x1a, 0x13, 0x2f, 0x76, 0x31, 0x2f, + 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2f, 0x73, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x42, + 0x90, 0x01, 0x0a, 0x0d, 0x63, 0x6f, 0x6d, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x76, + 0x31, 0x42, 0x0b, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, + 0x5a, 0x2d, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x65, 0x72, + 0x63, 0x6f, 0x6e, 0x61, 0x2f, 0x70, 0x6d, 0x6d, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x73, 0x65, 0x72, + 0x76, 0x65, 0x72, 0x2f, 0x76, 0x31, 0x3b, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x76, 0x31, 0xa2, + 0x02, 0x03, 0x53, 0x58, 0x58, 0xaa, 0x02, 0x09, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2e, 0x56, + 0x31, 0xca, 0x02, 0x09, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x5c, 0x56, 0x31, 0xe2, 0x02, 0x15, + 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x5c, 0x56, 0x31, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, + 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x0a, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x3a, 0x3a, + 0x56, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, }) var ( @@ -1934,87 +2169,93 @@ 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, 23) + file_server_v1_server_proto_msgTypes = make([]protoimpl.MessageInfo, 26) file_server_v1_server_proto_goTypes = []any{ - (DistributionMethod)(0), // 0: server.v1.DistributionMethod - (*VersionInfo)(nil), // 1: server.v1.VersionInfo - (*VersionRequest)(nil), // 2: server.v1.VersionRequest - (*VersionResponse)(nil), // 3: server.v1.VersionResponse - (*ReadinessRequest)(nil), // 4: server.v1.ReadinessRequest - (*ReadinessResponse)(nil), // 5: server.v1.ReadinessResponse - (*LeaderHealthCheckRequest)(nil), // 6: server.v1.LeaderHealthCheckRequest - (*LeaderHealthCheckResponse)(nil), // 7: server.v1.LeaderHealthCheckResponse - (*CheckUpdatesRequest)(nil), // 8: server.v1.CheckUpdatesRequest - (*DockerVersionInfo)(nil), // 9: server.v1.DockerVersionInfo - (*CheckUpdatesResponse)(nil), // 10: server.v1.CheckUpdatesResponse - (*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 + (DistributionMethod)(0), // 0: server.v1.DistributionMethod + (*VersionInfo)(nil), // 1: server.v1.VersionInfo + (*VersionRequest)(nil), // 2: server.v1.VersionRequest + (*VersionResponse)(nil), // 3: server.v1.VersionResponse + (*ReadinessRequest)(nil), // 4: server.v1.ReadinessRequest + (*ReadinessResponse)(nil), // 5: server.v1.ReadinessResponse + (*LeaderHealthCheckRequest)(nil), // 6: server.v1.LeaderHealthCheckRequest + (*LeaderHealthCheckResponse)(nil), // 7: server.v1.LeaderHealthCheckResponse + (*CheckUpdatesRequest)(nil), // 8: server.v1.CheckUpdatesRequest + (*DockerVersionInfo)(nil), // 9: server.v1.DockerVersionInfo + (*CheckUpdatesResponse)(nil), // 10: server.v1.CheckUpdatesResponse + (*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 + (*ReadOnlySettings)(nil), // 20: server.v1.ReadOnlySettings + (*GetSettingsRequest)(nil), // 21: server.v1.GetSettingsRequest + (*GetReadOnlySettingsRequest)(nil), // 22: server.v1.GetReadOnlySettingsRequest + (*GetSettingsResponse)(nil), // 23: server.v1.GetSettingsResponse + (*GetReadOnlySettingsResponse)(nil), // 24: server.v1.GetReadOnlySettingsResponse + (*ChangeSettingsRequest)(nil), // 25: server.v1.ChangeSettingsRequest + (*ChangeSettingsResponse)(nil), // 26: server.v1.ChangeSettingsResponse + (*timestamppb.Timestamp)(nil), // 27: google.protobuf.Timestamp + (*durationpb.Duration)(nil), // 28: google.protobuf.Duration + (*common.StringArray)(nil), // 29: common.StringArray } ) var file_server_v1_server_proto_depIdxs = []int32{ - 24, // 0: server.v1.VersionInfo.timestamp:type_name -> google.protobuf.Timestamp + 27, // 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 - 24, // 4: server.v1.DockerVersionInfo.timestamp:type_name -> google.protobuf.Timestamp + 27, // 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 - 24, // 7: server.v1.CheckUpdatesResponse.last_check:type_name -> google.protobuf.Timestamp + 27, // 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 + 27, // 9: server.v1.ListChangeLogsResponse.last_check:type_name -> google.protobuf.Timestamp + 28, // 10: server.v1.MetricsResolutions.hr:type_name -> google.protobuf.Duration + 28, // 11: server.v1.MetricsResolutions.mr:type_name -> google.protobuf.Duration + 28, // 12: server.v1.MetricsResolutions.lr:type_name -> google.protobuf.Duration + 28, // 13: server.v1.AdvisorRunIntervals.standard_interval:type_name -> google.protobuf.Duration + 28, // 14: server.v1.AdvisorRunIntervals.rare_interval:type_name -> google.protobuf.Duration + 28, // 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 + 28, // 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 + 20, // 20: server.v1.GetReadOnlySettingsResponse.settings:type_name -> server.v1.ReadOnlySettings + 17, // 21: server.v1.ChangeSettingsRequest.metrics_resolutions:type_name -> server.v1.MetricsResolutions + 28, // 22: server.v1.ChangeSettingsRequest.data_retention:type_name -> google.protobuf.Duration + 29, // 23: server.v1.ChangeSettingsRequest.aws_partitions:type_name -> common.StringArray + 18, // 24: server.v1.ChangeSettingsRequest.advisor_run_intervals:type_name -> server.v1.AdvisorRunIntervals + 19, // 25: server.v1.ChangeSettingsResponse.settings:type_name -> server.v1.Settings + 2, // 26: server.v1.ServerService.Version:input_type -> server.v1.VersionRequest + 4, // 27: server.v1.ServerService.Readiness:input_type -> server.v1.ReadinessRequest + 6, // 28: server.v1.ServerService.LeaderHealthCheck:input_type -> server.v1.LeaderHealthCheckRequest + 8, // 29: server.v1.ServerService.CheckUpdates:input_type -> server.v1.CheckUpdatesRequest + 11, // 30: server.v1.ServerService.ListChangeLogs:input_type -> server.v1.ListChangeLogsRequest + 13, // 31: server.v1.ServerService.StartUpdate:input_type -> server.v1.StartUpdateRequest + 15, // 32: server.v1.ServerService.UpdateStatus:input_type -> server.v1.UpdateStatusRequest + 21, // 33: server.v1.ServerService.GetSettings:input_type -> server.v1.GetSettingsRequest + 22, // 34: server.v1.ServerService.GetReadOnlySettings:input_type -> server.v1.GetReadOnlySettingsRequest + 25, // 35: server.v1.ServerService.ChangeSettings:input_type -> server.v1.ChangeSettingsRequest + 3, // 36: server.v1.ServerService.Version:output_type -> server.v1.VersionResponse + 5, // 37: server.v1.ServerService.Readiness:output_type -> server.v1.ReadinessResponse + 7, // 38: server.v1.ServerService.LeaderHealthCheck:output_type -> server.v1.LeaderHealthCheckResponse + 10, // 39: server.v1.ServerService.CheckUpdates:output_type -> server.v1.CheckUpdatesResponse + 12, // 40: server.v1.ServerService.ListChangeLogs:output_type -> server.v1.ListChangeLogsResponse + 14, // 41: server.v1.ServerService.StartUpdate:output_type -> server.v1.StartUpdateResponse + 16, // 42: server.v1.ServerService.UpdateStatus:output_type -> server.v1.UpdateStatusResponse + 23, // 43: server.v1.ServerService.GetSettings:output_type -> server.v1.GetSettingsResponse + 24, // 44: server.v1.ServerService.GetReadOnlySettings:output_type -> server.v1.GetReadOnlySettingsResponse + 26, // 45: server.v1.ServerService.ChangeSettings:output_type -> server.v1.ChangeSettingsResponse + 36, // [36:46] is the sub-list for method output_type + 26, // [26:36] is the sub-list for method input_type + 26, // [26:26] is the sub-list for extension type_name + 26, // [26:26] is the sub-list for extension extendee + 0, // [0:26] is the sub-list for field type_name } func init() { file_server_v1_server_proto_init() } @@ -2022,14 +2263,14 @@ func file_server_v1_server_proto_init() { if File_server_v1_server_proto != nil { return } - file_server_v1_server_proto_msgTypes[21].OneofWrappers = []any{} + file_server_v1_server_proto_msgTypes[24].OneofWrappers = []any{} type x struct{} out := protoimpl.TypeBuilder{ File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: unsafe.Slice(unsafe.StringData(file_server_v1_server_proto_rawDesc), len(file_server_v1_server_proto_rawDesc)), NumEnums: 1, - NumMessages: 23, + NumMessages: 26, NumExtensions: 0, NumServices: 1, }, diff --git a/api/server/v1/server.pb.gw.go b/api/server/v1/server.pb.gw.go index 0ac06c5e58..d5d02fa605 100644 --- a/api/server/v1/server.pb.gw.go +++ b/api/server/v1/server.pb.gw.go @@ -219,6 +219,24 @@ func local_request_ServerService_GetSettings_0(ctx context.Context, marshaler ru return msg, metadata, err } +func request_ServerService_GetReadOnlySettings_0(ctx context.Context, marshaler runtime.Marshaler, client ServerServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var ( + protoReq GetReadOnlySettingsRequest + metadata runtime.ServerMetadata + ) + msg, err := client.GetReadOnlySettings(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) + return msg, metadata, err +} + +func local_request_ServerService_GetReadOnlySettings_0(ctx context.Context, marshaler runtime.Marshaler, server ServerServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { + var ( + protoReq GetReadOnlySettingsRequest + metadata runtime.ServerMetadata + ) + msg, err := server.GetReadOnlySettings(ctx, &protoReq) + return msg, metadata, err +} + func request_ServerService_ChangeSettings_0(ctx context.Context, marshaler runtime.Marshaler, client ServerServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { var ( protoReq ChangeSettingsRequest @@ -409,6 +427,26 @@ func RegisterServerServiceHandlerServer(ctx context.Context, mux *runtime.ServeM } forward_ServerService_GetSettings_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) }) + mux.Handle(http.MethodGet, pattern_ServerService_GetReadOnlySettings_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) + annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/server.v1.ServerService/GetReadOnlySettings", runtime.WithHTTPPathPattern("/v1/server/settings/readonly")) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := local_request_ServerService_GetReadOnlySettings_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_GetReadOnlySettings_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + }) mux.Handle(http.MethodPut, pattern_ServerService_ChangeSettings_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() @@ -605,6 +643,23 @@ func RegisterServerServiceHandlerClient(ctx context.Context, mux *runtime.ServeM } forward_ServerService_GetSettings_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) }) + mux.Handle(http.MethodGet, pattern_ServerService_GetReadOnlySettings_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) + annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/server.v1.ServerService/GetReadOnlySettings", runtime.WithHTTPPathPattern("/v1/server/settings/readonly")) + if err != nil { + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return + } + resp, md, err := request_ServerService_GetReadOnlySettings_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_GetReadOnlySettings_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) + }) mux.Handle(http.MethodPut, pattern_ServerService_ChangeSettings_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() @@ -626,25 +681,27 @@ func RegisterServerServiceHandlerClient(ctx context.Context, mux *runtime.ServeM } var ( - pattern_ServerService_Version_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v1", "server", "version"}, "")) - pattern_ServerService_Readiness_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v1", "server", "readyz"}, "")) - pattern_ServerService_LeaderHealthCheck_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v1", "server", "leaderHealthCheck"}, "")) - 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")) - pattern_ServerService_GetSettings_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v1", "server", "settings"}, "")) - pattern_ServerService_ChangeSettings_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v1", "server", "settings"}, "")) + pattern_ServerService_Version_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v1", "server", "version"}, "")) + pattern_ServerService_Readiness_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v1", "server", "readyz"}, "")) + pattern_ServerService_LeaderHealthCheck_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v1", "server", "leaderHealthCheck"}, "")) + 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")) + pattern_ServerService_GetSettings_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v1", "server", "settings"}, "")) + pattern_ServerService_GetReadOnlySettings_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"v1", "server", "settings", "readonly"}, "")) + pattern_ServerService_ChangeSettings_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v1", "server", "settings"}, "")) ) var ( - forward_ServerService_Version_0 = runtime.ForwardResponseMessage - forward_ServerService_Readiness_0 = runtime.ForwardResponseMessage - forward_ServerService_LeaderHealthCheck_0 = runtime.ForwardResponseMessage - forward_ServerService_CheckUpdates_0 = runtime.ForwardResponseMessage - forward_ServerService_ListChangeLogs_0 = runtime.ForwardResponseMessage - forward_ServerService_StartUpdate_0 = runtime.ForwardResponseMessage - forward_ServerService_UpdateStatus_0 = runtime.ForwardResponseMessage - forward_ServerService_GetSettings_0 = runtime.ForwardResponseMessage - forward_ServerService_ChangeSettings_0 = runtime.ForwardResponseMessage + forward_ServerService_Version_0 = runtime.ForwardResponseMessage + forward_ServerService_Readiness_0 = runtime.ForwardResponseMessage + forward_ServerService_LeaderHealthCheck_0 = runtime.ForwardResponseMessage + forward_ServerService_CheckUpdates_0 = runtime.ForwardResponseMessage + forward_ServerService_ListChangeLogs_0 = runtime.ForwardResponseMessage + forward_ServerService_StartUpdate_0 = runtime.ForwardResponseMessage + forward_ServerService_UpdateStatus_0 = runtime.ForwardResponseMessage + forward_ServerService_GetSettings_0 = runtime.ForwardResponseMessage + forward_ServerService_GetReadOnlySettings_0 = runtime.ForwardResponseMessage + forward_ServerService_ChangeSettings_0 = runtime.ForwardResponseMessage ) diff --git a/api/server/v1/server.pb.validate.go b/api/server/v1/server.pb.validate.go index 6f8e7a3248..e98c6f7115 100644 --- a/api/server/v1/server.pb.validate.go +++ b/api/server/v1/server.pb.validate.go @@ -2552,6 +2552,122 @@ var _ interface { ErrorName() string } = SettingsValidationError{} +// Validate checks the field values on ReadOnlySettings 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 *ReadOnlySettings) Validate() error { + return m.validate(false) +} + +// ValidateAll checks the field values on ReadOnlySettings 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 +// ReadOnlySettingsMultiError, or nil if none found. +func (m *ReadOnlySettings) ValidateAll() error { + return m.validate(true) +} + +func (m *ReadOnlySettings) validate(all bool) error { + if m == nil { + return nil + } + + var errors []error + + // no validation rules for UpdatesEnabled + + // no validation rules for TelemetryEnabled + + // no validation rules for AdvisorEnabled + + // no validation rules for AlertingEnabled + + // no validation rules for PmmPublicAddress + + // no validation rules for BackupManagementEnabled + + // no validation rules for AzurediscoverEnabled + + // no validation rules for EnableAccessControl + + if len(errors) > 0 { + return ReadOnlySettingsMultiError(errors) + } + + return nil +} + +// ReadOnlySettingsMultiError is an error wrapping multiple validation errors +// returned by ReadOnlySettings.ValidateAll() if the designated constraints +// aren't met. +type ReadOnlySettingsMultiError []error + +// Error returns a concatenation of all the error messages it wraps. +func (m ReadOnlySettingsMultiError) Error() string { + msgs := make([]string, 0, len(m)) + for _, err := range m { + msgs = append(msgs, err.Error()) + } + return strings.Join(msgs, "; ") +} + +// AllErrors returns a list of validation violation errors. +func (m ReadOnlySettingsMultiError) AllErrors() []error { return m } + +// ReadOnlySettingsValidationError is the validation error returned by +// ReadOnlySettings.Validate if the designated constraints aren't met. +type ReadOnlySettingsValidationError struct { + field string + reason string + cause error + key bool +} + +// Field function returns field value. +func (e ReadOnlySettingsValidationError) Field() string { return e.field } + +// Reason function returns reason value. +func (e ReadOnlySettingsValidationError) Reason() string { return e.reason } + +// Cause function returns cause value. +func (e ReadOnlySettingsValidationError) Cause() error { return e.cause } + +// Key function returns key value. +func (e ReadOnlySettingsValidationError) Key() bool { return e.key } + +// ErrorName returns error name. +func (e ReadOnlySettingsValidationError) ErrorName() string { return "ReadOnlySettingsValidationError" } + +// Error satisfies the builtin error interface +func (e ReadOnlySettingsValidationError) 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 %sReadOnlySettings.%s: %s%s", + key, + e.field, + e.reason, + cause) +} + +var _ error = ReadOnlySettingsValidationError{} + +var _ interface { + Field() string + Reason() string + Key() bool + Cause() error + ErrorName() string +} = ReadOnlySettingsValidationError{} + // Validate checks the field values on GetSettingsRequest 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. @@ -2654,6 +2770,108 @@ var _ interface { ErrorName() string } = GetSettingsRequestValidationError{} +// Validate checks the field values on GetReadOnlySettingsRequest 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 *GetReadOnlySettingsRequest) Validate() error { + return m.validate(false) +} + +// ValidateAll checks the field values on GetReadOnlySettingsRequest 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 +// GetReadOnlySettingsRequestMultiError, or nil if none found. +func (m *GetReadOnlySettingsRequest) ValidateAll() error { + return m.validate(true) +} + +func (m *GetReadOnlySettingsRequest) validate(all bool) error { + if m == nil { + return nil + } + + var errors []error + + if len(errors) > 0 { + return GetReadOnlySettingsRequestMultiError(errors) + } + + return nil +} + +// GetReadOnlySettingsRequestMultiError is an error wrapping multiple +// validation errors returned by GetReadOnlySettingsRequest.ValidateAll() if +// the designated constraints aren't met. +type GetReadOnlySettingsRequestMultiError []error + +// Error returns a concatenation of all the error messages it wraps. +func (m GetReadOnlySettingsRequestMultiError) Error() string { + msgs := make([]string, 0, len(m)) + for _, err := range m { + msgs = append(msgs, err.Error()) + } + return strings.Join(msgs, "; ") +} + +// AllErrors returns a list of validation violation errors. +func (m GetReadOnlySettingsRequestMultiError) AllErrors() []error { return m } + +// GetReadOnlySettingsRequestValidationError is the validation error returned +// by GetReadOnlySettingsRequest.Validate if the designated constraints aren't met. +type GetReadOnlySettingsRequestValidationError struct { + field string + reason string + cause error + key bool +} + +// Field function returns field value. +func (e GetReadOnlySettingsRequestValidationError) Field() string { return e.field } + +// Reason function returns reason value. +func (e GetReadOnlySettingsRequestValidationError) Reason() string { return e.reason } + +// Cause function returns cause value. +func (e GetReadOnlySettingsRequestValidationError) Cause() error { return e.cause } + +// Key function returns key value. +func (e GetReadOnlySettingsRequestValidationError) Key() bool { return e.key } + +// ErrorName returns error name. +func (e GetReadOnlySettingsRequestValidationError) ErrorName() string { + return "GetReadOnlySettingsRequestValidationError" +} + +// Error satisfies the builtin error interface +func (e GetReadOnlySettingsRequestValidationError) 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 %sGetReadOnlySettingsRequest.%s: %s%s", + key, + e.field, + e.reason, + cause) +} + +var _ error = GetReadOnlySettingsRequestValidationError{} + +var _ interface { + Field() string + Reason() string + Key() bool + Cause() error + ErrorName() string +} = GetReadOnlySettingsRequestValidationError{} + // Validate checks the field values on GetSettingsResponse 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. @@ -2785,6 +3003,138 @@ var _ interface { ErrorName() string } = GetSettingsResponseValidationError{} +// Validate checks the field values on GetReadOnlySettingsResponse 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 *GetReadOnlySettingsResponse) Validate() error { + return m.validate(false) +} + +// ValidateAll checks the field values on GetReadOnlySettingsResponse 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 +// GetReadOnlySettingsResponseMultiError, or nil if none found. +func (m *GetReadOnlySettingsResponse) ValidateAll() error { + return m.validate(true) +} + +func (m *GetReadOnlySettingsResponse) validate(all bool) error { + if m == nil { + return nil + } + + var errors []error + + if all { + switch v := interface{}(m.GetSettings()).(type) { + case interface{ ValidateAll() error }: + if err := v.ValidateAll(); err != nil { + errors = append(errors, GetReadOnlySettingsResponseValidationError{ + field: "Settings", + reason: "embedded message failed validation", + cause: err, + }) + } + case interface{ Validate() error }: + if err := v.Validate(); err != nil { + errors = append(errors, GetReadOnlySettingsResponseValidationError{ + field: "Settings", + reason: "embedded message failed validation", + cause: err, + }) + } + } + } else if v, ok := interface{}(m.GetSettings()).(interface{ Validate() error }); ok { + if err := v.Validate(); err != nil { + return GetReadOnlySettingsResponseValidationError{ + field: "Settings", + reason: "embedded message failed validation", + cause: err, + } + } + } + + if len(errors) > 0 { + return GetReadOnlySettingsResponseMultiError(errors) + } + + return nil +} + +// GetReadOnlySettingsResponseMultiError is an error wrapping multiple +// validation errors returned by GetReadOnlySettingsResponse.ValidateAll() if +// the designated constraints aren't met. +type GetReadOnlySettingsResponseMultiError []error + +// Error returns a concatenation of all the error messages it wraps. +func (m GetReadOnlySettingsResponseMultiError) Error() string { + msgs := make([]string, 0, len(m)) + for _, err := range m { + msgs = append(msgs, err.Error()) + } + return strings.Join(msgs, "; ") +} + +// AllErrors returns a list of validation violation errors. +func (m GetReadOnlySettingsResponseMultiError) AllErrors() []error { return m } + +// GetReadOnlySettingsResponseValidationError is the validation error returned +// by GetReadOnlySettingsResponse.Validate if the designated constraints +// aren't met. +type GetReadOnlySettingsResponseValidationError struct { + field string + reason string + cause error + key bool +} + +// Field function returns field value. +func (e GetReadOnlySettingsResponseValidationError) Field() string { return e.field } + +// Reason function returns reason value. +func (e GetReadOnlySettingsResponseValidationError) Reason() string { return e.reason } + +// Cause function returns cause value. +func (e GetReadOnlySettingsResponseValidationError) Cause() error { return e.cause } + +// Key function returns key value. +func (e GetReadOnlySettingsResponseValidationError) Key() bool { return e.key } + +// ErrorName returns error name. +func (e GetReadOnlySettingsResponseValidationError) ErrorName() string { + return "GetReadOnlySettingsResponseValidationError" +} + +// Error satisfies the builtin error interface +func (e GetReadOnlySettingsResponseValidationError) 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 %sGetReadOnlySettingsResponse.%s: %s%s", + key, + e.field, + e.reason, + cause) +} + +var _ error = GetReadOnlySettingsResponseValidationError{} + +var _ interface { + Field() string + Reason() string + Key() bool + Cause() error + ErrorName() string +} = GetReadOnlySettingsResponseValidationError{} + // Validate checks the field values on ChangeSettingsRequest 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 67882f91c3..bffdc859b5 100644 --- a/api/server/v1/server.proto +++ b/api/server/v1/server.proto @@ -181,12 +181,38 @@ message Settings { uint32 default_role_id = 18; } +// ReadOnlySettings represents a stripped-down version of PMM Server settings that can be accessed by users of all roles. +message ReadOnlySettings { + // True if updates are enabled. + bool updates_enabled = 1; + // True if telemetry is enabled. + bool telemetry_enabled = 2; + // True if Advisor is enabled. + bool advisor_enabled = 3; + // True if Alerting is enabled. + bool alerting_enabled = 4; + // PMM Server public address. + string pmm_public_address = 5; + // True if Backup Management is enabled. + bool backup_management_enabled = 6; + // True if Azure Discover is enabled. + bool azurediscover_enabled = 7; + // True if Access Control is enabled. + bool enable_access_control = 8; +} + message GetSettingsRequest {} +message GetReadOnlySettingsRequest {} + message GetSettingsResponse { Settings settings = 1; } +message GetReadOnlySettingsResponse { + ReadOnlySettings settings = 1; +} + message ChangeSettingsRequest { optional bool enable_updates = 1; optional bool enable_telemetry = 2; @@ -288,6 +314,14 @@ service ServerService { description: "Returns current PMM Server settings." }; } + // GetReadOnlySettings returns a limited number of PMM settings that is opened to authenticated users of all roles. + rpc GetReadOnlySettings(GetReadOnlySettingsRequest) returns (GetReadOnlySettingsResponse) { + option (google.api.http) = {get: "/v1/server/settings/readonly"}; + option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = { + summary: "Get read-only settings" + description: "Returns a stripped version of PMM Server settings." + }; + } // ChangeSettings changes PMM Server settings. rpc ChangeSettings(ChangeSettingsRequest) returns (ChangeSettingsResponse) { option (google.api.http) = { diff --git a/api/server/v1/server_grpc.pb.go b/api/server/v1/server_grpc.pb.go index 1e91e3cc14..a42c8016ad 100644 --- a/api/server/v1/server_grpc.pb.go +++ b/api/server/v1/server_grpc.pb.go @@ -20,15 +20,16 @@ import ( const _ = grpc.SupportPackageIsVersion9 const ( - ServerService_Version_FullMethodName = "/server.v1.ServerService/Version" - 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" - ServerService_ChangeSettings_FullMethodName = "/server.v1.ServerService/ChangeSettings" + ServerService_Version_FullMethodName = "/server.v1.ServerService/Version" + 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" + ServerService_GetReadOnlySettings_FullMethodName = "/server.v1.ServerService/GetReadOnlySettings" + ServerService_ChangeSettings_FullMethodName = "/server.v1.ServerService/ChangeSettings" ) // ServerServiceClient is the client API for ServerService service. @@ -54,6 +55,8 @@ type ServerServiceClient interface { UpdateStatus(ctx context.Context, in *UpdateStatusRequest, opts ...grpc.CallOption) (*UpdateStatusResponse, error) // GetSettings returns current PMM Server settings. GetSettings(ctx context.Context, in *GetSettingsRequest, opts ...grpc.CallOption) (*GetSettingsResponse, error) + // GetReadOnlySettings returns a limited number of PMM settings that is opened to authenticated users of all roles. + GetReadOnlySettings(ctx context.Context, in *GetReadOnlySettingsRequest, opts ...grpc.CallOption) (*GetReadOnlySettingsResponse, error) // ChangeSettings changes PMM Server settings. ChangeSettings(ctx context.Context, in *ChangeSettingsRequest, opts ...grpc.CallOption) (*ChangeSettingsResponse, error) } @@ -146,6 +149,16 @@ func (c *serverServiceClient) GetSettings(ctx context.Context, in *GetSettingsRe return out, nil } +func (c *serverServiceClient) GetReadOnlySettings(ctx context.Context, in *GetReadOnlySettingsRequest, opts ...grpc.CallOption) (*GetReadOnlySettingsResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(GetReadOnlySettingsResponse) + err := c.cc.Invoke(ctx, ServerService_GetReadOnlySettings_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + func (c *serverServiceClient) ChangeSettings(ctx context.Context, in *ChangeSettingsRequest, opts ...grpc.CallOption) (*ChangeSettingsResponse, error) { cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) out := new(ChangeSettingsResponse) @@ -179,6 +192,8 @@ type ServerServiceServer interface { UpdateStatus(context.Context, *UpdateStatusRequest) (*UpdateStatusResponse, error) // GetSettings returns current PMM Server settings. GetSettings(context.Context, *GetSettingsRequest) (*GetSettingsResponse, error) + // GetReadOnlySettings returns a limited number of PMM settings that is opened to authenticated users of all roles. + GetReadOnlySettings(context.Context, *GetReadOnlySettingsRequest) (*GetReadOnlySettingsResponse, error) // ChangeSettings changes PMM Server settings. ChangeSettings(context.Context, *ChangeSettingsRequest) (*ChangeSettingsResponse, error) mustEmbedUnimplementedServerServiceServer() @@ -223,6 +238,10 @@ func (UnimplementedServerServiceServer) GetSettings(context.Context, *GetSetting return nil, status.Errorf(codes.Unimplemented, "method GetSettings not implemented") } +func (UnimplementedServerServiceServer) GetReadOnlySettings(context.Context, *GetReadOnlySettingsRequest) (*GetReadOnlySettingsResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method GetReadOnlySettings not implemented") +} + func (UnimplementedServerServiceServer) ChangeSettings(context.Context, *ChangeSettingsRequest) (*ChangeSettingsResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method ChangeSettings not implemented") } @@ -391,6 +410,24 @@ func _ServerService_GetSettings_Handler(srv interface{}, ctx context.Context, de return interceptor(ctx, in, info, handler) } +func _ServerService_GetReadOnlySettings_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(GetReadOnlySettingsRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(ServerServiceServer).GetReadOnlySettings(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: ServerService_GetReadOnlySettings_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(ServerServiceServer).GetReadOnlySettings(ctx, req.(*GetReadOnlySettingsRequest)) + } + return interceptor(ctx, in, info, handler) +} + func _ServerService_ChangeSettings_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(ChangeSettingsRequest) if err := dec(in); err != nil { @@ -448,6 +485,10 @@ var ServerService_ServiceDesc = grpc.ServiceDesc{ MethodName: "GetSettings", Handler: _ServerService_GetSettings_Handler, }, + { + MethodName: "GetReadOnlySettings", + Handler: _ServerService_GetReadOnlySettings_Handler, + }, { MethodName: "ChangeSettings", Handler: _ServerService_ChangeSettings_Handler, diff --git a/api/swagger/swagger-dev.json b/api/swagger/swagger-dev.json index d12c969387..d3f083d7bc 100644 --- a/api/swagger/swagger-dev.json +++ b/api/swagger/swagger-dev.json @@ -27487,6 +27487,106 @@ } } }, + "/v1/server/settings/readonly": { + "get": { + "description": "Returns a stripped version of PMM Server settings.", + "tags": [ + "ServerService" + ], + "summary": "Get read-only settings", + "operationId": "GetReadOnlySettings", + "responses": { + "200": { + "description": "A successful response.", + "schema": { + "type": "object", + "properties": { + "settings": { + "description": "ReadOnlySettings represents a stripped-down version of PMM Server settings that can be accessed by users of all roles.", + "type": "object", + "properties": { + "updates_enabled": { + "description": "True if updates are enabled.", + "type": "boolean", + "x-order": 0 + }, + "telemetry_enabled": { + "description": "True if telemetry is enabled.", + "type": "boolean", + "x-order": 1 + }, + "advisor_enabled": { + "description": "True if Advisor is enabled.", + "type": "boolean", + "x-order": 2 + }, + "alerting_enabled": { + "description": "True if Alerting is enabled.", + "type": "boolean", + "x-order": 3 + }, + "pmm_public_address": { + "description": "PMM Server public address.", + "type": "string", + "x-order": 4 + }, + "backup_management_enabled": { + "description": "True if Backup Management is enabled.", + "type": "boolean", + "x-order": 5 + }, + "azurediscover_enabled": { + "description": "True if Azure Discover is enabled.", + "type": "boolean", + "x-order": 6 + }, + "enable_access_control": { + "description": "True if Access Control is enabled.", + "type": "boolean", + "x-order": 7 + } + }, + "x-order": 0 + } + } + } + }, + "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": {} + }, + "x-order": 2 + } + } + } + } + } + } + }, "/v1/server/updates": { "get": { "description": "Checks for available PMM Server updates.", diff --git a/api/swagger/swagger.json b/api/swagger/swagger.json index 8693873951..4205c9c111 100644 --- a/api/swagger/swagger.json +++ b/api/swagger/swagger.json @@ -26529,6 +26529,106 @@ } } }, + "/v1/server/settings/readonly": { + "get": { + "description": "Returns a stripped version of PMM Server settings.", + "tags": [ + "ServerService" + ], + "summary": "Get read-only settings", + "operationId": "GetReadOnlySettings", + "responses": { + "200": { + "description": "A successful response.", + "schema": { + "type": "object", + "properties": { + "settings": { + "description": "ReadOnlySettings represents a stripped-down version of PMM Server settings that can be accessed by users of all roles.", + "type": "object", + "properties": { + "updates_enabled": { + "description": "True if updates are enabled.", + "type": "boolean", + "x-order": 0 + }, + "telemetry_enabled": { + "description": "True if telemetry is enabled.", + "type": "boolean", + "x-order": 1 + }, + "advisor_enabled": { + "description": "True if Advisor is enabled.", + "type": "boolean", + "x-order": 2 + }, + "alerting_enabled": { + "description": "True if Alerting is enabled.", + "type": "boolean", + "x-order": 3 + }, + "pmm_public_address": { + "description": "PMM Server public address.", + "type": "string", + "x-order": 4 + }, + "backup_management_enabled": { + "description": "True if Backup Management is enabled.", + "type": "boolean", + "x-order": 5 + }, + "azurediscover_enabled": { + "description": "True if Azure Discover is enabled.", + "type": "boolean", + "x-order": 6 + }, + "enable_access_control": { + "description": "True if Access Control is enabled.", + "type": "boolean", + "x-order": 7 + } + }, + "x-order": 0 + } + } + } + }, + "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": {} + }, + "x-order": 2 + } + } + } + } + } + } + }, "/v1/server/updates": { "get": { "description": "Checks for available PMM Server updates.", diff --git a/managed/services/grafana/auth_server.go b/managed/services/grafana/auth_server.go index 863c6cd605..2e1b076408 100644 --- a/managed/services/grafana/auth_server.go +++ b/managed/services/grafana/auth_server.go @@ -63,6 +63,7 @@ var rules = map[string]role{ "/v1/alerting": viewer, "/v1/advisors": editor, "/v1/advisors/checks:": editor, + "/v1/advisors/failedServices": editor, "/v1/actions/": viewer, "/v1/actions:": viewer, "/v1/backups": admin, @@ -77,6 +78,7 @@ var rules = map[string]role{ "/v1/server/updates:start": admin, "/v1/server/updates:getStatus": none, // special token-based auth "/v1/server/settings": admin, + "/v1/server/settings/readonly": viewer, "/v1/platform:": admin, "/v1/platform/": viewer, "/v1/users": viewer, diff --git a/managed/services/grafana/auth_server_test.go b/managed/services/grafana/auth_server_test.go index 42aa225fac..05d72f0996 100644 --- a/managed/services/grafana/auth_server_test.go +++ b/managed/services/grafana/auth_server_test.go @@ -115,12 +115,14 @@ func TestAuthServerAuthenticate(t *testing.T) { "/v1/actions:startServiceAction": viewer, "/v1/advisors": editor, "/v1/advisors/checks:start": editor, + "/v1/advisors/failedServices": editor, "/v1/management/services": admin, "/v1/management/agents": admin, "/v1/server/updates": viewer, "/v1/server/updates:start": admin, "/v1/server/updates:getStatus": none, "/v1/server/settings": admin, + "/v1/server/settings/readonly": viewer, "/v1/server/AWSInstance": none, "/v1/backups": admin, "/v1/accesscontrol": admin, diff --git a/managed/services/server/server.go b/managed/services/server/server.go index 45985719f0..b6c1e2a635 100644 --- a/managed/services/server/server.go +++ b/managed/services/server/server.go @@ -494,6 +494,22 @@ func (s *Server) convertSettings(settings *models.Settings, connectedToPlatform return res } +// convertReadOnlySettings creates a subset of database settings for non-admin roles. +func (s *Server) convertReadOnlySettings(settings *models.Settings) *serverv1.ReadOnlySettings { + res := &serverv1.ReadOnlySettings{ + UpdatesEnabled: settings.IsUpdatesEnabled(), + TelemetryEnabled: settings.IsTelemetryEnabled(), + AdvisorEnabled: settings.IsAdvisorsEnabled(), + AlertingEnabled: settings.IsAlertingEnabled(), + PmmPublicAddress: settings.PMMPublicAddress, + BackupManagementEnabled: settings.IsBackupManagementEnabled(), + AzurediscoverEnabled: settings.IsAzureDiscoverEnabled(), + EnableAccessControl: settings.IsAccessControlEnabled(), + } + + return res +} + // GetSettings returns current PMM Server settings. func (s *Server) GetSettings(ctx context.Context, req *serverv1.GetSettingsRequest) (*serverv1.GetSettingsResponse, error) { //nolint:revive s.envRW.RLock() @@ -511,6 +527,21 @@ func (s *Server) GetSettings(ctx context.Context, req *serverv1.GetSettingsReque }, nil } +// GetReadOnlySettings returns current PMM Server settings . +func (s *Server) GetReadOnlySettings(ctx context.Context, req *serverv1.GetReadOnlySettingsRequest) (*serverv1.GetReadOnlySettingsResponse, error) { //nolint:revive + s.envRW.RLock() + defer s.envRW.RUnlock() + + settings, err := models.GetSettings(s.db) + if err != nil { + return nil, err + } + + return &serverv1.GetReadOnlySettingsResponse{ + Settings: s.convertReadOnlySettings(settings), + }, nil +} + func (s *Server) validateChangeSettingsRequest(ctx context.Context, req *serverv1.ChangeSettingsRequest) error { metricsRes := req.MetricsResolutions