Skip to content

Commit

Permalink
PMM-13400 Nomad configuration.
Browse files Browse the repository at this point in the history
  • Loading branch information
BupycHuk committed Jan 31, 2025
1 parent 8d9df7e commit 10a464f
Show file tree
Hide file tree
Showing 4 changed files with 199 additions and 10 deletions.
2 changes: 1 addition & 1 deletion agent/agents/supervisor/supervisor.go
Original file line number Diff line number Diff line change
Expand Up @@ -696,7 +696,7 @@ func (s *Supervisor) processParams(agentID string, agentProcess *agentv1.SetStat
templateParams["tmp_dir"] = cfg.Paths.TempDir
processParams.Path = cfg.Paths.VMAgent
case inventoryv1.AgentType_AGENT_TYPE_NOMAD_AGENT:
templateParams["server_host"] = cfg.Server.URL().Host
templateParams["server_host"] = cfg.Server.URL().Hostname()
templateParams["nomad_data_dir"] = cfg.Paths.NomadDataDir
processParams.Path = cfg.Paths.Nomad
default:
Expand Down
189 changes: 188 additions & 1 deletion agent/agents/supervisor/supervisor_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -327,13 +327,15 @@ func TestSupervisorProcessParams(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background())
paths := config.Paths{
MySQLdExporter: "/path/to/mysql_exporter",
Nomad: "/path/to/nomad",
TempDir: temp,
NomadDataDir: "/path/to/nomad/data",
}

cfgStorage := config.NewStorage(&config.Config{
Paths: paths,
Ports: config.Ports{},
Server: config.Server{},
Server: config.Server{Address: "server:443", Username: "admin", Password: "admin"},
LogLinesCount: 1,
})
s := NewSupervisor(ctx, nil, cfgStorage) //nolint:varnamelen
Expand All @@ -360,6 +362,7 @@ func TestSupervisorProcessParams(t *testing.T) {
Args: []string{
"-web.listen-address=:{{ .listen_port }}",
"-web.ssl-cert-file={{ .TextFiles.Cert }}",
"-web.config={{ .TextFiles.Config }}",
},
Env: []string{
"MONGODB_URI=mongodb://username:s3cur3%20p%[email protected]:12345/?connectTimeoutMS=1000&ssl=true&sslCaFile={{.TextFiles.caFilePlaceholder}}&sslCertificateKeyFile={{.TextFiles.certificateKeyFilePlaceholder}}",
Expand All @@ -376,11 +379,13 @@ func TestSupervisorProcessParams(t *testing.T) {
actual, err := s.processParams("ID", p, 12345)
require.NoError(t, err)

configFilePath := filepath.Join(s.cfg.Get().Paths.TempDir, "agent_type_mysqld_exporter", "ID", "Config")
expected := process.Params{
Path: "/path/to/mysql_exporter",
Args: []string{
"-web.listen-address=:12345",
"-web.ssl-cert-file=" + filepath.Join(s.cfg.Get().Paths.TempDir, "agent_type_mysqld_exporter", "ID", "Cert"),
"-web.config=" + configFilePath,
},
Env: []string{
"MONGODB_URI=mongodb://username:s3cur3%20p%[email protected]:12345/?connectTimeoutMS=1000&ssl=true&" +
Expand All @@ -395,6 +400,188 @@ func TestSupervisorProcessParams(t *testing.T) {
assert.Equal(t, expected.Env, actual.Env)
assert.NotEmpty(t, actual.TemplateParams)
assert.NotEmpty(t, actual.TemplateRenderer)
require.FileExists(t, configFilePath)
b, err := os.ReadFile(configFilePath)
require.NoError(t, err)
assert.Equal(t, "test=12345", string(b))
})

t.Run("Nomad", func(t *testing.T) {
t.Parallel()
s, teardown := setup(t)
defer teardown()

configTemplate := `log_level = "DEBUG"
disable_update_check = true
data_dir = "{{.nomad_data_dir}}" # it shall be persistent
region = "global"
datacenter = "PMM Deployment"
name = "PMM Agent node-name"
ui {
enabled = false
}
addresses {
http = "127.0.0.1"
rpc = "127.0.0.1"
}
advertise {
# 127.0.0.1 is not applicable here
http = "node-address" # filled by PMM Server
rpc = "node-address" # filled by PMM Server
}
client {
enabled = true
cpu_total_compute = 1000
servers = ["{{.server_host}}:4647"] # filled by PMM Server
# disable Docker plugin
options = {
"driver.denylist" = "docker,qemu,java,exec"
"driver.allowlist" = "raw_exec"
}
# optional lables set to Nomad Client, may be the same as for PMM Agent.
meta {
pmm-agent = "1"
agent_type = "nomad-client"
node_id = "node-id"
node_name = "node-name"
}
}
server {
enabled = false
}
tls {
http = true
rpc = true
ca_file = "{{ .TextFiles.caCert }}" # filled by PMM Agent
cert_file = "{{ .TextFiles.certFile }}" # filled by PMM Agent
key_file = "{{ .TextFiles.keyFile }}" # filled by PMM Agent
verify_server_hostname = true
}
# Enabled plugins
plugin "raw_exec" {
config {
enabled = true
}
}
`

expectedConfig := `log_level = "DEBUG"
disable_update_check = true
data_dir = "/path/to/nomad/data" # it shall be persistent
region = "global"
datacenter = "PMM Deployment"
name = "PMM Agent node-name"
ui {
enabled = false
}
addresses {
http = "127.0.0.1"
rpc = "127.0.0.1"
}
advertise {
# 127.0.0.1 is not applicable here
http = "node-address" # filled by PMM Server
rpc = "node-address" # filled by PMM Server
}
client {
enabled = true
cpu_total_compute = 1000
servers = ["server:4647"] # filled by PMM Server
# disable Docker plugin
options = {
"driver.denylist" = "docker,qemu,java,exec"
"driver.allowlist" = "raw_exec"
}
# optional lables set to Nomad Client, may be the same as for PMM Agent.
meta {
pmm-agent = "1"
agent_type = "nomad-client"
node_id = "node-id"
node_name = "node-name"
}
}
server {
enabled = false
}
tls {
http = true
rpc = true
ca_file = "` + filepath.Join(s.cfg.Get().Paths.TempDir, "agent_type_nomad_agent", "ID", "caCert") + `" # filled by PMM Agent
cert_file = "` + filepath.Join(s.cfg.Get().Paths.TempDir, "agent_type_nomad_agent", "ID", "certFile") + `" # filled by PMM Agent
key_file = "` + filepath.Join(s.cfg.Get().Paths.TempDir, "agent_type_nomad_agent", "ID", "keyFile") + `" # filled by PMM Agent
verify_server_hostname = true
}
# Enabled plugins
plugin "raw_exec" {
config {
enabled = true
}
}
`

p := &agentv1.SetStateRequest_AgentProcess{
Type: inventoryv1.AgentType_AGENT_TYPE_NOMAD_AGENT,
TemplateLeftDelim: "{{",
TemplateRightDelim: "}}",
Args: []string{
"agent",
"-client",
"-config",
"{{ .TextFiles.nomadConfigPlaceholder }}",
},
TextFiles: map[string]string{
"nomadConfigPlaceholder": configTemplate,
"caCert": "-----BEGIN CERTIFICATE-----\n...",
"certFile": "---BEGIN CERTIFICATE---\n...",
"keyFile": "---BEGIN PRIVATE",
},
}
actual, err := s.processParams("ID", p, 12345)
require.NoError(t, err)

configFilePath := filepath.Join(s.cfg.Get().Paths.TempDir, "agent_type_nomad_agent", "ID", "nomadConfigPlaceholder")
expected := process.Params{
Path: "/path/to/nomad",
Args: []string{
"agent",
"-client",
"-config",
configFilePath,
},
}
assert.Equal(t, expected.Path, actual.Path)
assert.Equal(t, expected.Args, actual.Args)
assert.NotEmpty(t, actual.TemplateParams)
assert.NotEmpty(t, actual.TemplateRenderer)
require.FileExists(t, configFilePath)
b, err := os.ReadFile(configFilePath)
require.NoError(t, err)
assert.Equal(t, expectedConfig, string(b))

})

t.Run("BadTemplate", func(t *testing.T) {
Expand Down
11 changes: 8 additions & 3 deletions agent/utils/templates/template.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,12 +69,19 @@ func (tr *TemplateRenderer) RenderFiles(templateParams map[string]interface{}) (
}

textFiles := make(map[string]string, len(tr.TextFiles)) // template name => full file path
for name, text := range tr.TextFiles {

for name := range tr.TextFiles {
// avoid /, .., ., \, and other special symbols
if !textFileRE.MatchString(name) {
return nil, errors.Errorf("invalid text file name %q", name)
}

path := filepath.Join(tr.TempDir, name)
textFiles[name] = path
}
templateParams["TextFiles"] = textFiles

for name, text := range tr.TextFiles {
b, err := tr.RenderTemplate(name, text, templateParams)
if err != nil {
return nil, err
Expand All @@ -84,9 +91,7 @@ func (tr *TemplateRenderer) RenderFiles(templateParams map[string]interface{}) (
if err = os.WriteFile(path, b, 0o600); err != nil {
return nil, errors.WithStack(err)
}
textFiles[name] = path
}
templateParams["TextFiles"] = textFiles
return templateParams, nil
}

Expand Down
7 changes: 2 additions & 5 deletions managed/services/agents/nomad.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ import (
"strings"
"text/template"

"github.com/AlekSi/pointer"
"github.com/pkg/errors"

agentv1 "github.com/percona/pmm/api/agent/v1"
Expand Down Expand Up @@ -110,9 +109,7 @@ func nomadClientConfig(n nomad, node *models.Node, exporter *models.Agent) (*age
"{{ .TextFiles.nomadConfigPlaceholder }}",
}

tdp := models.TemplateDelimsPair(
append(args, pointer.GetString(exporter.MetricsPath))...,
)
tdp := models.TemplateDelimsPair()

config, err := generateNomadClientConfig(node, exporter, tdp)
if err != nil {
Expand All @@ -132,7 +129,7 @@ func nomadClientConfig(n nomad, node *models.Node, exporter *models.Agent) (*age
return nil, errors.Wrap(err, "Failed to read client key")
}
params := &agentv1.SetStateRequest_AgentProcess{
Type: inventoryv1.AgentType_AGENT_TYPE_NODE_EXPORTER,
Type: inventoryv1.AgentType_AGENT_TYPE_NOMAD_AGENT,
TemplateLeftDelim: tdp.Left,
TemplateRightDelim: tdp.Right,
Args: args,
Expand Down

0 comments on commit 10a464f

Please sign in to comment.