From 74e57527735bd062c4bd37adbd89c31bb14ebc15 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ji=C5=99=C3=AD=20=C4=8Ctvrtka?= <62988319+JiriCtvrtka@users.noreply.github.com> Date: Wed, 5 Jun 2024 18:15:14 +0200 Subject: [PATCH] PMM-13145 Certs Fix - Backward compatibility for older clients. (#3014) (#3017) * PMM-13145 Fix for older clients. * PMM-13145 Small changes. * PMM-13145 Lint. * PMM-13145 Lint. * PMM-13145 Logic fix. * PMM-13145 Refactor. * PMM-13145 Fix after refactor. * Update managed/models/agent_model.go * Update managed/models/agent_model.go --------- Co-authored-by: Nurlan Moldomurov --- managed/models/agent_helpers.go | 18 ++++++++ managed/models/agent_model.go | 12 +++++- managed/models/agent_model_test.go | 42 +++++++++---------- managed/models/dsn_helpers.go | 3 +- managed/services/agents/connection_checker.go | 13 +++--- managed/services/agents/mongodb.go | 6 +-- managed/services/agents/mysql.go | 10 ++--- managed/services/agents/postgresql.go | 6 +-- managed/services/agents/proxysql.go | 2 +- .../services/agents/service_info_broker.go | 13 +++--- managed/services/agents/state.go | 6 +-- 11 files changed, 83 insertions(+), 48 deletions(-) diff --git a/managed/models/agent_helpers.go b/managed/models/agent_helpers.go index d509bdf435..68fd243bec 100644 --- a/managed/models/agent_helpers.go +++ b/managed/models/agent_helpers.go @@ -524,6 +524,24 @@ func FindPmmAgentIDToRunActionOrJob(pmmAgentID string, agents []*Agent) (string, return "", status.Errorf(codes.FailedPrecondition, "Couldn't find pmm-agent-id to run action") } +// ExtractPmmAgentVersionFromAgent extract PMM agent version from Agent by pmm-agent-id. +func ExtractPmmAgentVersionFromAgent(q *reform.Querier, agent *Agent) *version.Parsed { + pmmAgentID, err := ExtractPmmAgentID(agent) + if err != nil { + return nil + } + pmmAgent, err := FindAgentByID(q, pmmAgentID) + if err != nil { + return nil + } + version, err := version.Parse(pointer.GetString(pmmAgent.Version)) + if err != nil { + return nil + } + + return version +} + // ExtractPmmAgentID extract pmm-agent-id from Agent by type. func ExtractPmmAgentID(agent *Agent) (string, error) { switch agent.AgentType { diff --git a/managed/models/agent_model.go b/managed/models/agent_model.go index bd7014b303..ab838e423f 100644 --- a/managed/models/agent_model.go +++ b/managed/models/agent_model.go @@ -73,6 +73,8 @@ const ( VMAgentType AgentType = "vmagent" ) +var v2_42 = version.MustParse("2.42.0-0") + // PMMServerAgentID is a special Agent ID representing pmm-agent on PMM Server. const PMMServerAgentID = string("pmm-server") // no /agent_id/ prefix @@ -313,7 +315,7 @@ type DSNParams struct { } // DSN returns a DSN string for accessing a given Service with this Agent (and an implicit driver). -func (s *Agent) DSN(service *Service, dsnParams DSNParams, tdp *DelimiterPair) string { //nolint:cyclop,maintidx +func (s *Agent) DSN(service *Service, dsnParams DSNParams, tdp *DelimiterPair, pmmAgentVersion *version.Parsed) string { //nolint:cyclop,maintidx host := pointer.GetString(service.Address) port := pointer.GetUint16(service.Port) socket := pointer.GetString(service.Socket) @@ -340,8 +342,12 @@ func (s *Agent) DSN(service *Service, dsnParams DSNParams, tdp *DelimiterPair) s cfg.Params = make(map[string]string) if s.TLS { // It is mandatory to have "custom" as the first case. + // Except case for backward compatibility. // Skip verify for "custom" is handled on pmm-agent side. switch { + // Backward compatibility + case s.TLSSkipVerify && (pmmAgentVersion == nil || pmmAgentVersion.Less(v2_42)): + cfg.Params["tls"] = skipVerify case len(s.Files()) != 0: cfg.Params["tls"] = "custom" case s.TLSSkipVerify: @@ -371,8 +377,12 @@ func (s *Agent) DSN(service *Service, dsnParams DSNParams, tdp *DelimiterPair) s cfg.Params = make(map[string]string) if s.TLS { // It is mandatory to have "custom" as the first case. + // Except case for backward compatibility. // Skip verify for "custom" is handled on pmm-agent side. switch { + // Backward compatibility + case pmmAgentVersion != nil && s.TLSSkipVerify && pmmAgentVersion.Less(v2_42): + cfg.Params["tls"] = skipVerify case len(s.Files()) != 0: cfg.Params["tls"] = "custom" case s.TLSSkipVerify: diff --git a/managed/models/agent_model_test.go b/managed/models/agent_model_test.go index a8a09de5ad..a17b44f26c 100644 --- a/managed/models/agent_model_test.go +++ b/managed/models/agent_model_test.go @@ -66,15 +66,15 @@ func TestAgent(t *testing.T) { } { t.Run(string(typ), func(t *testing.T) { agent.AgentType = typ - assert.Equal(t, expected, agent.DSN(service, models.DSNParams{DialTimeout: time.Second, Database: "database"}, nil)) + assert.Equal(t, expected, agent.DSN(service, models.DSNParams{DialTimeout: time.Second, Database: "database"}, nil, nil)) }) } t.Run("MongoDBNoDatabase", func(t *testing.T) { agent.AgentType = models.MongoDBExporterType - assert.Equal(t, "mongodb://username:s3cur3%20p%40$$w0r4.@1.2.3.4:12345/?connectTimeoutMS=1000&directConnection=true&serverSelectionTimeoutMS=1000", agent.DSN(service, models.DSNParams{DialTimeout: time.Second}, nil)) - assert.Equal(t, "mongodb://username:s3cur3%20p%40$$w0r4.@1.2.3.4:12345/?directConnection=true", agent.DSN(service, models.DSNParams{}, nil)) + assert.Equal(t, "mongodb://username:s3cur3%20p%40$$w0r4.@1.2.3.4:12345/?connectTimeoutMS=1000&directConnection=true&serverSelectionTimeoutMS=1000", agent.DSN(service, models.DSNParams{DialTimeout: time.Second}, nil, nil)) + assert.Equal(t, "mongodb://username:s3cur3%20p%40$$w0r4.@1.2.3.4:12345/?directConnection=true", agent.DSN(service, models.DSNParams{}, nil, nil)) }) }) @@ -94,7 +94,7 @@ func TestAgent(t *testing.T) { } { t.Run(string(typ), func(t *testing.T) { agent.AgentType = typ - assert.Equal(t, expected, agent.DSN(service, models.DSNParams{DialTimeout: time.Second, Database: "database"}, nil)) + assert.Equal(t, expected, agent.DSN(service, models.DSNParams{DialTimeout: time.Second, Database: "database"}, nil, nil)) }) } }) @@ -113,7 +113,7 @@ func TestAgent(t *testing.T) { } { t.Run(string(typ), func(t *testing.T) { agent.AgentType = typ - assert.Equal(t, expected, agent.DSN(service, models.DSNParams{DialTimeout: time.Second, Database: "database"}, nil)) + assert.Equal(t, expected, agent.DSN(service, models.DSNParams{DialTimeout: time.Second, Database: "database"}, nil, nil)) }) } }) @@ -159,7 +159,7 @@ func TestAgent(t *testing.T) { } { t.Run(string(typ), func(t *testing.T) { agent.AgentType = typ - assert.Equal(t, expected, agent.DSN(service, models.DSNParams{DialTimeout: time.Second, Database: "database"}, nil)) + assert.Equal(t, expected, agent.DSN(service, models.DSNParams{DialTimeout: time.Second, Database: "database"}, nil, nil)) }) } @@ -169,8 +169,8 @@ func TestAgent(t *testing.T) { agent.MongoDBOptions.TLSCertificateKeyFilePassword = "" agent.MongoDBOptions.AuthenticationMechanism = "" - assert.Equal(t, "mongodb://username:s3cur3%20p%40$$w0r4.@1.2.3.4:12345/?connectTimeoutMS=1000&directConnection=true&serverSelectionTimeoutMS=1000&ssl=true&tlsCaFile={{.TextFiles.caFilePlaceholder}}&tlsCertificateKeyFile={{.TextFiles.certificateKeyFilePlaceholder}}", agent.DSN(service, models.DSNParams{DialTimeout: time.Second}, nil)) - assert.Equal(t, "mongodb://username:s3cur3%20p%40$$w0r4.@1.2.3.4:12345/?directConnection=true&ssl=true&tlsCaFile={{.TextFiles.caFilePlaceholder}}&tlsCertificateKeyFile={{.TextFiles.certificateKeyFilePlaceholder}}", agent.DSN(service, models.DSNParams{}, nil)) + assert.Equal(t, "mongodb://username:s3cur3%20p%40$$w0r4.@1.2.3.4:12345/?connectTimeoutMS=1000&directConnection=true&serverSelectionTimeoutMS=1000&ssl=true&tlsCaFile={{.TextFiles.caFilePlaceholder}}&tlsCertificateKeyFile={{.TextFiles.certificateKeyFilePlaceholder}}", agent.DSN(service, models.DSNParams{DialTimeout: time.Second}, nil, nil)) + assert.Equal(t, "mongodb://username:s3cur3%20p%40$$w0r4.@1.2.3.4:12345/?directConnection=true&ssl=true&tlsCaFile={{.TextFiles.caFilePlaceholder}}&tlsCertificateKeyFile={{.TextFiles.certificateKeyFilePlaceholder}}", agent.DSN(service, models.DSNParams{}, nil, nil)) expectedFiles := map[string]string{ "caFilePlaceholder": "cert", "certificateKeyFilePlaceholder": "key", @@ -185,8 +185,8 @@ func TestAgent(t *testing.T) { agent.MongoDBOptions.AuthenticationMechanism = "MONGO-X509" agent.MongoDBOptions.AuthenticationDatabase = "$external" - assert.Equal(t, "mongodb://username:s3cur3%20p%40$$w0r4.@1.2.3.4:12345/?authMechanism=MONGO-X509&authSource=%24external&connectTimeoutMS=1000&directConnection=true&serverSelectionTimeoutMS=1000&ssl=true&tlsCaFile={{.TextFiles.caFilePlaceholder}}&tlsCertificateKeyFile={{.TextFiles.certificateKeyFilePlaceholder}}", agent.DSN(service, models.DSNParams{DialTimeout: time.Second}, nil)) - assert.Equal(t, "mongodb://username:s3cur3%20p%40$$w0r4.@1.2.3.4:12345/?authMechanism=MONGO-X509&authSource=%24external&directConnection=true&ssl=true&tlsCaFile={{.TextFiles.caFilePlaceholder}}&tlsCertificateKeyFile={{.TextFiles.certificateKeyFilePlaceholder}}", agent.DSN(service, models.DSNParams{}, nil)) + assert.Equal(t, "mongodb://username:s3cur3%20p%40$$w0r4.@1.2.3.4:12345/?authMechanism=MONGO-X509&authSource=%24external&connectTimeoutMS=1000&directConnection=true&serverSelectionTimeoutMS=1000&ssl=true&tlsCaFile={{.TextFiles.caFilePlaceholder}}&tlsCertificateKeyFile={{.TextFiles.certificateKeyFilePlaceholder}}", agent.DSN(service, models.DSNParams{DialTimeout: time.Second}, nil, nil)) + assert.Equal(t, "mongodb://username:s3cur3%20p%40$$w0r4.@1.2.3.4:12345/?authMechanism=MONGO-X509&authSource=%24external&directConnection=true&ssl=true&tlsCaFile={{.TextFiles.caFilePlaceholder}}&tlsCertificateKeyFile={{.TextFiles.certificateKeyFilePlaceholder}}", agent.DSN(service, models.DSNParams{}, nil, nil)) expectedFiles := map[string]string{ "caFilePlaceholder": "cert", "certificateKeyFilePlaceholder": "key", @@ -217,15 +217,15 @@ func TestAgent(t *testing.T) { } { t.Run(string(typ), func(t *testing.T) { agent.AgentType = typ - assert.Equal(t, expected, agent.DSN(service, models.DSNParams{DialTimeout: time.Second, Database: "database"}, nil)) + assert.Equal(t, expected, agent.DSN(service, models.DSNParams{DialTimeout: time.Second, Database: "database"}, nil, nil)) }) } t.Run("MongoDBNoDatabase", func(t *testing.T) { agent.AgentType = models.MongoDBExporterType - assert.Equal(t, "mongodb://username:s3cur3%20p%40$$w0r4.@1.2.3.4:12345/?connectTimeoutMS=1000&directConnection=true&serverSelectionTimeoutMS=1000&ssl=true&tlsInsecure=true", agent.DSN(service, models.DSNParams{DialTimeout: time.Second}, nil)) - assert.Equal(t, "mongodb://username:s3cur3%20p%40$$w0r4.@1.2.3.4:12345/?directConnection=true&ssl=true&tlsInsecure=true", agent.DSN(service, models.DSNParams{}, nil)) + assert.Equal(t, "mongodb://username:s3cur3%20p%40$$w0r4.@1.2.3.4:12345/?connectTimeoutMS=1000&directConnection=true&serverSelectionTimeoutMS=1000&ssl=true&tlsInsecure=true", agent.DSN(service, models.DSNParams{DialTimeout: time.Second}, nil, nil)) + assert.Equal(t, "mongodb://username:s3cur3%20p%40$$w0r4.@1.2.3.4:12345/?directConnection=true&ssl=true&tlsInsecure=true", agent.DSN(service, models.DSNParams{}, nil, nil)) }) }) } @@ -255,13 +255,13 @@ func TestPostgresAgentTLS(t *testing.T) { t.Run(name, func(t *testing.T) { agent.TLS = testCase.tls agent.TLSSkipVerify = testCase.tlsSkipVerify - assert.Equal(t, testCase.expected, agent.DSN(service, models.DSNParams{DialTimeout: time.Second, Database: "database"}, nil)) + assert.Equal(t, testCase.expected, agent.DSN(service, models.DSNParams{DialTimeout: time.Second, Database: "database"}, nil, nil)) }) t.Run(fmt.Sprintf("AutodiscoveryLimit set TLS:%v/TLSSkipVerify:%v", testCase.tls, testCase.tlsSkipVerify), func(t *testing.T) { agent.TLS = testCase.tls agent.TLSSkipVerify = testCase.tlsSkipVerify agent.PostgreSQLOptions = &models.PostgreSQLOptions{AutoDiscoveryLimit: 10} - assert.Equal(t, testCase.expected, agent.DSN(service, models.DSNParams{DialTimeout: time.Second, Database: "database"}, nil)) + assert.Equal(t, testCase.expected, agent.DSN(service, models.DSNParams{DialTimeout: time.Second, Database: "database"}, nil, nil)) }) } } @@ -278,7 +278,7 @@ func TestPostgresWithSocket(t *testing.T) { Socket: pointer.ToString("/var/run/postgres"), } expect := "postgres://username@/database?connect_timeout=1&host=%2Fvar%2Frun%2Fpostgres&sslmode=verify-ca" - assert.Equal(t, expect, agent.DSN(service, models.DSNParams{DialTimeout: time.Second, Database: "database"}, nil)) + assert.Equal(t, expect, agent.DSN(service, models.DSNParams{DialTimeout: time.Second, Database: "database"}, nil, nil)) }) t.Run("empty-user-password", func(t *testing.T) { @@ -289,7 +289,7 @@ func TestPostgresWithSocket(t *testing.T) { Socket: pointer.ToString("/var/run/postgres"), } expect := "postgres:///database?connect_timeout=1&host=%2Fvar%2Frun%2Fpostgres&sslmode=disable" - assert.Equal(t, expect, agent.DSN(service, models.DSNParams{DialTimeout: time.Second, Database: "database"}, nil)) + assert.Equal(t, expect, agent.DSN(service, models.DSNParams{DialTimeout: time.Second, Database: "database"}, nil, nil)) }) t.Run("dir-with-symbols", func(t *testing.T) { @@ -300,7 +300,7 @@ func TestPostgresWithSocket(t *testing.T) { Socket: pointer.ToString(`/tmp/123\ A0m\%\$\@\8\,\+\-`), } expect := "postgres:///database?connect_timeout=1&host=%2Ftmp%2F123%5C+A0m%5C%25%5C%24%5C%40%5C8%5C%2C%5C%2B%5C-&sslmode=disable" - assert.Equal(t, expect, agent.DSN(service, models.DSNParams{DialTimeout: time.Second, Database: "database"}, nil)) + assert.Equal(t, expect, agent.DSN(service, models.DSNParams{DialTimeout: time.Second, Database: "database"}, nil, nil)) }) } @@ -316,7 +316,7 @@ func TestMongoWithSocket(t *testing.T) { Socket: pointer.ToString("/tmp/mongodb-27017.sock"), } expect := "mongodb://username@%2Ftmp%2Fmongodb-27017.sock/database?connectTimeoutMS=1000&directConnection=true&serverSelectionTimeoutMS=1000&ssl=true" - assert.Equal(t, expect, agent.DSN(service, models.DSNParams{DialTimeout: time.Second, Database: "database"}, nil)) + assert.Equal(t, expect, agent.DSN(service, models.DSNParams{DialTimeout: time.Second, Database: "database"}, nil, nil)) }) t.Run("empty-user-password", func(t *testing.T) { @@ -327,7 +327,7 @@ func TestMongoWithSocket(t *testing.T) { Socket: pointer.ToString("/tmp/mongodb-27017.sock"), } expect := "mongodb://%2Ftmp%2Fmongodb-27017.sock/database?connectTimeoutMS=1000&directConnection=true&serverSelectionTimeoutMS=1000" - assert.Equal(t, expect, agent.DSN(service, models.DSNParams{DialTimeout: time.Second, Database: "database"}, nil)) + assert.Equal(t, expect, agent.DSN(service, models.DSNParams{DialTimeout: time.Second, Database: "database"}, nil, nil)) }) t.Run("dir-with-symbols", func(t *testing.T) { @@ -338,7 +338,7 @@ func TestMongoWithSocket(t *testing.T) { Socket: pointer.ToString(`/tmp/123\ A0m\%\$\@\8\,\+\-/mongodb-27017.sock`), } expect := "mongodb://%2Ftmp%2F123%5C%20A0m%5C%25%5C$%5C%40%5C8%5C,%5C+%5C-%2Fmongodb-27017.sock/database?connectTimeoutMS=1000&directConnection=true&serverSelectionTimeoutMS=1000" - assert.Equal(t, expect, agent.DSN(service, models.DSNParams{DialTimeout: time.Second, Database: "database"}, nil)) + assert.Equal(t, expect, agent.DSN(service, models.DSNParams{DialTimeout: time.Second, Database: "database"}, nil, nil)) }) } diff --git a/managed/models/dsn_helpers.go b/managed/models/dsn_helpers.go index d4d6112262..a8d47399d0 100644 --- a/managed/models/dsn_helpers.go +++ b/managed/models/dsn_helpers.go @@ -86,7 +86,8 @@ func FindDSNByServiceIDandPMMAgentID(q *reform.Querier, serviceID, pmmAgentID, d } if len(fexp) == 1 { agent := fexp[0] - return agent.DSN(svc, dsnParams, nil), agent, nil + pmmAgentVersion := ExtractPmmAgentVersionFromAgent(q, agent) + return agent.DSN(svc, dsnParams, nil, pmmAgentVersion), agent, nil } if len(fexp) > 1 { return "", nil, status.Errorf(codes.FailedPrecondition, "Couldn't resolve dsn, as there should be only one agent") diff --git a/managed/services/agents/connection_checker.go b/managed/services/agents/connection_checker.go index 9f695d8a8a..402ad52d18 100644 --- a/managed/services/agents/connection_checker.go +++ b/managed/services/agents/connection_checker.go @@ -137,12 +137,14 @@ func (c *ConnectionChecker) CheckConnectionToService(ctx context.Context, q *ref func connectionRequest(q *reform.Querier, service *models.Service, agent *models.Agent) (*agentpb.CheckConnectionRequest, error) { var request *agentpb.CheckConnectionRequest + + pmmAgentVersion := models.ExtractPmmAgentVersionFromAgent(q, agent) switch service.ServiceType { case models.MySQLServiceType: tdp := agent.TemplateDelimiters(service) request = &agentpb.CheckConnectionRequest{ Type: inventorypb.ServiceType_MYSQL_SERVICE, - Dsn: agent.DSN(service, models.DSNParams{DialTimeout: 2 * time.Second, Database: service.DatabaseName}, nil), + Dsn: agent.DSN(service, models.DSNParams{DialTimeout: 2 * time.Second, Database: service.DatabaseName}, nil, pmmAgentVersion), Timeout: durationpb.New(3 * time.Second), TextFiles: &agentpb.TextFiles{ Files: agent.Files(), @@ -158,8 +160,9 @@ func connectionRequest(q *reform.Querier, service *models.Service, agent *models return nil, err } request = &agentpb.CheckConnectionRequest{ - Type: inventorypb.ServiceType_POSTGRESQL_SERVICE, - Dsn: agent.DSN(service, models.DSNParams{DialTimeout: 2 * time.Second, Database: service.DatabaseName, PostgreSQLSupportsSSLSNI: sqlSniSupported}, nil), + Type: inventorypb.ServiceType_POSTGRESQL_SERVICE, + Dsn: agent.DSN(service, models.DSNParams{DialTimeout: 2 * time.Second, Database: service.DatabaseName, PostgreSQLSupportsSSLSNI: sqlSniSupported}, + nil, pmmAgentVersion), Timeout: durationpb.New(3 * time.Second), TextFiles: &agentpb.TextFiles{ Files: agent.Files(), @@ -171,7 +174,7 @@ func connectionRequest(q *reform.Querier, service *models.Service, agent *models tdp := agent.TemplateDelimiters(service) request = &agentpb.CheckConnectionRequest{ Type: inventorypb.ServiceType_MONGODB_SERVICE, - Dsn: agent.DSN(service, models.DSNParams{DialTimeout: 2 * time.Second, Database: service.DatabaseName}, nil), + Dsn: agent.DSN(service, models.DSNParams{DialTimeout: 2 * time.Second, Database: service.DatabaseName}, nil, pmmAgentVersion), Timeout: durationpb.New(3 * time.Second), TextFiles: &agentpb.TextFiles{ Files: agent.Files(), @@ -182,7 +185,7 @@ func connectionRequest(q *reform.Querier, service *models.Service, agent *models case models.ProxySQLServiceType: request = &agentpb.CheckConnectionRequest{ Type: inventorypb.ServiceType_PROXYSQL_SERVICE, - Dsn: agent.DSN(service, models.DSNParams{DialTimeout: 2 * time.Second, Database: service.DatabaseName}, nil), + Dsn: agent.DSN(service, models.DSNParams{DialTimeout: 2 * time.Second, Database: service.DatabaseName}, nil, pmmAgentVersion), Timeout: durationpb.New(3 * time.Second), } case models.ExternalServiceType: diff --git a/managed/services/agents/mongodb.go b/managed/services/agents/mongodb.go index 3ff1983593..0e043e3904 100644 --- a/managed/services/agents/mongodb.go +++ b/managed/services/agents/mongodb.go @@ -78,7 +78,7 @@ func mongodbExporterConfig(node *models.Node, service *models.Service, exporter database = exporter.MongoDBOptions.AuthenticationDatabase } env := []string{ - fmt.Sprintf("MONGODB_URI=%s", exporter.DSN(service, models.DSNParams{DialTimeout: time.Second, Database: database}, tdp)), + fmt.Sprintf("MONGODB_URI=%s", exporter.DSN(service, models.DSNParams{DialTimeout: time.Second, Database: database}, tdp, pmmAgentVersion)), } res := &agentpb.SetStateRequest_AgentProcess{ @@ -270,11 +270,11 @@ func defaultCollectors(collectAll bool) map[string]collectorArgs { } // qanMongoDBProfilerAgentConfig returns desired configuration of qan-mongodb-profiler-agent built-in agent. -func qanMongoDBProfilerAgentConfig(service *models.Service, agent *models.Agent) *agentpb.SetStateRequest_BuiltinAgent { +func qanMongoDBProfilerAgentConfig(service *models.Service, agent *models.Agent, pmmAgentVersion *version.Parsed) *agentpb.SetStateRequest_BuiltinAgent { tdp := agent.TemplateDelimiters(service) return &agentpb.SetStateRequest_BuiltinAgent{ Type: inventorypb.AgentType_QAN_MONGODB_PROFILER_AGENT, - Dsn: agent.DSN(service, models.DSNParams{DialTimeout: time.Second, Database: ""}, nil), + Dsn: agent.DSN(service, models.DSNParams{DialTimeout: time.Second, Database: ""}, nil, pmmAgentVersion), DisableQueryExamples: agent.QueryExamplesDisabled, MaxQueryLength: agent.MaxQueryLength, TextFiles: &agentpb.TextFiles{ diff --git a/managed/services/agents/mysql.go b/managed/services/agents/mysql.go index a7d9487ff2..e3e1c377e6 100644 --- a/managed/services/agents/mysql.go +++ b/managed/services/agents/mysql.go @@ -141,7 +141,7 @@ func mysqldExporterConfig( TemplateRightDelim: tdp.Right, Args: args, Env: []string{ - fmt.Sprintf("DATA_SOURCE_NAME=%s", exporter.DSN(service, models.DSNParams{DialTimeout: time.Second, Database: ""}, nil)), + fmt.Sprintf("DATA_SOURCE_NAME=%s", exporter.DSN(service, models.DSNParams{DialTimeout: time.Second, Database: ""}, nil, pmmAgentVersion)), fmt.Sprintf("HTTP_AUTH=pmm:%s", exporter.GetAgentPassword()), }, TextFiles: exporter.Files(), @@ -153,11 +153,11 @@ func mysqldExporterConfig( } // qanMySQLPerfSchemaAgentConfig returns desired configuration of qan-mysql-perfschema built-in agent. -func qanMySQLPerfSchemaAgentConfig(service *models.Service, agent *models.Agent) *agentpb.SetStateRequest_BuiltinAgent { +func qanMySQLPerfSchemaAgentConfig(service *models.Service, agent *models.Agent, pmmAgentVersion *version.Parsed) *agentpb.SetStateRequest_BuiltinAgent { tdp := agent.TemplateDelimiters(service) return &agentpb.SetStateRequest_BuiltinAgent{ Type: inventorypb.AgentType_QAN_MYSQL_PERFSCHEMA_AGENT, - Dsn: agent.DSN(service, models.DSNParams{DialTimeout: time.Second, Database: ""}, nil), + Dsn: agent.DSN(service, models.DSNParams{DialTimeout: time.Second, Database: ""}, nil, pmmAgentVersion), MaxQueryLength: agent.MaxQueryLength, DisableQueryExamples: agent.QueryExamplesDisabled, DisableCommentsParsing: agent.CommentsParsingDisabled, @@ -171,11 +171,11 @@ func qanMySQLPerfSchemaAgentConfig(service *models.Service, agent *models.Agent) } // qanMySQLSlowlogAgentConfig returns desired configuration of qan-mysql-slowlog built-in agent. -func qanMySQLSlowlogAgentConfig(service *models.Service, agent *models.Agent) *agentpb.SetStateRequest_BuiltinAgent { +func qanMySQLSlowlogAgentConfig(service *models.Service, agent *models.Agent, pmmAgentVersion *version.Parsed) *agentpb.SetStateRequest_BuiltinAgent { tdp := agent.TemplateDelimiters(service) return &agentpb.SetStateRequest_BuiltinAgent{ Type: inventorypb.AgentType_QAN_MYSQL_SLOWLOG_AGENT, - Dsn: agent.DSN(service, models.DSNParams{DialTimeout: time.Second, Database: ""}, nil), + Dsn: agent.DSN(service, models.DSNParams{DialTimeout: time.Second, Database: ""}, nil, pmmAgentVersion), MaxQueryLength: agent.MaxQueryLength, DisableQueryExamples: agent.QueryExamplesDisabled, DisableCommentsParsing: agent.CommentsParsingDisabled, diff --git a/managed/services/agents/postgresql.go b/managed/services/agents/postgresql.go index 33523d830e..73575eafed 100644 --- a/managed/services/agents/postgresql.go +++ b/managed/services/agents/postgresql.go @@ -121,7 +121,7 @@ func postgresExporterConfig(node *models.Node, service *models.Service, exporter TemplateRightDelim: tdp.Right, Args: args, Env: []string{ - fmt.Sprintf("DATA_SOURCE_NAME=%s", exporter.DSN(service, dnsParams, nil)), + fmt.Sprintf("DATA_SOURCE_NAME=%s", exporter.DSN(service, dnsParams, nil, pmmAgentVersion)), }, TextFiles: exporter.Files(), } @@ -147,7 +147,7 @@ func qanPostgreSQLPgStatementsAgentConfig(service *models.Service, agent *models } return &agentpb.SetStateRequest_BuiltinAgent{ Type: inventorypb.AgentType_QAN_POSTGRESQL_PGSTATEMENTS_AGENT, - Dsn: agent.DSN(service, dnsParams, nil), + Dsn: agent.DSN(service, dnsParams, nil, pmmAgentVersion), MaxQueryLength: agent.MaxQueryLength, DisableCommentsParsing: agent.CommentsParsingDisabled, TextFiles: &agentpb.TextFiles{ @@ -168,7 +168,7 @@ func qanPostgreSQLPgStatMonitorAgentConfig(service *models.Service, agent *model } return &agentpb.SetStateRequest_BuiltinAgent{ Type: inventorypb.AgentType_QAN_POSTGRESQL_PGSTATMONITOR_AGENT, - Dsn: agent.DSN(service, dnsParams, nil), + Dsn: agent.DSN(service, dnsParams, nil, pmmAgentVersion), DisableQueryExamples: agent.QueryExamplesDisabled, MaxQueryLength: agent.MaxQueryLength, DisableCommentsParsing: agent.CommentsParsingDisabled, diff --git a/managed/services/agents/proxysql.go b/managed/services/agents/proxysql.go index 383a27c0c6..9d66bbb906 100644 --- a/managed/services/agents/proxysql.go +++ b/managed/services/agents/proxysql.go @@ -73,7 +73,7 @@ func proxysqlExporterConfig(node *models.Node, service *models.Service, exporter TemplateRightDelim: tdp.Right, Args: args, Env: []string{ - fmt.Sprintf("DATA_SOURCE_NAME=%s", exporter.DSN(service, models.DSNParams{DialTimeout: time.Second, Database: ""}, nil)), + fmt.Sprintf("DATA_SOURCE_NAME=%s", exporter.DSN(service, models.DSNParams{DialTimeout: time.Second, Database: ""}, nil, pmmAgentVersion)), fmt.Sprintf("HTTP_AUTH=pmm:%s", exporter.GetAgentPassword()), }, } diff --git a/managed/services/agents/service_info_broker.go b/managed/services/agents/service_info_broker.go index 6f0041656a..890a647109 100644 --- a/managed/services/agents/service_info_broker.go +++ b/managed/services/agents/service_info_broker.go @@ -52,12 +52,14 @@ func NewServiceInfoBroker(r *Registry) *ServiceInfoBroker { // ServiceInfoRequest creates a ServiceInfoRequest for a given service. func serviceInfoRequest(q *reform.Querier, service *models.Service, agent *models.Agent) (*agentpb.ServiceInfoRequest, error) { var request *agentpb.ServiceInfoRequest + + pmmAgentVersion := models.ExtractPmmAgentVersionFromAgent(q, agent) switch service.ServiceType { case models.MySQLServiceType: tdp := agent.TemplateDelimiters(service) request = &agentpb.ServiceInfoRequest{ Type: inventorypb.ServiceType_MYSQL_SERVICE, - Dsn: agent.DSN(service, models.DSNParams{DialTimeout: time.Second, Database: service.DatabaseName}, nil), + Dsn: agent.DSN(service, models.DSNParams{DialTimeout: time.Second, Database: service.DatabaseName}, nil, pmmAgentVersion), Timeout: durationpb.New(3 * time.Second), TextFiles: &agentpb.TextFiles{ Files: agent.Files(), @@ -73,8 +75,9 @@ func serviceInfoRequest(q *reform.Querier, service *models.Service, agent *model return nil, err } request = &agentpb.ServiceInfoRequest{ - Type: inventorypb.ServiceType_POSTGRESQL_SERVICE, - Dsn: agent.DSN(service, models.DSNParams{DialTimeout: time.Second, Database: service.DatabaseName, PostgreSQLSupportsSSLSNI: sqlSniSupported}, nil), + Type: inventorypb.ServiceType_POSTGRESQL_SERVICE, + Dsn: agent.DSN(service, models.DSNParams{DialTimeout: time.Second, Database: service.DatabaseName, PostgreSQLSupportsSSLSNI: sqlSniSupported}, + nil, pmmAgentVersion), Timeout: durationpb.New(3 * time.Second), TextFiles: &agentpb.TextFiles{ Files: agent.Files(), @@ -86,7 +89,7 @@ func serviceInfoRequest(q *reform.Querier, service *models.Service, agent *model tdp := agent.TemplateDelimiters(service) request = &agentpb.ServiceInfoRequest{ Type: inventorypb.ServiceType_MONGODB_SERVICE, - Dsn: agent.DSN(service, models.DSNParams{DialTimeout: time.Second, Database: service.DatabaseName}, nil), + Dsn: agent.DSN(service, models.DSNParams{DialTimeout: time.Second, Database: service.DatabaseName}, nil, pmmAgentVersion), Timeout: durationpb.New(3 * time.Second), TextFiles: &agentpb.TextFiles{ Files: agent.Files(), @@ -97,7 +100,7 @@ func serviceInfoRequest(q *reform.Querier, service *models.Service, agent *model case models.ProxySQLServiceType: request = &agentpb.ServiceInfoRequest{ Type: inventorypb.ServiceType_PROXYSQL_SERVICE, - Dsn: agent.DSN(service, models.DSNParams{DialTimeout: time.Second, Database: service.DatabaseName}, nil), + Dsn: agent.DSN(service, models.DSNParams{DialTimeout: time.Second, Database: service.DatabaseName}, nil, pmmAgentVersion), Timeout: durationpb.New(3 * time.Second), } case models.ExternalServiceType: diff --git a/managed/services/agents/state.go b/managed/services/agents/state.go index ed0c4e0ecd..0e55f14a97 100644 --- a/managed/services/agents/state.go +++ b/managed/services/agents/state.go @@ -245,11 +245,11 @@ func (u *StateUpdater) sendSetStateRequest(ctx context.Context, agent *pmmAgentI case models.ProxySQLExporterType: agentProcesses[row.AgentID] = proxysqlExporterConfig(node, service, row, redactMode, pmmAgentVersion) case models.QANMySQLPerfSchemaAgentType: - builtinAgents[row.AgentID] = qanMySQLPerfSchemaAgentConfig(service, row) + builtinAgents[row.AgentID] = qanMySQLPerfSchemaAgentConfig(service, row, pmmAgentVersion) case models.QANMySQLSlowlogAgentType: - builtinAgents[row.AgentID] = qanMySQLSlowlogAgentConfig(service, row) + builtinAgents[row.AgentID] = qanMySQLSlowlogAgentConfig(service, row, pmmAgentVersion) case models.QANMongoDBProfilerAgentType: - builtinAgents[row.AgentID] = qanMongoDBProfilerAgentConfig(service, row) + builtinAgents[row.AgentID] = qanMongoDBProfilerAgentConfig(service, row, pmmAgentVersion) case models.QANPostgreSQLPgStatementsAgentType: builtinAgents[row.AgentID] = qanPostgreSQLPgStatementsAgentConfig(service, row, pmmAgentVersion) case models.QANPostgreSQLPgStatMonitorAgentType: