Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Harvest should load templates from a set of conf directories #2394

Merged
merged 1 commit into from
Oct 3, 2023
Merged
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
98 changes: 64 additions & 34 deletions cmd/tools/generate/generate.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ type PollerInfo struct {
ContainerName string
ShowPorts bool
IsFull bool
TemplateDir string
CertDir string
Mounts []string
}
Expand Down Expand Up @@ -61,11 +60,12 @@ type options struct {
filesdPath string
showPorts bool
outputPath string
templateDir string
certDir string
promPort int
grafanaPort int
mounts []string
configPath string
confPath string
}

var opts = &options{
Expand Down Expand Up @@ -105,22 +105,28 @@ var metricCmd = &cobra.Command{
}

func doDockerFull(cmd *cobra.Command, _ []string) {
var config = cmd.Root().PersistentFlags().Lookup("config")
generateDocker(conf.ConfigPath(config.Value.String()), full)
addRootOptions(cmd)
generateDocker(full)
}

func doSystemd(cmd *cobra.Command, _ []string) {
var config = cmd.Root().PersistentFlags().Lookup("config")
generateSystemd(conf.ConfigPath(config.Value.String()))
addRootOptions(cmd)
generateSystemd()
}

func doDockerCompose(cmd *cobra.Command, _ []string) {
var config = cmd.Root().PersistentFlags().Lookup("config")
generateDocker(conf.ConfigPath(config.Value.String()), harvest)
addRootOptions(cmd)
generateDocker(harvest)
}

func doGenerateMetrics(cmd *cobra.Command, _ []string) {
var config = cmd.Root().PersistentFlags().Lookup("config")
generateMetrics(conf.ConfigPath(config.Value.String()))
addRootOptions(cmd)
generateMetrics()
}

func addRootOptions(cmd *cobra.Command) {
opts.configPath = conf.ConfigPath(cmd.Root().PersistentFlags().Lookup("config").Value.String())
opts.confPath = cmd.Root().PersistentFlags().Lookup("confpath").Value.String()
}

const (
Expand All @@ -134,35 +140,27 @@ func normalizeContainerNames(name string) string {
return strings.ToLower(re.ReplaceAllString(name, "-"))
}

func generateDocker(path string, kind int) {
func generateDocker(kind int) {
var (
pollerTemplate PollerTemplate
configFilePath string
templateDirPath string
certDirPath string
filesd []string
extraMounts []string
out *os.File
pollerTemplate PollerTemplate
configFilePath string
certDirPath string
filesd []string
out *os.File
)

pollerTemplate = PollerTemplate{}
promTemplate := PromTemplate{
opts.grafanaPort,
opts.promPort,
}
_, err := conf.LoadHarvestConfig(path)
_, err := conf.LoadHarvestConfig(opts.configPath)
if err != nil {
logErrAndExit(err)
}
configFilePath = asComposePath(path)
templateDirPath = asComposePath(opts.templateDir)
configFilePath = asComposePath(opts.configPath)
certDirPath = asComposePath(opts.certDir)

extraMounts = make([]string, 0, len(opts.mounts))
for _, mount := range opts.mounts {
extraMounts = append(extraMounts, asComposePath(mount))
}

for _, v := range conf.Config.PollersOrdered {
port, _ := conf.GetPrometheusExporterPorts(v, true)
pollerInfo := PollerInfo{
Expand All @@ -175,9 +173,8 @@ func generateDocker(path string, kind int) {
ContainerName: normalizeContainerNames("poller_" + v),
ShowPorts: opts.showPorts,
IsFull: kind == full,
TemplateDir: templateDirPath,
CertDir: certDirPath,
Mounts: extraMounts,
Mounts: makeMounts(v),
}
pollerTemplate.Pollers = append(pollerTemplate.Pollers, pollerInfo)
filesd = append(filesd, fmt.Sprintf("- targets: ['%s:%d']", pollerInfo.ServiceName, pollerInfo.Port))
Expand Down Expand Up @@ -272,6 +269,40 @@ func generateDocker(path string, kind int) {
}
}

// setup mount(s) for the confpath and any CLI-passed mounts
func makeMounts(pollerName string) []string {
var mounts = opts.mounts

p, err := conf.PollerNamed(pollerName)
if err != nil {
logErrAndExit(err)
}

confPath := opts.confPath
if confPath == "conf" {
confPath = p.ConfPath
}

if confPath == "" {
mounts = append(mounts, toMount("./conf"))
} else {
paths := strings.Split(confPath, ":")
for _, path := range paths {
mounts = append(mounts, toMount(path))
}
}

return mounts
}

func toMount(hostPath string) string {
hostPath = asComposePath(hostPath)
if strings.HasPrefix(hostPath, "./") {
return hostPath + ":" + "/opt/harvest/" + hostPath[2:]
}
return hostPath + ":" + hostPath
}

func copyFiles(srcPath, destPath string) error {
filesToExclude := map[string]bool{
"harvest.yml": true,
Expand Down Expand Up @@ -346,9 +377,9 @@ func silentClose(body io.ReadCloser) {
_ = body.Close()
}

func generateSystemd(path string) {
func generateSystemd() {
var adminService string
_, err := conf.LoadHarvestConfig(path)
_, err := conf.LoadHarvestConfig(opts.configPath)
if err != nil {
logErrAndExit(err)
}
Expand All @@ -367,7 +398,7 @@ func generateSystemd(path string) {
println("and " + color.Colorize("cp "+harvestAdminService+" /etc/systemd/system/", color.Green))
}
println("and then run " + color.Colorize("systemctl daemon-reload", color.Green))
writeAdminSystemd(path)
writeAdminSystemd(opts.configPath)
// reorder list of pollers so that unix collectors are last, see https://github.com/NetApp/harvest/issues/643
pollers := make([]string, 0)
unixPollers := make([]string, 0)
Expand Down Expand Up @@ -422,15 +453,15 @@ func writeAdminSystemd(configFp string) {
println(color.Colorize("✓", color.Green) + " HTTP SD file: " + harvestAdminService + " created")
}

func generateMetrics(path string) {
func generateMetrics() {
var (
poller *conf.Poller
err error
restClient *rest.Client
zapiClient *zapi.Client
)

_, err = conf.LoadHarvestConfig(path)
_, err = conf.LoadHarvestConfig(opts.configPath)
if err != nil {
logErrAndExit(err)
}
Expand Down Expand Up @@ -480,7 +511,6 @@ func init() {
"logging level (0=trace, 1=debug, 2=info, 3=warning, 4=error, 5=critical)",
)
dFlags.StringVar(&opts.image, "image", "ghcr.io/netapp/harvest:latest", "Harvest image. Use rahulguptajss/harvest:latest to pull from Docker Hub")
dFlags.StringVar(&opts.templateDir, "templatedir", "./conf", "Harvest template dir path")
dFlags.StringVar(&opts.certDir, "certdir", "./cert", "Harvest certificate dir path")
dFlags.StringVarP(&opts.outputPath, "output", "o", "", "Output file path. ")
dFlags.BoolVarP(&opts.showPorts, "port", "p", true, "Expose poller ports to host machine")
Expand Down
22 changes: 22 additions & 0 deletions cmd/tools/generate/generate_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package generate

import "testing"

func Test_toMount(t *testing.T) {
tests := []struct {
name string
hostPath string
want string
}{
{name: "dot prefix", hostPath: "./abc/d", want: "./abc/d:/opt/harvest/abc/d"},
{name: "absolute", hostPath: "/x/y/z", want: "/x/y/z:/x/y/z"},
{name: "cwd", hostPath: "abc/d", want: "./abc/d:/opt/harvest/abc/d"},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := toMount(tt.hostPath); got != tt.want {
t.Errorf("toMount() = %v, want %v", got, tt.want)
}
})
}
}
1 change: 0 additions & 1 deletion container/onePollerPerContainer/docker-compose.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ services:
command: '--poller {{ .PollerName }} {{if .Port }}--promPort {{ .Port }} {{ end }}
{{- if ne .LogLevel 2 }}--loglevel {{ .LogLevel }} {{ end}}--config /opt/harvest.yml'
volumes:
- {{ .TemplateDir }}:/opt/harvest/conf
- {{ .CertDir }}:/opt/harvest/cert
- {{ .ConfigFile }}:/opt/harvest.yml
{{- range .Mounts}}
Expand Down