From cd7c983a754eb62e8d431dabd846d21e2707f453 Mon Sep 17 00:00:00 2001 From: Nurlan Moldomurov Date: Thu, 14 Nov 2024 12:19:30 +0300 Subject: [PATCH 1/2] PMM-13543 Support socket path. PMM-13477 Support of PSMDB 8.0. --- exporter/diagnostic_data_collector.go | 2 +- main.go | 28 ++++++++++++++---- main_test.go | 42 +++++++++++++++++++++++++++ 3 files changed, 66 insertions(+), 6 deletions(-) diff --git a/exporter/diagnostic_data_collector.go b/exporter/diagnostic_data_collector.go index 57b4b7e96..409a76faf 100644 --- a/exporter/diagnostic_data_collector.go +++ b/exporter/diagnostic_data_collector.go @@ -117,7 +117,7 @@ func (d *diagnosticDataCollector) collect(ch chan<- prometheus.Metric) { debugResult(logger, m) // MongoDB 8.0 splits the diagnostic data into multiple blocks, so we need to merge them - if d.buildInfo.VersionArray[0] >= 8 { //nolint:gomnd + if _, ok := m["common"]; ok { //nolint:gomnd,mng b := bson.M{} for _, mv := range m { block, ok := mv.(bson.M) diff --git a/main.go b/main.go index 937b610a3..1ed816906 100644 --- a/main.go +++ b/main.go @@ -268,18 +268,36 @@ func parseURIList(uriList []string, logger *logrus.Logger, splitCluster bool) [] return URIs } +// buildURIManually builds the URI manually by checking if the user and password are supplied +func buildURIManually(uri string, user string, password string) string { + uriArray := strings.SplitN(uri, "://", 2) + prefix := uriArray[0] + "://" + uri = uriArray[1] + + // IF user@pass not contained in uri AND custom user and pass supplied in arguments + // DO concat a new uri with user and pass arguments value + if !strings.Contains(uri, "@") && user != "" && password != "" { + // add user and pass to the uri + uri = fmt.Sprintf("%s:%s@%s", user, password, uri) + } + + // add back prefix after adding the user and pass + uri = prefix + uri + + return uri +} + func buildURI(uri string, user string, password string, log *logrus.Logger) string { defaultPrefix := "mongodb://" // default prefix - matchRegexp := regexp.MustCompile(`^mongodb(\+srv)?://`) - // Split the uri defaultPrefix if there is any - if !matchRegexp.MatchString(uri) { + if !strings.HasPrefix(uri, defaultPrefix) && !strings.HasPrefix(uri, "mongodb+srv://") { uri = defaultPrefix + uri } parsedURI, err := url.Parse(uri) if err != nil { - log.Fatalf("Failed to parse URI %s: %v", uri, err) - return uri + // PMM generates URI with escaped path to socket file, so url.Parse fails + // in this case we build URI manually + return buildURIManually(uri, user, password) } if parsedURI.User == nil && user != "" && password != "" { diff --git a/main_test.go b/main_test.go index 49d077c9b..c1e0c9fa2 100644 --- a/main_test.go +++ b/main_test.go @@ -227,6 +227,48 @@ func TestBuildURI(t *testing.T) { newPassword: "yyy?!#$%^&*()_+", expect: "mongodb://xxx%3F%21%23$%25%5E&%2A%28%29_+:yyy%3F%21%23$%25%5E&%2A%28%29_+@127.0.0.1", }, + { + situation: "path to socket", + origin: "mongodb:///tmp/mongodb-27017.sock", + newUser: "", + newPassword: "", + expect: "mongodb:///tmp/mongodb-27017.sock", + }, + { + situation: "path to socket with params", + origin: "mongodb://username:s3cur3%20p%40$$w0r4.@%2Fvar%2Frun%2Fmongodb%2Fmongodb.sock/database?connectTimeoutMS=1000&directConnection=true&serverSelectionTimeoutMS=1000", + newUser: "", + newPassword: "", + expect: "mongodb://username:s3cur3%20p%40$$w0r4.@%2Fvar%2Frun%2Fmongodb%2Fmongodb.sock/database?connectTimeoutMS=1000&directConnection=true&serverSelectionTimeoutMS=1000", + }, + { + situation: "path to socket with auth", + origin: "mongodb://xxx:yyy@/tmp/mongodb-27017.sock", + newUser: "", + newPassword: "", + expect: "mongodb://xxx:yyy@/tmp/mongodb-27017.sock", + }, + { + situation: "path to socket with auth and user params", + origin: "mongodb:///tmp/mongodb-27017.sock", + newUser: "xxx", + newPassword: "yyy", + expect: "mongodb://xxx:yyy@/tmp/mongodb-27017.sock", + }, + { + situation: "path to socket without prefix", + origin: "/tmp/mongodb-27017.sock", + newUser: "", + newPassword: "", + expect: "mongodb:///tmp/mongodb-27017.sock", + }, + { + situation: "path to socket without prefix with auth", + origin: "/tmp/mongodb-27017.sock", + newUser: "xxx", + newPassword: "yyy", + expect: "mongodb://xxx:yyy@/tmp/mongodb-27017.sock", + }, } for _, tc := range tests { t.Run(tc.situation, func(t *testing.T) { From 9a5af4875f9190d48b704b20764ed4598f2b1dec Mon Sep 17 00:00:00 2001 From: Nurlan Moldomurov Date: Thu, 14 Nov 2024 13:52:09 +0300 Subject: [PATCH 2/2] Apply suggestions from code review Co-authored-by: Alex Demidoff --- exporter/diagnostic_data_collector.go | 2 +- main.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/exporter/diagnostic_data_collector.go b/exporter/diagnostic_data_collector.go index 409a76faf..e4b19fe00 100644 --- a/exporter/diagnostic_data_collector.go +++ b/exporter/diagnostic_data_collector.go @@ -117,7 +117,7 @@ func (d *diagnosticDataCollector) collect(ch chan<- prometheus.Metric) { debugResult(logger, m) // MongoDB 8.0 splits the diagnostic data into multiple blocks, so we need to merge them - if _, ok := m["common"]; ok { //nolint:gomnd,mng + if _, ok := m["common"]; ok { b := bson.M{} for _, mv := range m { block, ok := mv.(bson.M) diff --git a/main.go b/main.go index 1ed816906..a894588d7 100644 --- a/main.go +++ b/main.go @@ -270,7 +270,7 @@ func parseURIList(uriList []string, logger *logrus.Logger, splitCluster bool) [] // buildURIManually builds the URI manually by checking if the user and password are supplied func buildURIManually(uri string, user string, password string) string { - uriArray := strings.SplitN(uri, "://", 2) + uriArray := strings.SplitN(uri, "://", 2) //nolint:mnd prefix := uriArray[0] + "://" uri = uriArray[1]