diff --git a/.devcontainer/setup.py b/.devcontainer/setup.py index f57267ac07..35d0ece5b2 100755 --- a/.devcontainer/setup.py +++ b/.devcontainer/setup.py @@ -89,7 +89,7 @@ def setup(): # Having fsync off in dev environment is fine. "sed -i -e \"s/#fsync = on/fsync = off/\" /srv/postgres14/postgresql.conf", "echo 'host all all 0.0.0.0/0 trust' >> /srv/postgres14/pg_hba.conf", - "supervisorctl restart postgresql", + # "supervisorctl restart postgresql", ]) @@ -99,8 +99,7 @@ def main(): make_init() # do basic setup - # TODO: fix the setup and revert - # setup() + setup() MARKER = "/tmp/devcontainer-setup-done" diff --git a/managed/models/agent_model.go b/managed/models/agent_model.go index d77909d3a5..0233183e77 100644 --- a/managed/models/agent_model.go +++ b/managed/models/agent_model.go @@ -308,7 +308,7 @@ type DSNParams struct { PostgreSQLSupportsSSLSNI bool } -// DSN returns DSN string for accessing given Service with this Agent (and implicit driver). +// 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 host := pointer.GetString(service.Address) port := pointer.GetUint16(service.Port) @@ -516,9 +516,9 @@ func (s *Agent) DSN(service *Service, dsnParams DSNParams, tdp *DelimiterPair) s if socket == "" { address = net.JoinHostPort(host, strconv.Itoa(int(port))) } else { - // Set socket dirrectory as host URI parameter. + // Set socket directory as host URI parameter. q.Set("host", socket) - // In case of empty url.URL.Host we need to identify a start of a path (database name). + // In case of empty url.URL.Host we need to identify the start of the path (database name). database = "/" + database } @@ -563,11 +563,20 @@ func (s *Agent) ExporterURL(q *reform.Querier) (string, error) { } address := net.JoinHostPort(host, strconv.Itoa(listenPort)) + // We have to split MetricsPath into the path and the query because it may contain both. + // Example: "/metrics?format=prometheus&output=json" + p := strings.Split(path, "?") + u := &url.URL{ Scheme: scheme, Host: address, - Path: path, + Path: p[0], + } + + if len(p) > 1 { + u.RawQuery = p[1] } + switch { case password != "": u.User = url.UserPassword(username, password) diff --git a/managed/models/agent_model_test.go b/managed/models/agent_model_test.go index a328bcff88..72a5885c4d 100644 --- a/managed/models/agent_model_test.go +++ b/managed/models/agent_model_test.go @@ -401,6 +401,13 @@ func TestExporterURL(t *testing.T) { Address: "redis_exporter", }, + &models.Node{ + NodeID: "ExporterServerlessNodeID2", + NodeType: models.RemoteNodeType, + NodeName: "Node 2 for Serverless Exporter", + Address: "nomad_exporter", + }, + &models.Service{ ServiceID: "external", ServiceType: models.ExternalServiceType, @@ -417,6 +424,14 @@ func TestExporterURL(t *testing.T) { ExternalGroup: "redis", }, + &models.Service{ + ServiceID: "nomad_exporter-external", + ServiceType: models.ExternalServiceType, + ServiceName: "Service on ExporterServerlessNode 2", + NodeID: "ExporterServerlessNodeID2", + ExternalGroup: "nomad", + }, + &models.Agent{ AgentID: "ExporterAgentPush", AgentType: models.ExternalExporterType, @@ -453,6 +468,32 @@ func TestExporterURL(t *testing.T) { Username: pointer.ToString("user"), Password: pointer.ToString("secret"), }, + + &models.Agent{ + AgentID: "ExporterServerlessWithQueryParams", + AgentType: models.ExternalExporterType, + RunsOnNodeID: pointer.ToString("ExporterServerlessNodeID2"), + ServiceID: pointer.ToString("nomad_exporter-external"), + MetricsScheme: pointer.ToString("http"), + PushMetrics: false, + ListenPort: pointer.ToUint16(9121), + MetricsPath: pointer.ToString("/metrics?format=prometheus&output=json"), + Username: pointer.ToString("user"), + Password: pointer.ToString("secret"), + }, + + &models.Agent{ + AgentID: "ExporterServerlessWithEmptyMetricsPath", + AgentType: models.ExternalExporterType, + RunsOnNodeID: pointer.ToString("ExporterServerlessNodeID2"), + ServiceID: pointer.ToString("nomad_exporter-external"), + MetricsScheme: pointer.ToString("http"), + PushMetrics: false, + ListenPort: pointer.ToUint16(9121), + MetricsPath: pointer.ToString("/"), + Username: pointer.ToString("user"), + Password: pointer.ToString("secret"), + }, } { require.NoError(t, q.Insert(str), "failed to INSERT %+v", str) } @@ -469,9 +510,11 @@ func TestExporterURL(t *testing.T) { defer teardown(t) for agentID, expected := range map[string]string{ - "ExporterAgentPush": "http://127.0.0.1:9121/metrics", - "ExporterAgentPull": "http://user:secret@172.20.0.4:9121/metrics", - "ExporterServerless": "http://user:secret@redis_exporter:9121/metrics", + "ExporterAgentPush": "http://127.0.0.1:9121/metrics", + "ExporterAgentPull": "http://user:secret@172.20.0.4:9121/metrics", + "ExporterServerless": "http://user:secret@redis_exporter:9121/metrics", + "ExporterServerlessWithQueryParams": "http://user:secret@nomad_exporter:9121/metrics?format=prometheus&output=json", + "ExporterServerlessWithEmptyMetricsPath": "http://user:secret@nomad_exporter:9121/", } { t.Run(agentID, func(t *testing.T) { agent, err := models.FindAgentByID(q, agentID)