Skip to content

Commit

Permalink
Support use local file or directory as config for monitor components (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
lucklove authored Aug 28, 2020
1 parent 4978e39 commit d3003bf
Show file tree
Hide file tree
Showing 35 changed files with 2,532 additions and 112 deletions.
9 changes: 9 additions & 0 deletions components/dm/spec/alertmanager.go
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,15 @@ func (i *AlertManagerInstance) InitConfig(e executor.Executor, clusterName, clus
return err
}

// If the user specific a local config file, we should overwrite the default one with it
if spec.ConfigFilePath != "" {
name := filepath.Base(spec.ConfigFilePath)
dst := filepath.Join(paths.Deploy, "conf", name)
if err := i.TransferLocalConfigFile(e, spec.ConfigFilePath, dst); err != nil {
return errors.Annotate(err, "transfer alertmanager config failed")
}
}

return nil
}

Expand Down
120 changes: 78 additions & 42 deletions components/dm/spec/grafana.go
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,10 @@ func (i *GrafanaInstance) InitConfig(e executor.Executor, clusterName, clusterVe
return err
}

if err := i.initDashboards(e, i.InstanceSpec.(GrafanaSpec), paths); err != nil {
return errors.Annotate(err, "initial dashboards")
}

var dirs []string

// provisioningDir Must same as in grafana.ini.tpl
Expand Down Expand Up @@ -150,6 +154,27 @@ func (i *GrafanaInstance) InitConfig(e executor.Executor, clusterName, clusterVe
return e.Transfer(fp, dst, false)
}

func (i *GrafanaInstance) initDashboards(e executor.Executor, spec GrafanaSpec, paths meta.DirPaths) error {
dashboardsDir := filepath.Join(paths.Deploy, "dashboards")
// To make this step idempotent, we need cleanup old dashboards first
if _, _, err := e.Execute(fmt.Sprintf("rm -f %s/*", dashboardsDir), false); err != nil {
return err
}

if spec.DashboardDir != "" {
return i.TransferLocalConfigDir(e, spec.DashboardDir, dashboardsDir, func(name string) bool {
return strings.HasSuffix(name, ".json")
})
}

// Use the default ones
cmd := fmt.Sprintf("cp %[1]s/bin/*.json %[1]s/dashboards/", paths.Deploy)
if _, _, err := e.Execute(cmd, false); err != nil {
return err
}
return nil
}

// ScaleConfig deploy temporary config on scaling
func (i *GrafanaInstance) ScaleConfig(e executor.Executor, topo spec.Topology,
clusterName string, clusterVersion string, deployUser string, paths meta.DirPaths) error {
Expand Down Expand Up @@ -179,57 +204,68 @@ func (i *GrafanaInstance) Deploy(t *task.Builder, srcPath string, deployDir stri
).Func("Dashboards", func(ctx *task.Context) error {
e := ctx.Get(i.GetHost())

tmp := filepath.Join(deployDir, "_tiup_tmp")
_, stderr, err := e.Execute(fmt.Sprintf("mkdir -p %s", tmp), false)
if err != nil {
return errors.Annotatef(err, "stderr: %s", string(stderr))
}
return i.installDashboards(e, deployDir, clusterName, clusterVersion)
})
}

srcPath := task.PackagePath(ComponentDMMaster, clusterVersion, i.OS(), i.Arch())
dstPath := filepath.Join(tmp, filepath.Base(srcPath))
err = e.Transfer(srcPath, dstPath, false)
if err != nil {
return errors.AddStack(err)
}
func (i *GrafanaInstance) installDashboards(e executor.Executor, deployDir, clusterName, clusterVersion string) error {
tmp := filepath.Join(deployDir, "_tiup_tmp")
_, stderr, err := e.Execute(fmt.Sprintf("mkdir -p %s", tmp), false)
if err != nil {
return errors.Annotatef(err, "stderr: %s", string(stderr))
}

cmd := fmt.Sprintf(`tar --no-same-owner -zxf %s -C %s && rm %s`, dstPath, tmp, dstPath)
_, stderr, err = e.Execute(cmd, false)
if err != nil {
return errors.Annotatef(err, "stderr: %s", string(stderr))
}
srcPath := task.PackagePath(ComponentDMMaster, clusterVersion, i.OS(), i.Arch())
dstPath := filepath.Join(tmp, filepath.Base(srcPath))
err = e.Transfer(srcPath, dstPath, false)
if err != nil {
return errors.AddStack(err)
}

// copy dm-master/scripts/*.json
targetDir := filepath.Join(deployDir, "dashboards")
_, stderr, err = e.Execute(fmt.Sprintf("mkdir -p %s", targetDir), false)
if err != nil {
return errors.Annotatef(err, "stderr: %s", string(stderr))
}
cmd := fmt.Sprintf(`tar --no-same-owner -zxf %s -C %s && rm %s`, dstPath, tmp, dstPath)
_, stderr, err = e.Execute(cmd, false)
if err != nil {
return errors.Annotatef(err, "stderr: %s", string(stderr))
}

cmd = fmt.Sprintf("cp %s/dm-master/scripts/*json %s", tmp, targetDir)
_, stderr, err = e.Execute(cmd, false)
if err != nil {
return errors.Annotatef(err, "stderr: %s", string(stderr))
}
// copy dm-master/scripts/*.json
targetDir := filepath.Join(deployDir, "dashboards")
_, stderr, err = e.Execute(fmt.Sprintf("mkdir -p %s", targetDir), false)
if err != nil {
return errors.Annotatef(err, "stderr: %s", string(stderr))
}

for _, cmd := range []string{
`find %s -type f -exec sed -i "s/\${DS_.*-CLUSTER}/%s/g" {} \;`,
`find %s -type f -exec sed -i "s/DS_.*-CLUSTER/%s/g" {} \;`,
`find %s -type f -exec sed -i "s/test-cluster/%s/g" {} \;`,
`find %s -type f -exec sed -i "s/Test-Cluster/%s/g" {} \;`,
} {
cmd := fmt.Sprintf(cmd, targetDir, clusterName)
_, stderr, err = e.Execute(cmd, false)
if err != nil {
return errors.Annotatef(err, "stderr: %s", string(stderr))
}
}
cmd = fmt.Sprintf("cp %s/dm-master/scripts/*.json %s", tmp, targetDir)
_, stderr, err = e.Execute(cmd, false)
if err != nil {
return errors.Annotatef(err, "stderr: %s", string(stderr))
}

cmd = fmt.Sprintf("rm -rf %s", tmp)
for _, cmd := range []string{
`find %s -type f -exec sed -i "s/\${DS_.*-CLUSTER}/%s/g" {} \;`,
`find %s -type f -exec sed -i "s/DS_.*-CLUSTER/%s/g" {} \;`,
`find %s -type f -exec sed -i "s/test-cluster/%s/g" {} \;`,
`find %s -type f -exec sed -i "s/Test-Cluster/%s/g" {} \;`,
} {
cmd := fmt.Sprintf(cmd, targetDir, clusterName)
_, stderr, err = e.Execute(cmd, false)
if err != nil {
return errors.Annotatef(err, "stderr: %s", string(stderr))
}
}

return nil
})
cmd = fmt.Sprintf("rm -rf %s", tmp)
_, stderr, err = e.Execute(cmd, false)
if err != nil {
return errors.Annotatef(err, "stderr: %s", string(stderr))
}

// backup *.json for later reload (in case that the user change dashboard_dir)
cmd = fmt.Sprintf("cp %s/*.json %s", targetDir, filepath.Join(deployDir, "bin"))
_, stderr, err = e.Execute(cmd, false)
if err != nil {
return errors.Annotatef(err, "stderr: %s", string(stderr))
}

return nil
}
58 changes: 58 additions & 0 deletions components/dm/spec/grafana_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
// Copyright 2020 PingCAP, Inc.
//
// 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,
// See the License for the specific language governing permissions and
// limitations under the License.

package spec

import (
"io/ioutil"
"os"
"path"
"path/filepath"
"testing"

"github.com/pingcap/tiup/pkg/cluster/executor"
"github.com/pingcap/tiup/pkg/meta"
"github.com/stretchr/testify/assert"
)

func TestLocalDashboards(t *testing.T) {
deployDir, err := ioutil.TempDir("", "tiup-*")
assert.Nil(t, err)
defer os.RemoveAll(deployDir)
localDir, err := filepath.Abs("./testdata/dashboards")
assert.Nil(t, err)

topo := new(Topology)
topo.Grafana = append(topo.Grafana, GrafanaSpec{
Host: "127.0.0.1",
Port: 3000,
DashboardDir: localDir,
})

comp := GrafanaComponent{topo}
ints := comp.Instances()

assert.Equal(t, len(ints), 1)
grafanaInstance := ints[0].(*GrafanaInstance)

e := &executor.Local{}
err = grafanaInstance.initDashboards(e, topo.Grafana[0], meta.DirPaths{Deploy: deployDir})
assert.Nil(t, err)

assert.FileExists(t, path.Join(deployDir, "dashboards", "tidb.json"))
fs, err := ioutil.ReadDir(localDir)
assert.Nil(t, err)
for _, f := range fs {
assert.FileExists(t, path.Join(deployDir, "dashboards", f.Name()))
}
}
107 changes: 73 additions & 34 deletions components/dm/spec/prometheus.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ package spec
import (
"fmt"
"path/filepath"
"strings"

"github.com/pingcap/errors"
"github.com/pingcap/tiup/pkg/cluster"
Expand Down Expand Up @@ -121,13 +122,39 @@ func (i *MonitorInstance) InitConfig(e executor.Executor, clusterName, clusterVe
cfig.AddAlertmanager(alertmanager.Host, uint64(alertmanager.WebPort))
}

if err := i.initRules(e, spec, paths); err != nil {
return errors.AddStack(err)
}

if err := cfig.ConfigToFile(fp); err != nil {
return err
}
dst = filepath.Join(paths.Deploy, "conf", "prometheus.yml")
return e.Transfer(fp, dst, false)
}

func (i *MonitorInstance) initRules(e executor.Executor, spec PrometheusSpec, paths meta.DirPaths) error {
confDir := filepath.Join(paths.Deploy, "conf")
// To make this step idempotent, we need cleanup old rules first
if _, _, err := e.Execute(fmt.Sprintf("rm -f %s/*.rules.yml", confDir), false); err != nil {
return err
}

// If the user specify a rule directory, we should use the rules specified
if spec.RuleDir != "" {
return i.TransferLocalConfigDir(e, spec.RuleDir, confDir, func(name string) bool {
return strings.HasSuffix(name, ".rules.yml")
})
}

// Use the default ones
cmd := fmt.Sprintf("cp %[1]s/bin/prometheus/*.rules.yml %[1]s/conf/", paths.Deploy)
if _, _, err := e.Execute(cmd, false); err != nil {
return err
}
return nil
}

// ScaleConfig deploy temporary config on scaling
func (i *MonitorInstance) ScaleConfig(e executor.Executor, topo spec.Topology,
clusterName string, clusterVersion string, deployUser string, paths meta.DirPaths) error {
Expand Down Expand Up @@ -156,39 +183,51 @@ func (i *MonitorInstance) Deploy(t *task.Builder, srcPath string, deployDir stri
).Func("CopyRulesYML", func(ctx *task.Context) error {
e := ctx.Get(i.GetHost())

tmp := filepath.Join(deployDir, "_tiup_tmp")
_, stderr, err := e.Execute(fmt.Sprintf("mkdir -p %s", tmp), false)
if err != nil {
return errors.Annotatef(err, "stderr: %s", string(stderr))
}

srcPath := task.PackagePath(ComponentDMMaster, clusterVersion, i.OS(), i.Arch())
dstPath := filepath.Join(tmp, filepath.Base(srcPath))

err = e.Transfer(srcPath, dstPath, false)
if err != nil {
return errors.AddStack(err)
}

cmd := fmt.Sprintf(`tar --no-same-owner -zxf %s -C %s && rm %s`, dstPath, tmp, dstPath)
_, stderr, err = e.Execute(cmd, false)
if err != nil {
return errors.Annotatef(err, "stderr: %s", string(stderr))
}

// copy dm-master/conf/*.rules.yml
cmd = fmt.Sprintf("cp %s/dm-master/conf/*rules.yml %s", tmp, filepath.Join(deployDir, "conf"))
_, stderr, err = e.Execute(cmd, false)
if err != nil {
return errors.Annotatef(err, "stderr: %s", string(stderr))
}

cmd = fmt.Sprintf("rm -rf %s", tmp)
_, stderr, err = e.Execute(cmd, false)
if err != nil {
return errors.Annotatef(err, "stderr: %s", string(stderr))
}

return nil
return i.installRules(e, deployDir, clusterVersion)
})
}

func (i *MonitorInstance) installRules(e executor.Executor, deployDir, clusterVersion string) error {
tmp := filepath.Join(deployDir, "_tiup_tmp")
_, stderr, err := e.Execute(fmt.Sprintf("mkdir -p %s", tmp), false)
if err != nil {
return errors.Annotatef(err, "stderr: %s", string(stderr))
}

srcPath := task.PackagePath(ComponentDMMaster, clusterVersion, i.OS(), i.Arch())
dstPath := filepath.Join(tmp, filepath.Base(srcPath))

err = e.Transfer(srcPath, dstPath, false)
if err != nil {
return errors.AddStack(err)
}

cmd := fmt.Sprintf(`tar --no-same-owner -zxf %s -C %s && rm %s`, dstPath, tmp, dstPath)
_, stderr, err = e.Execute(cmd, false)
if err != nil {
return errors.Annotatef(err, "stderr: %s", string(stderr))
}

// copy dm-master/conf/*.rules.yml
targetDir := filepath.Join(deployDir, "conf")
cmd = fmt.Sprintf("cp %s/dm-master/conf/*.rules.yml %s", tmp, targetDir)
_, stderr, err = e.Execute(cmd, false)
if err != nil {
return errors.Annotatef(err, "stderr: %s", string(stderr))
}

cmd = fmt.Sprintf("rm -rf %s", tmp)
_, stderr, err = e.Execute(cmd, false)
if err != nil {
return errors.Annotatef(err, "stderr: %s", string(stderr))
}

// backup *.rules.yml for later reload (in case that the user change rule_dir)
cmd = fmt.Sprintf("cp %s/*.rules.yml %s", targetDir, filepath.Join(deployDir, "bin", "prometheus"))
_, stderr, err = e.Execute(cmd, false)
if err != nil {
return errors.Annotatef(err, "stderr: %s", string(stderr))
}

return nil
}
3 changes: 3 additions & 0 deletions components/dm/spec/testdata/dashboards/tidb.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"desc": "this is a dummy test file"
}
6 changes: 5 additions & 1 deletion components/dm/spec/topology_dm.go
Original file line number Diff line number Diff line change
Expand Up @@ -542,7 +542,11 @@ func (topo *Topology) Validate() error {
return err
}

return topo.dirConflictsDetect()
if err := topo.dirConflictsDetect(); err != nil {
return err
}

return spec.RelativePathDetect(topo, isSkipField)
}

// BaseTopo implements Topology interface.
Expand Down
Loading

0 comments on commit d3003bf

Please sign in to comment.