From c938523cd54abe8c4b71a2b9009e9fdf175fa363 Mon Sep 17 00:00:00 2001
From: gotyaoi <gotyaoi@hotmail.com>
Date: Mon, 19 Oct 2015 00:09:36 -0700
Subject: [PATCH] Implementing LoadDirectory.

---
 cmd/telegraf/telegraf.go |  9 +++++
 config.go                | 76 ++++++++++++++++++++++++++++++++++++++++
 scripts/init.sh          |  5 +--
 scripts/telegraf.service |  2 +-
 4 files changed, 89 insertions(+), 3 deletions(-)

diff --git a/cmd/telegraf/telegraf.go b/cmd/telegraf/telegraf.go
index 8dd16226..19156d07 100644
--- a/cmd/telegraf/telegraf.go
+++ b/cmd/telegraf/telegraf.go
@@ -17,6 +17,8 @@ var fDebug = flag.Bool("debug", false,
 	"show metrics as they're generated to stdout")
 var fTest = flag.Bool("test", false, "gather metrics, print them out, and exit")
 var fConfig = flag.String("config", "", "configuration file to load")
+var fConfigDirectory = flag.String("configdirectory", "",
+	"directory containing additional configuration files")
 var fVersion = flag.Bool("version", false, "display the version")
 var fSampleConfig = flag.Bool("sample-config", false,
 	"print out full sample configuration")
@@ -81,6 +83,13 @@ func main() {
 		return
 	}
 
+	if *fConfigDirectory != "" {
+		err = config.LoadDirectory(*fConfigDirectory)
+		if err != nil {
+			log.Fatal(err)
+		}
+	}
+
 	ag, err := telegraf.NewAgent(config)
 	if err != nil {
 		log.Fatal(err)
diff --git a/config.go b/config.go
index 2c5152dd..9bd095e0 100644
--- a/config.go
+++ b/config.go
@@ -4,6 +4,7 @@ import (
 	"errors"
 	"fmt"
 	"io/ioutil"
+	"path/filepath"
 	"reflect"
 	"sort"
 	"strings"
@@ -378,6 +379,81 @@ func mergeStruct(base, overlay interface{}, fields []string) error {
 	return nil
 }
 
+func (c *Config) LoadDirectory(path string) error {
+	directoryEntries, err := ioutil.ReadDir(path)
+	if err != nil {
+		return err
+	}
+	for _, entry := range directoryEntries {
+		if entry.IsDir() {
+			continue
+		}
+		name := entry.Name()
+		if name[len(name)-5:] != ".conf" {
+			continue
+		}
+		subConfig, err := LoadConfig(filepath.Join(path, name))
+		if err != nil {
+			return err
+		}
+		if subConfig.agent != nil {
+			err = mergeStruct(c.agent, subConfig.agent, subConfig.agentFieldsSet)
+			if err != nil {
+				return err
+			}
+			for _, field := range subConfig.agentFieldsSet {
+				if !sliceContains(field, c.agentFieldsSet) {
+					c.agentFieldsSet = append(c.agentFieldsSet, field)
+				}
+			}
+		}
+		for pluginName, plugin := range subConfig.plugins {
+			if _, ok := c.plugins[pluginName]; !ok {
+				c.plugins[pluginName] = plugin
+				c.pluginFieldsSet[pluginName] = subConfig.pluginFieldsSet[pluginName]
+				c.pluginConfigurations[pluginName] = subConfig.pluginConfigurations[pluginName]
+				c.pluginConfigurationFieldsSet[pluginName] = subConfig.pluginConfigurationFieldsSet[pluginName]
+				continue
+			}
+			err = mergeStruct(c.plugins[pluginName], plugin, subConfig.pluginFieldsSet[pluginName])
+			if err != nil {
+				return err
+			}
+			for _, field := range subConfig.pluginFieldsSet[pluginName] {
+				if !sliceContains(field, c.pluginFieldsSet[pluginName]) {
+					c.pluginFieldsSet[pluginName] = append(c.pluginFieldsSet[pluginName], field)
+				}
+			}
+			err = mergeStruct(c.pluginConfigurations[pluginName], subConfig.pluginConfigurations[pluginName], subConfig.pluginConfigurationFieldsSet[pluginName])
+			if err != nil {
+				return err
+			}
+			for _, field := range subConfig.pluginConfigurationFieldsSet[pluginName] {
+				if !sliceContains(field, c.pluginConfigurationFieldsSet[pluginName]) {
+					c.pluginConfigurationFieldsSet[pluginName] = append(c.pluginConfigurationFieldsSet[pluginName], field)
+				}
+			}
+		}
+		for outputName, output := range subConfig.outputs {
+			if _, ok := c.outputs[outputName]; !ok {
+				c.outputs[outputName] = output
+				c.outputFieldsSet[outputName] = subConfig.outputFieldsSet[outputName]
+				continue
+			}
+			err = mergeStruct(c.outputs[outputName], output, subConfig.outputFieldsSet[outputName])
+			if err != nil {
+				return err
+			}
+			for _, field := range subConfig.outputFieldsSet[outputName] {
+				if !sliceContains(field, c.outputFieldsSet[outputName]) {
+					c.outputFieldsSet[outputName] = append(c.outputFieldsSet[outputName], field)
+				}
+			}
+		}
+	}
+	return nil
+}
+
 // hazmat area. Keeping the ast parsing here.
 
 // LoadConfig loads the given config file and returns a *Config pointer
diff --git a/scripts/init.sh b/scripts/init.sh
index a3b704e2..91e9b47b 100755
--- a/scripts/init.sh
+++ b/scripts/init.sh
@@ -111,6 +111,7 @@ fi
 
 # Configuration file
 config=/etc/opt/telegraf/telegraf.conf
+confdir=/etc/opt/telegraf/telegraf.d
 
 # If the daemon is not there, then exit.
 [ -x $daemon ] || exit 5
@@ -136,9 +137,9 @@ case $1 in
 
         log_success_msg "Starting the process" "$name"
         if which start-stop-daemon > /dev/null 2>&1; then
-            start-stop-daemon --chuid $GROUP:$USER --start --quiet --pidfile $pidfile --exec $daemon -- -pidfile $pidfile -config $config $TELEGRAF_OPTS >>$STDOUT 2>>$STDERR &
+            start-stop-daemon --chuid $GROUP:$USER --start --quiet --pidfile $pidfile --exec $daemon -- -pidfile $pidfile -config $config -configdirectory $confdir $TELEGRAF_OPTS >>$STDOUT 2>>$STDERR &
         else
-            nohup $daemon -pidfile $pidfile -config $config $TELEGRAF_OPTS >>$STDOUT 2>>$STDERR &
+            nohup $daemon -pidfile $pidfile -config $config -configdirectory $confdir $TELEGRAF_OPTS >>$STDOUT 2>>$STDERR &
         fi
         log_success_msg "$name process was started"
         ;;
diff --git a/scripts/telegraf.service b/scripts/telegraf.service
index 87fcd0f2..d5e46b12 100644
--- a/scripts/telegraf.service
+++ b/scripts/telegraf.service
@@ -6,7 +6,7 @@ After=network.target
 [Service]
 EnvironmentFile=-/etc/default/telegraf
 User=telegraf
-ExecStart=/opt/telegraf/telegraf -config /etc/opt/telegraf/telegraf.conf $TELEGRAF_OPTS
+ExecStart=/opt/telegraf/telegraf -config /etc/opt/telegraf/telegraf.conf -configdirectory /etc/opt/telegraf/telegraf.d $TELEGRAF_OPTS
 Restart=on-failure
 KillMode=process
 
-- 
GitLab