Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
122 changes: 122 additions & 0 deletions admin/commands/inventory/add_agent_rta_mysql.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
// Copyright (C) 2023 Percona LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package inventory

import (
"time"

"github.com/percona/pmm/admin/commands"
"github.com/percona/pmm/admin/pkg/flags"
"github.com/percona/pmm/api/inventory/v1/json/client"
agents "github.com/percona/pmm/api/inventory/v1/json/client/agents_service"
)

var addAgentRTAMySQLAgentResultT = commands.ParseTemplate(`
Real-Time Analytics MySQL agent added.
Agent ID : {{ .Agent.AgentID }}
PMM-Agent ID : {{ .Agent.PMMAgentID }}
Service ID : {{ .Agent.ServiceID }}
Username : {{ .Agent.Username }}
TLS enabled : {{ .Agent.TLS }}
Skip TLS verification : {{ .Agent.TLSSkipVerify }}

Disabled : {{ .Agent.Disabled }}
Custom labels : {{ formatCustomLabels .Agent.CustomLabels }}
Collect interval : {{ .Agent.RtaOptions.CollectInterval }}
Log level : {{ formatLogLevel .Agent.LogLevel }}
`)

type addAgentRTAMySQLAgentResult struct {
Agent *agents.AddAgentOKBodyRtaMysqlAgent `json:"rta_mysql_agent"`
}

func (res *addAgentRTAMySQLAgentResult) Result() {}

func (res *addAgentRTAMySQLAgentResult) String() string {
return commands.RenderTemplate(addAgentRTAMySQLAgentResultT, res)
}

// AddAgentRTAMySQLAgentCommand is used by Kong for CLI flags and commands.
type AddAgentRTAMySQLAgentCommand struct {
PMMAgentID string `arg:"" help:"The pmm-agent identifier which runs this instance"`
ServiceID string `arg:"" help:"Service identifier"`
Username string `arg:"" optional:"" help:"MySQL username for getting queries data"`
Password string `help:"MySQL password for getting queries data"`
CustomLabels map[string]string `mapsep:"," help:"Custom user-assigned labels"`
SkipConnectionCheck bool `help:"Skip connection check"`
TLS bool `help:"Use TLS to connect to the database"`
TLSSkipVerify bool `help:"Skip TLS certificate verification"`
TLSCaFile string `help:"Path to certificate authority file"`
TLSCertFile string `help:"Path to client certificate file"`
TLSKeyFile string `help:"Path to client key file"`
CollectInterval *time.Duration `placeholder:"DURATION" help:"Query collect interval (default: server-defined 2s)"`

flags.LogLevelFatalFlags
}

// RunCmd executes the AddAgentRTAMySQLAgentCommand and returns the result.
func (cmd *AddAgentRTAMySQLAgentCommand) RunCmd() (commands.Result, error) {
customLabels := commands.ParseKeyValuePair(&cmd.CustomLabels)

tlsCa, err := commands.ReadFile(cmd.TLSCaFile)
if err != nil {
return nil, err
}

tlsCert, err := commands.ReadFile(cmd.TLSCertFile)
if err != nil {
return nil, err
}

tlsKey, err := commands.ReadFile(cmd.TLSKeyFile)
if err != nil {
return nil, err
}

params := &agents.AddAgentParams{
Body: agents.AddAgentBody{
RtaMysqlAgent: &agents.AddAgentParamsBodyRtaMysqlAgent{
PMMAgentID: cmd.PMMAgentID,
ServiceID: cmd.ServiceID,
Username: cmd.Username,
Password: cmd.Password,
CustomLabels: *customLabels,
SkipConnectionCheck: cmd.SkipConnectionCheck,
TLS: cmd.TLS,
TLSSkipVerify: cmd.TLSSkipVerify,
TLSCa: tlsCa,
TLSCert: tlsCert,
TLSKey: tlsKey,
LogLevel: cmd.LogLevel.EnumValue(),
},
},
Context: commands.Ctx,
}

if cmd.CollectInterval != nil {
params.Body.RtaMysqlAgent.RtaOptions = &agents.AddAgentParamsBodyRtaMysqlAgentRtaOptions{
CollectInterval: cmd.CollectInterval.String(),
}
}

resp, err := client.Default.AgentsService.AddAgent(params)
if err != nil {
return nil, err
}

return &addAgentRTAMySQLAgentResult{
Agent: resp.Payload.RtaMysqlAgent,
}, nil
}
218 changes: 218 additions & 0 deletions admin/commands/inventory/change_agent_rta_mysql.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,218 @@
// Copyright (C) 2023 Percona LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package inventory

import (
"fmt"
"time"

"github.com/percona/pmm/admin/commands"
"github.com/percona/pmm/admin/pkg/flags"
"github.com/percona/pmm/api/inventory/v1/json/client"
agents "github.com/percona/pmm/api/inventory/v1/json/client/agents_service"
)

var changeAgentRTAMySQLAgentResultT = commands.ParseTemplate(`
Real-Time Analytics MySQL agent configuration updated.
Agent ID : {{ .Agent.AgentID }}
PMM-Agent ID : {{ .Agent.PMMAgentID }}
Service ID : {{ .Agent.ServiceID }}
Username : {{ .Agent.Username }}
TLS enabled : {{ .Agent.TLS }}
Skip TLS verification : {{ .Agent.TLSSkipVerify }}

Disabled : {{ .Agent.Disabled }}
Custom labels : {{ formatCustomLabels .Agent.CustomLabels }}
Collect interval : {{ .Agent.RtaOptions.CollectInterval }}
Log level : {{ formatLogLevel .Agent.LogLevel }}

{{- if .Changes}}
Configuration changes applied:
{{- range .Changes}}
- {{ . }}
{{- end}}
{{- end}}
`)

type changeAgentRTAMySQLAgentResult struct {
Agent *agents.ChangeAgentOKBodyRtaMysqlAgent `json:"rta_mysql_agent"`
Changes []string `json:"changes,omitempty"`
}

func (res *changeAgentRTAMySQLAgentResult) Result() {}

func (res *changeAgentRTAMySQLAgentResult) String() string {
return commands.RenderTemplate(changeAgentRTAMySQLAgentResultT, res)
}

// ChangeAgentRTAMySQLAgentCommand is used by Kong for CLI flags and commands.
type ChangeAgentRTAMySQLAgentCommand struct {
// Embedded flags
flags.LogLevelFatalChangeFlags

AgentID string `arg:"" help:"Real-Time Analytics MySQL Agent ID"`

// NOTE: Only provided flags will be changed, others will remain unchanged

// Basic options
Enable *bool `help:"Enable or disable the agent"`
Username *string `help:"MySQL username for getting queries data"`
Password *string `help:"MySQL password for getting queries data"`

// TLS options
TLS *bool `help:"Use TLS to connect to the database"`
TLSSkipVerify *bool `help:"Skip TLS certificate verification"`
TLSCaFile *string `help:"Path to certificate authority file"`
TLSCertFile *string `help:"Path to client certificate file"`
TLSKeyFile *string `help:"Path to client key file"`

// RTA specific options
CollectInterval *time.Duration `placeholder:"DURATION" help:"Query collect interval (default: server-defined 2s)"`

// Custom labels
CustomLabels *map[string]string `mapsep:"," help:"Custom user-assigned labels"`
}

// RunCmd executes the ChangeAgentRTAMySQLAgentCommand and returns the result.
func (cmd *ChangeAgentRTAMySQLAgentCommand) RunCmd() (commands.Result, error) {
var changes []string

// Parse custom labels if provided
customLabels := commands.ParseKeyValuePair(cmd.CustomLabels)

// Read TLS files if provided
var tlsCa, tlsCert, tlsKey *string

if cmd.TLSCaFile != nil {
content, err := commands.ReadFile(*cmd.TLSCaFile)
if err != nil {
return nil, fmt.Errorf("failed to read TLS CA file: %w", err)
}

tlsCa = &content
}

if cmd.TLSCertFile != nil {
content, err := commands.ReadFile(*cmd.TLSCertFile)
if err != nil {
return nil, fmt.Errorf("failed to read TLS certificate file: %w", err)
}

tlsCert = &content
}

if cmd.TLSKeyFile != nil {
content, err := commands.ReadFile(*cmd.TLSKeyFile)
if err != nil {
return nil, fmt.Errorf("failed to read TLS key file: %w", err)
}

tlsKey = &content
}

body := &agents.ChangeAgentParamsBodyRtaMysqlAgent{
Enable: cmd.Enable,
Username: cmd.Username,
Password: cmd.Password,
TLS: cmd.TLS,
TLSSkipVerify: cmd.TLSSkipVerify,
TLSCa: tlsCa,
TLSCert: tlsCert,
TLSKey: tlsKey,
LogLevel: convertLogLevelPtr(cmd.LogLevel),
}

if customLabels != nil {
body.CustomLabels = &agents.ChangeAgentParamsBodyRtaMysqlAgentCustomLabels{
Values: *customLabels,
}
}

if cmd.CollectInterval != nil {
body.RtaOptions = &agents.ChangeAgentParamsBodyRtaMysqlAgentRtaOptions{
CollectInterval: cmd.CollectInterval.String(),
}
}

params := &agents.ChangeAgentParams{
AgentID: cmd.AgentID,
Body: agents.ChangeAgentBody{
RtaMysqlAgent: body,
},
Context: commands.Ctx,
}

resp, err := client.Default.AgentsService.ChangeAgent(params)
if err != nil {
return nil, err
}

// Track changes
if cmd.Enable != nil {
if *cmd.Enable {
changes = append(changes, "enabled agent")
} else {
changes = append(changes, "disabled agent")
}
}
if cmd.Username != nil {
changes = append(changes, "updated username")
}
if cmd.Password != nil {
changes = append(changes, "updated password")
}
if cmd.TLS != nil {
if *cmd.TLS {
changes = append(changes, "enabled TLS")
} else {
changes = append(changes, "disabled TLS")
}
}
if cmd.TLSSkipVerify != nil {
if *cmd.TLSSkipVerify {
changes = append(changes, "enabled TLS skip verification")
} else {
changes = append(changes, "disabled TLS skip verification")
}
}
if cmd.TLSCaFile != nil {
changes = append(changes, "updated TLS CA certificate")
}
if cmd.TLSCertFile != nil {
changes = append(changes, "updated TLS certificate")
}
if cmd.TLSKeyFile != nil {
changes = append(changes, "updated TLS key")
}
if cmd.LogLevel != nil {
changes = append(changes, fmt.Sprintf("changed log level to %s", *cmd.LogLevel))
}
if customLabels != nil {
if len(*customLabels) != 0 {
changes = append(changes, "updated custom labels")
} else {
changes = append(changes, "custom labels are removed")
}
}

if cmd.CollectInterval != nil {
changes = append(changes, fmt.Sprintf("changed collect interval to %s", *cmd.CollectInterval))
}

return &changeAgentRTAMySQLAgentResult{
Agent: resp.Payload.RtaMysqlAgent,
Changes: changes,
}, nil
}
2 changes: 2 additions & 0 deletions admin/commands/inventory/inventory.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ type AddAgentCommand struct {

RDSExporter AddAgentRDSExporterCommand `cmd:"" help:"Add rds_exporter to inventory"`
RTAMongoDBAgent AddAgentRTAMongoDBAgentCommand `cmd:"" name:"rta-mongodb-agent" help:"Add Real-Time Analytics MongoDB agent to inventory"`
RTAMySQLAgent AddAgentRTAMySQLAgentCommand `cmd:"" name:"rta-mysql-agent" help:"Add Real-Time Analytics MySQL agent to inventory"`
}

// AddNodeCommand is used by Kong for CLI flags and commands.
Expand Down Expand Up @@ -119,6 +120,7 @@ type ChangeAgentCommand struct {
QANPostgreSQLPgStatementsAgent ChangeAgentQANPostgreSQLPgStatementsAgentCommand `cmd:"" name:"qan-postgresql-pgstatements-agent" help:"Change QAN PostgreSQL pgstatements agent configuration (only passed flags will be changed)"`
QANPostgreSQLPgStatMonitorAgent ChangeAgentQANPostgreSQLPgStatMonitorAgentCommand `cmd:"" name:"qan-postgresql-pgstatmonitor-agent" help:"Change QAN PostgreSQL pgstatmonitor agent configuration (only passed flags will be changed)"`
RTAMongoDBAgent ChangeAgentRTAMongoDBAgentCommand `cmd:"" name:"rta-mongodb-agent" help:"Change Real-Time Analytics MongoDB agent configuration (only passed flags will be changed)"`
RTAMySQLAgent ChangeAgentRTAMySQLAgentCommand `cmd:"" name:"rta-mysql-agent" help:"Change Real-Time Analytics MySQL agent configuration (only passed flags will be changed)"`
}

// formatTypeValue checks acceptable type value and variations contains input and returns type value.
Expand Down
14 changes: 13 additions & 1 deletion admin/commands/inventory/list_agents.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ var acceptableAgentTypes = map[string][]string{
types.AgentTypeQANPostgreSQLPgStatMonitorAgent: {types.AgentTypeName(types.AgentTypeQANPostgreSQLPgStatMonitorAgent), "qan-postgresql-pgstatmonitor-agent"},
types.AgentTypeRDSExporter: {types.AgentTypeName(types.AgentTypeRDSExporter), "rds-exporter"},
types.AgentTypeRTAMongoDBAgent: {types.AgentTypeName(types.AgentTypeRTAMongoDBAgent), "rta-mongodb-agent"},
types.AgentTypeRTAMySQLAgent: {types.AgentTypeName(types.AgentTypeRTAMySQLAgent), "rta-mysql-agent"},
}

type listResultAgent struct {
Expand Down Expand Up @@ -141,7 +142,8 @@ func (cmd *ListAgentsCommand) RunCmd() (commands.Result, error) {
len(agentsRes.Payload.QANPostgresqlPgstatementsAgent)+
len(agentsRes.Payload.QANPostgresqlPgstatmonitorAgent)+
len(agentsRes.Payload.ExternalExporter)+
len(agentsRes.Payload.RtaMongodbAgent),
len(agentsRes.Payload.RtaMongodbAgent)+
len(agentsRes.Payload.RtaMysqlAgent),
)
for _, a := range agentsRes.Payload.PMMAgent {
status := "disconnected"
Expand Down Expand Up @@ -309,6 +311,16 @@ func (cmd *ListAgentsCommand) RunCmd() (commands.Result, error) {
Disabled: a.Disabled,
})
}
for _, a := range agentsRes.Payload.RtaMysqlAgent {
agentsList = append(agentsList, listResultAgent{
AgentType: types.AgentTypeRTAMySQLAgent,
AgentID: a.AgentID,
PMMAgentID: a.PMMAgentID,
ServiceID: a.ServiceID,
Status: getAgentStatus(a.Status),
Disabled: a.Disabled,
})
}

return &listAgentsResult{
Agents: agentsList,
Expand Down
Loading
Loading