Skip to content

Commit

Permalink
cluster: clean operations cannot cleanup monitor component files (#1643)
Browse files Browse the repository at this point in the history
  • Loading branch information
srstack authored Nov 30, 2021
1 parent 2dba6d7 commit 0349e97
Show file tree
Hide file tree
Showing 2 changed files with 170 additions and 45 deletions.
24 changes: 24 additions & 0 deletions pkg/cluster/manager/basic.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import (
"github.com/pingcap/tiup/pkg/cluster/task"
"github.com/pingcap/tiup/pkg/logger/log"
"github.com/pingcap/tiup/pkg/meta"
"github.com/pingcap/tiup/pkg/set"
"github.com/pingcap/tiup/pkg/tui"
)

Expand Down Expand Up @@ -238,3 +239,26 @@ func (m *Manager) RestartCluster(name string, gOpt operator.Options, skipConfirm
log.Infof("Restarted cluster `%s` successfully", name)
return nil
}

// getMonitorHosts get the instance to ignore list if it marks itself as ignore_exporter
func getMonitorHosts(topo spec.Topology) (map[string]hostInfo, set.StringSet) {
// monitor
uniqueHosts := make(map[string]hostInfo) // host -> ssh-port, os, arch
noAgentHosts := set.NewStringSet()
topo.IterInstance(func(inst spec.Instance) {
// add the instance to ignore list if it marks itself as ignore_exporter
if inst.IgnoreMonitorAgent() {
noAgentHosts.Insert(inst.GetHost())
}

if _, found := uniqueHosts[inst.GetHost()]; !found {
uniqueHosts[inst.GetHost()] = hostInfo{
ssh: inst.GetSSHPort(),
os: inst.OS(),
arch: inst.Arch(),
}
}
})

return uniqueHosts, noAgentHosts
}
191 changes: 146 additions & 45 deletions pkg/cluster/manager/cleanup.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import (
"context"
"fmt"
"path"
"path/filepath"
"strings"

"github.com/fatih/color"
Expand Down Expand Up @@ -56,51 +57,8 @@ func (m *Manager) CleanCluster(name string, gOpt operator.Options, cleanOpt oper
}

// calculate file paths to be deleted before the prompt
delFileMap := make(map[string]set.StringSet)
for _, com := range topo.ComponentsByStopOrder() {
instances := com.Instances()
retainDataRoles := set.NewStringSet(cleanOpt.RetainDataRoles...)
retainDataNodes := set.NewStringSet(cleanOpt.RetainDataNodes...)

for _, ins := range instances {
// not cleaning files of monitor agents if the instance does not have one
switch ins.ComponentName() {
case spec.ComponentNodeExporter,
spec.ComponentBlackboxExporter:
if ins.IgnoreMonitorAgent() {
continue
}
}

// Some data of instances will be retained
dataRetained := retainDataRoles.Exist(ins.ComponentName()) ||
retainDataNodes.Exist(ins.ID()) || retainDataNodes.Exist(ins.GetHost())

if dataRetained {
continue
}

dataPaths := set.NewStringSet()
logPaths := set.NewStringSet()

if cleanOpt.CleanupData && len(ins.DataDir()) > 0 {
for _, dataDir := range strings.Split(ins.DataDir(), ",") {
dataPaths.Insert(path.Join(dataDir, "*"))
}
}

if cleanOpt.CleanupLog && len(ins.LogDir()) > 0 {
for _, logDir := range strings.Split(ins.LogDir(), ",") {
logPaths.Insert(path.Join(logDir, "*.log"))
}
}

if delFileMap[ins.GetHost()] == nil {
delFileMap[ins.GetHost()] = set.NewStringSet()
}
delFileMap[ins.GetHost()].Join(logPaths).Join(dataPaths)
}
}
delFileMap := getCleanupFiles(topo,
cleanOpt.CleanupData, cleanOpt.CleanupLog, false, cleanOpt.RetainDataRoles, cleanOpt.RetainDataNodes)

if !skipConfirm {
target := ""
Expand Down Expand Up @@ -160,3 +118,146 @@ func (m *Manager) CleanCluster(name string, gOpt operator.Options, cleanOpt oper
log.Infof("Cleanup cluster `%s` successfully", name)
return nil
}

// cleanupFiles record the file that needs to be cleaned up
type cleanupFiles struct {
cleanupData bool // whether to clean up the data
cleanupLog bool // whether to clean up the log
cleanupTLS bool // whether to clean up the tls files
retainDataRoles []string // roles that don't clean up
retainDataNodes []string // roles that don't clean up
delFileMap map[string]set.StringSet
}

// getCleanupFiles get the files that need to be deleted
func getCleanupFiles(topo spec.Topology,
cleanupData, cleanupLog, cleanupTLS bool, retainDataRoles, retainDataNodes []string) map[string]set.StringSet {
c := &cleanupFiles{
cleanupData: cleanupData,
cleanupLog: cleanupLog,
cleanupTLS: cleanupTLS,
retainDataRoles: retainDataRoles,
retainDataNodes: retainDataNodes,
delFileMap: make(map[string]set.StringSet),
}

// calculate file paths to be deleted before the prompt
c.instanceCleanupFiles(topo)
c.monitorCleanupFiles(topo)

return c.delFileMap
}

// instanceCleanupFiles get the files that need to be deleted in the component
func (c *cleanupFiles) instanceCleanupFiles(topo spec.Topology) {
for _, com := range topo.ComponentsByStopOrder() {
instances := com.Instances()
retainDataRoles := set.NewStringSet(c.retainDataRoles...)
retainDataNodes := set.NewStringSet(c.retainDataNodes...)

for _, ins := range instances {
// not cleaning files of monitor agents if the instance does not have one
// may not work
switch ins.ComponentName() {
case spec.ComponentNodeExporter,
spec.ComponentBlackboxExporter:
if ins.IgnoreMonitorAgent() {
continue
}
}

// Some data of instances will be retained
dataRetained := retainDataRoles.Exist(ins.ComponentName()) ||
retainDataNodes.Exist(ins.ID()) || retainDataNodes.Exist(ins.GetHost())

if dataRetained {
continue
}

// prevent duplicate directories
dataPaths := set.NewStringSet()
logPaths := set.NewStringSet()
tlsPath := set.NewStringSet()

if c.cleanupData && len(ins.DataDir()) > 0 {
for _, dataDir := range strings.Split(ins.DataDir(), ",") {
dataPaths.Insert(path.Join(dataDir, "*"))
}
}

if c.cleanupLog && len(ins.LogDir()) > 0 {
for _, logDir := range strings.Split(ins.LogDir(), ",") {
logPaths.Insert(path.Join(logDir, "*.log"))
}
}

// clean tls data
if c.cleanupTLS && !topo.BaseTopo().GlobalOptions.TLSEnabled {
deployDir := spec.Abs(topo.BaseTopo().GlobalOptions.User, ins.DeployDir())
tlsDir := filepath.Join(deployDir, spec.TLSCertKeyDir)
tlsPath.Insert(tlsDir)
}

if c.delFileMap[ins.GetHost()] == nil {
c.delFileMap[ins.GetHost()] = set.NewStringSet()
}
c.delFileMap[ins.GetHost()].Join(logPaths).Join(dataPaths).Join(tlsPath)
}
}
}

// monitorCleanupFiles get the files that need to be deleted in the mointor
func (c *cleanupFiles) monitorCleanupFiles(topo spec.Topology) {
monitoredOptions := topo.BaseTopo().MonitoredOptions
if monitoredOptions == nil {
return
}
user := topo.BaseTopo().GlobalOptions.User

// get the host with monitor installed
uniqueHosts, noAgentHosts := getMonitorHosts(topo)
retainDataNodes := set.NewStringSet(c.retainDataNodes...)

// monitoring agents
for host := range uniqueHosts {
// determine if host don't need to delete
dataRetained := noAgentHosts.Exist(host) || retainDataNodes.Exist(host)
if dataRetained {
continue
}

deployDir := spec.Abs(user, monitoredOptions.DeployDir)

// prevent duplicate directories
dataPaths := set.NewStringSet()
logPaths := set.NewStringSet()
tlsPath := set.NewStringSet()

// data dir would be empty for components which don't need it
dataDir := monitoredOptions.DataDir
if c.cleanupData && len(dataDir) > 0 {
// the default data_dir is relative to deploy_dir
if !strings.HasPrefix(dataDir, "/") {
dataDir = filepath.Join(deployDir, dataDir)
}
dataPaths.Insert(path.Join(dataDir, "*"))
}

// log dir will always be with values, but might not used by the component
logDir := spec.Abs(user, monitoredOptions.LogDir)
if c.cleanupLog && len(logDir) > 0 {
logPaths.Insert(path.Join(logDir, "*.log"))
}

// clean tls data
if c.cleanupTLS && !topo.BaseTopo().GlobalOptions.TLSEnabled {
tlsDir := filepath.Join(deployDir, spec.TLSCertKeyDir)
tlsPath.Insert(tlsDir)
}

if c.delFileMap[host] == nil {
c.delFileMap[host] = set.NewStringSet()
}
c.delFileMap[host].Join(logPaths).Join(dataPaths).Join(tlsPath)
}
}

0 comments on commit 0349e97

Please sign in to comment.