diff --git a/agent/client/channel/channel.go b/agent/client/channel/channel.go index 0630eb8985..d59b5324c6 100644 --- a/agent/client/channel/channel.go +++ b/agent/client/channel/channel.go @@ -47,7 +47,7 @@ type ServerRequest struct { } // AgentResponse represents agent's response. -// It is similar to agentpb.AgentMessage except it can contain only responses, +// It is similar to agentv1.AgentMessage except it can contain only responses, // and the payload is already unwrapped (XXX instead of AgentMessage_XXX). type AgentResponse struct { ID uint32 diff --git a/managed/services/agents/agents.go b/managed/services/agents/agents.go index 451b34f09b..ea5ea813ad 100644 --- a/managed/services/agents/agents.go +++ b/managed/services/agents/agents.go @@ -141,7 +141,9 @@ func pathsBase(agentVersion *version.Parsed, tdpLeft, tdpRight string) string { } // ensureAuthParams updates agent start parameters to contain prometheus webconfig. -func ensureAuthParams(exporter *models.Agent, params *agentv1.SetStateRequest_AgentProcess, agentVersion *version.Parsed, minAuthVersion *version.Parsed) error { +func ensureAuthParams(exporter *models.Agent, params *agentv1.SetStateRequest_AgentProcess, + agentVersion *version.Parsed, minAuthVersion *version.Parsed, useNewTLSConfig bool, +) error { if agentVersion.Less(minAuthVersion) { params.Env = append(params.Env, fmt.Sprintf("HTTP_AUTH=pmm:%s", exporter.GetAgentPassword())) } else { @@ -155,7 +157,11 @@ func ensureAuthParams(exporter *models.Agent, params *agentv1.SetStateRequest_Ag } params.TextFiles["webConfigPlaceholder"] = wcf // see https://github.com/prometheus/exporter-toolkit/tree/v0.1.0/https - params.Args = append(params.Args, "--web.config="+params.TemplateLeftDelim+" .TextFiles.webConfigPlaceholder "+params.TemplateRightDelim) + if useNewTLSConfig { + params.Args = append(params.Args, "--web.config.file="+params.TemplateLeftDelim+" .TextFiles.webConfigPlaceholder "+params.TemplateRightDelim) + } else { + params.Args = append(params.Args, "--web.config="+params.TemplateLeftDelim+" .TextFiles.webConfigPlaceholder "+params.TemplateRightDelim) + } } return nil diff --git a/managed/services/agents/mongodb.go b/managed/services/agents/mongodb.go index def2887e31..a61d6af06d 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 res.RedactWords = redactWords(exporter) } - if err := ensureAuthParams(exporter, res, pmmAgentVersion, v2_27_99); err != nil { + if err := ensureAuthParams(exporter, res, pmmAgentVersion, v2_28_00, false); err != nil { return nil, err } diff --git a/managed/services/agents/node.go b/managed/services/agents/node.go index 4dd5ad113c..4aac0b2422 100644 --- a/managed/services/agents/node.go +++ b/managed/services/agents/node.go @@ -30,7 +30,9 @@ import ( // The node exporter prior 2.28 use exporter_shared and gets basic auth config from env. // Starting with pmm 2.28, the exporter uses Prometheus Web Toolkit and needs a config file // with the basic auth users. -var v2_27_99 = version.MustParse("2.27.99") +var ( + v2_28_00 = version.MustParse("2.28.0-0") +) func nodeExporterConfig(node *models.Node, exporter *models.Agent, agentVersion *version.Parsed) (*agentv1.SetStateRequest_AgentProcess, error) { listenAddress := getExporterListenAddress(node, exporter) @@ -142,7 +144,7 @@ func nodeExporterConfig(node *models.Node, exporter *models.Agent, agentVersion Args: args, } - if err := ensureAuthParams(exporter, params, agentVersion, v2_27_99); err != nil { + if err := ensureAuthParams(exporter, params, agentVersion, v2_28_00, agentVersion.IsFeatureSupported(version.NodeExporterNewTLSConfigVersion)); err != nil { return nil, err } diff --git a/managed/services/agents/node_test.go b/managed/services/agents/node_test.go index d3fc5dc381..01bbdaf279 100644 --- a/managed/services/agents/node_test.go +++ b/managed/services/agents/node_test.go @@ -75,6 +75,32 @@ func TestAuthWebConfig(t *testing.T) { require.Equal(t, expected.Env, actual.Env) require.Equal(t, expected.TextFiles, actual.TextFiles) + require.Contains(t, actual.Args, "--web.config={{ .TextFiles.webConfigPlaceholder }}") + }) + + t.Run("v3.0.0", func(t *testing.T) { + t.Parallel() + + node := &models.Node{} + exporter := &models.Agent{ + AgentID: "agent-id", + AgentType: models.NodeExporterType, + } + agentVersion := version.MustParse("3.0.0") + + actual, err := nodeExporterConfig(node, exporter, agentVersion) + require.NoError(t, err, "Unable to build node exporter config") + + expected := &agentv1.SetStateRequest_AgentProcess{ + Env: []string(nil), + TextFiles: map[string]string{ + "webConfigPlaceholder": "basic_auth_users:\n pmm: agent-id\n", + }, + } + + require.Equal(t, expected.Env, actual.Env) + require.Equal(t, expected.TextFiles, actual.TextFiles) + require.Contains(t, actual.Args, "--web.config.file={{ .TextFiles.webConfigPlaceholder }}") }) } diff --git a/managed/services/agents/postgresql.go b/managed/services/agents/postgresql.go index 44223fa4c1..4160d2552f 100644 --- a/managed/services/agents/postgresql.go +++ b/managed/services/agents/postgresql.go @@ -150,7 +150,7 @@ func postgresExporterConfig(node *models.Node, service *models.Service, exporter res.RedactWords = redactWords(exporter) } - if err := ensureAuthParams(exporter, res, pmmAgentVersion, postgresExporterWebConfigVersion); err != nil { + if err := ensureAuthParams(exporter, res, pmmAgentVersion, postgresExporterWebConfigVersion, false); err != nil { return nil, err } diff --git a/version/features.go b/version/features.go new file mode 100644 index 0000000000..02630cb7de --- /dev/null +++ b/version/features.go @@ -0,0 +1,34 @@ +// Copyright (C) 2023 Percona LLC +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +package version + +// Versions list. +var ( + V3_0_0 = MustParse("3.0.0") //nolint:revive,stylecheck +) + +// FeatureVersion represents a minimum version feature being supported. +type FeatureVersion *Parsed + +// Features list. +var ( + NodeExporterNewTLSConfigVersion FeatureVersion = V3_0_0 +) + +// IsFeatureSupported checks if the feature is supported by the version. +func (p *Parsed) IsFeatureSupported(f FeatureVersion) bool { + return !p.Less(f) +}