Exemple #1
0
func TestInitConfigDefaultConfig(t *testing.T) {
	log.SetQuiet(true)
	want := Config{
		Backend:      "etcd",
		BackendNodes: []string{"http://127.0.0.1:4001"},
		ClientCaKeys: "",
		ClientCert:   "",
		ClientKey:    "",
		ConfDir:      "/etc/confd",
		Debug:        false,
		Interval:     600,
		Noop:         false,
		Prefix:       "/",
		Quiet:        false,
		SRVDomain:    "",
		Scheme:       "http",
		Verbose:      false,
	}
	if err := initConfig(); err != nil {
		t.Errorf(err.Error())
	}
	if !reflect.DeepEqual(want, config) {
		t.Errorf("initConfig() = %v, want %v", config, want)
	}
}
Exemple #2
0
func TestSameConfigFalse(t *testing.T) {
	log.SetQuiet(true)
	src, err := ioutil.TempFile("", "src")
	defer os.Remove(src.Name())
	if err != nil {
		t.Errorf(err.Error())
	}
	_, err = src.WriteString("src")
	if err != nil {
		t.Errorf(err.Error())
	}
	dest, err := ioutil.TempFile("", "dest")
	defer os.Remove(dest.Name())
	if err != nil {
		t.Errorf(err.Error())
	}
	_, err = dest.WriteString("dest")
	if err != nil {
		t.Errorf(err.Error())
	}
	status, err := sameConfig(src.Name(), dest.Name())
	if err != nil {
		t.Errorf(err.Error())
	}
	if status != false {
		t.Errorf("Expected sameConfig(src, dest) to be %v, got %v", false, status)
	}
}
Exemple #3
0
func main() {
	// Most flags are defined in the confd/config package which allows us to
	// override configuration settings from the command line. Parse the flags now
	// to make them active.
	flag.Parse()
	if printVersion {
		fmt.Printf("confd %s\n", Version)
		os.Exit(0)
	}
	if configFile == "" {
		if IsFileExist(defaultConfigFile) {
			configFile = defaultConfigFile
		}
	}
	// Initialize the global configuration.
	log.Debug("Loading confd configuration")
	if err := config.LoadConfig(configFile); err != nil {
		log.Fatal(err.Error())
	}
	// Configure logging. While you can enable debug and verbose logging, however
	// if quiet is set to true then debug and verbose messages will not be printed.
	log.SetQuiet(config.Quiet())
	log.SetVerbose(config.Verbose())
	log.SetDebug(config.Debug())
	log.Notice("Starting confd")

	// Create the storage client
	log.Notice("Backend set to " + config.Backend())
	store, err := backends.New(config.Backend())
	if err != nil {
		log.Fatal(err.Error())
	}

	signalChan := make(chan os.Signal, 1)
	signal.Notify(signalChan, syscall.SIGINT, syscall.SIGTERM)
	for {
		runErrors := template.ProcessTemplateResources(store)
		// If the -onetime flag is passed on the command line we immediately exit
		// after processing the template config files.
		if onetime {
			if len(runErrors) > 0 {
				os.Exit(1)
			}
			os.Exit(0)
		}
		select {
		case c := <-signalChan:
			log.Info(fmt.Sprintf("captured %v exiting...", c))
			os.Exit(0)
		case <-time.After(time.Duration(config.Interval()) * time.Second):
			// Continue processing templates.
		}
	}
}
Exemple #4
0
func TestIsFileExist(t *testing.T) {
	log.SetQuiet(true)
	result := isFileExist(fakeFile)
	if result != false {
		t.Errorf("Expected IsFileExist(%s) to be false, got %v", fakeFile, result)
	}
	f, err := ioutil.TempFile("", "")
	if err != nil {
		t.Fatal(err.Error())
	}
	defer os.Remove(f.Name())
	result = isFileExist(f.Name())
	if result != true {
		t.Errorf("Expected IsFileExist(%s) to be true, got %v", f.Name(), result)
	}
}
Exemple #5
0
func TestLoadConfig(t *testing.T) {
	log.SetQuiet(true)
	var expected = struct {
		clientCert  string
		clientKey   string
		configDir   string
		etcdNodes   []string
		interval    int
		prefix      string
		templateDir string
	}{
		"", "", "/etc/confd/conf.d", []string{"http://127.0.0.1:4001"},
		600, "/", "/etc/confd/templates",
	}
	LoadConfig("")
	cc := ClientCert()
	if cc != expected.clientCert {
		t.Errorf("Expected default clientCert = %s, got %s", expected.clientCert, cc)
	}
	ck := ClientKey()
	if ck != expected.clientKey {
		t.Errorf("Expected default clientKey = %s, got %s", expected.clientKey, ck)
	}
	cd := ConfigDir()
	if cd != expected.configDir {
		t.Errorf("Expected default configDir = %s, got %s", expected.configDir, cd)
	}
	en := EtcdNodes()
	if en[0] != expected.etcdNodes[0] {
		t.Errorf("Expected default etcdNodes = %v, got %v", expected.etcdNodes, en)
	}
	i := Interval()
	if i != expected.interval {
		t.Errorf("Expected default interval = %d, got %d", expected.interval, i)
	}
	p := Prefix()
	if p != expected.prefix {
		t.Errorf("Expected default prefix = %s, got %s", expected.prefix, p)
	}
	td := TemplateDir()
	if td != expected.templateDir {
		t.Errorf("Expected default templateDir = %s, got %s", expected.templateDir, td)
	}
}
Exemple #6
0
func TestBrokenTemplateResourceFile(t *testing.T) {
	log.SetQuiet(true)
	tempFile, err := ioutil.TempFile("", "")
	defer os.Remove(tempFile.Name())
	if err != nil {
		t.Errorf(err.Error())
	}
	_, err = tempFile.WriteString(brokenTemplateResourceConfig)
	if err != nil {
		t.Errorf(err.Error())
	}
	// Create the stub etcd client.
	c := etcdtest.NewClient()
	// Process broken template resource config file.
	_, err = NewTemplateResourceFromPath(tempFile.Name(), c)
	if err == nil {
		t.Errorf("Expected err not to be nil")
	}
}
Exemple #7
0
func main() {
	// Most flags are defined in the confd/config package which allows us to
	// override configuration settings from the command line. Parse the flags now
	// to make them active.
	flag.Parse()
	if configFile == "" {
		if IsFileExist(defaultConfigFile) {
			configFile = defaultConfigFile
		}
	}
	// Initialize the global configuration.
	log.Debug("Loading confd configuration")
	if err := config.LoadConfig(configFile); err != nil {
		log.Fatal(err.Error())
	}
	// Configure logging. While you can enable debug and verbose logging, however
	// if quiet is set to true then debug and verbose messages will not be printed.
	log.SetQuiet(config.Quiet())
	log.SetVerbose(config.Verbose())
	log.SetDebug(config.Debug())
	log.Notice("Starting confd")
	// Create the etcd client upfront and use it for the life of the process.
	// The etcdClient is an http.Client and designed to be reused.
	log.Notice("etcd nodes set to " + strings.Join(config.EtcdNodes(), ", "))
	etcdClient, err := etcdutil.NewEtcdClient(config.EtcdNodes(), config.ClientCert(), config.ClientKey(), config.ClientCaKeys())
	if err != nil {
		log.Fatal(err.Error())
	}
	for {
		runErrors := template.ProcessTemplateResources(etcdClient)
		// If the -onetime flag is passed on the command line we immediately exit
		// after processing the template config files.
		if onetime {
			if len(runErrors) > 0 {
				os.Exit(1)
			}
			os.Exit(0)
		}
		time.Sleep(time.Duration(config.Interval()) * time.Second)
	}
}
Exemple #8
0
func main() {
	// Most flags are defined in the confd/config package which allows us to
	// override configuration settings from the command line. Parse the flags now
	// to make them active.
	flag.Parse()
	if configFile == "" {
		if IsFileExist(defaultConfigFile) {
			configFile = defaultConfigFile
		}
	}
	// Initialize the global configuration.
	log.Debug("Loading confd configuration")
	if err := config.LoadConfig(configFile); err != nil {
		log.Fatal(err.Error())
	}
	// Configure logging. While you can enable debug and verbose logging, however
	// if quiet is set to true then debug and verbose messages will not be printed.
	log.SetQuiet(config.Quiet())
	log.SetVerbose(config.Verbose())
	log.SetDebug(config.Debug())
	log.Notice("Starting confd")

	// Create the storage client
	store, err := createStoreClient(config.Backend())
	if err != nil {
		log.Fatal(err.Error())
	}

	for {
		runErrors := template.ProcessTemplateResources(store)
		// If the -onetime flag is passed on the command line we immediately exit
		// after processing the template config files.
		if onetime {
			if len(runErrors) > 0 {
				os.Exit(1)
			}
			os.Exit(0)
		}
		time.Sleep(time.Duration(config.Interval()) * time.Second)
	}
}
Exemple #9
0
func TestProcessTemplateResources(t *testing.T) {
	log.SetQuiet(true)
	// Setup temporary conf, config, and template directories.
	tempConfDir, err := createTempDirs()
	if err != nil {
		t.Errorf("Failed to create temp dirs: %s", err.Error())
	}
	defer os.RemoveAll(tempConfDir)

	// Create the src template.
	srcTemplateFile := filepath.Join(tempConfDir, "templates", "foo.tmpl")
	err = ioutil.WriteFile(srcTemplateFile, []byte("foo = {{ .foo }}"), 0644)
	if err != nil {
		t.Error(err.Error())
	}

	// Create the dest.
	destFile, err := ioutil.TempFile("", "")
	if err != nil {
		t.Errorf("Failed to create destFile: %s", err.Error())
	}
	defer os.Remove(destFile.Name())

	// Create the template resource configuration file.
	templateResourcePath := filepath.Join(tempConfDir, "conf.d", "foo.toml")
	templateResourceFile, err := os.Create(templateResourcePath)
	if err != nil {
		t.Errorf(err.Error())
	}
	tmpl, err := template.New("templateResourceConfig").Parse(templateResourceConfigTmpl)
	if err != nil {
		t.Errorf("Unable to parse template resource template: %s", err.Error())
	}
	data := make(map[string]string)
	data["src"] = "foo.tmpl"
	data["dest"] = destFile.Name()
	err = tmpl.Execute(templateResourceFile, data)
	if err != nil {
		t.Errorf(err.Error())
	}

	// Load the confd configuration settings.
	if err := config.LoadConfig(""); err != nil {
		t.Errorf(err.Error())
	}
	config.SetPrefix("")
	// Use the temporary tempConfDir from above.
	config.SetConfDir(tempConfDir)

	// Create the stub etcd client.
	c := &MockStore{}
	c.AddKey("/foo", "bar")

	// Process the test template resource.
	runErrors := ProcessTemplateResources(c)
	if len(runErrors) > 0 {
		for _, e := range runErrors {
			t.Errorf(e.Error())
		}
	}
	// Verify the results.
	expected := "foo = bar"
	results, err := ioutil.ReadFile(destFile.Name())
	if err != nil {
		t.Error(err.Error())
	}
	if string(results) != expected {
		t.Errorf("Expected contents of dest == '%s', got %s", expected, string(results))
	}
}
Exemple #10
0
// initConfig initializes the confd configuration by first setting defaults,
// then overriding setting from the confd config file, and finally overriding
// settings from flags set on the command line.
// It returns an error if any.
func initConfig() error {
	if configFile == "" {
		if _, err := os.Stat(defaultConfigFile); !os.IsNotExist(err) {
			configFile = defaultConfigFile
		}
	}
	// Set defaults.
	config = Config{
		Backend:  "etcd",
		ConfDir:  "/etc/confd",
		Interval: 600,
		Prefix:   "/",
		Scheme:   "http",
	}
	// Update config from the TOML configuration file.
	if configFile == "" {
		log.Warning("Skipping confd config file.")
	} else {
		log.Debug("Loading " + configFile)
		configBytes, err := ioutil.ReadFile(configFile)
		if err != nil {
			return err
		}
		_, err = toml.Decode(string(configBytes), &config)
		if err != nil {
			return err
		}
	}
	// Update config from commandline flags.
	processFlags()

	// Configure logging.
	log.SetQuiet(config.Quiet)
	log.SetVerbose(config.Verbose)
	log.SetDebug(config.Debug)

	// Update BackendNodes from SRV records.
	if config.Backend != "env" && config.SRVDomain != "" {
		log.Info("SRV domain set to " + config.SRVDomain)
		srvNodes, err := getBackendNodesFromSRV(config.Backend, config.SRVDomain, config.Scheme)
		if err != nil {
			return errors.New("Cannot get nodes from SRV records " + err.Error())
		}
		config.BackendNodes = srvNodes
	}
	if len(config.BackendNodes) == 0 {
		switch config.Backend {
		case "consul":
			config.BackendNodes = []string{"127.0.0.1:8500"}
		case "etcd":
			peerstr := os.Getenv("ETCDCTL_PEERS")
			if len(peerstr) > 0 {
				config.BackendNodes = strings.Split(peerstr, ",")
			} else {
				config.BackendNodes = []string{"http://127.0.0.1:4001"}
			}
		case "redis":
			config.BackendNodes = []string{"127.0.0.1:6379"}
		}
	}
	// Initialize the storage client
	log.Notice("Backend set to " + config.Backend)

	if config.Watch {
		unsupportedBackends := map[string]bool{
			"zookeeper": true,
			"redis":     true,
		}

		if unsupportedBackends[config.Backend] {
			log.Notice(fmt.Sprintf("Watch is not supported for backend %s. Exiting...", config.Backend))
			os.Exit(1)
		}
	}

	backendsConfig = backends.Config{
		Backend:      config.Backend,
		ClientCaKeys: config.ClientCaKeys,
		ClientCert:   config.ClientCert,
		ClientKey:    config.ClientKey,
		BackendNodes: config.BackendNodes,
		Scheme:       config.Scheme,
	}
	// Template configuration.
	templateConfig = template.Config{
		ConfDir:       config.ConfDir,
		ConfigDir:     filepath.Join(config.ConfDir, "conf.d"),
		KeepStageFile: keepStageFile,
		Noop:          config.Noop,
		Prefix:        config.Prefix,
		TemplateDir:   filepath.Join(config.ConfDir, "templates"),
	}
	return nil
}
Exemple #11
0
func TestProcessTemplateResources(t *testing.T) {
	log.SetQuiet(true)
	// Setup temporary conf, config, and template directories.
	tempConfDir, err := createTempDirs()
	if err != nil {
		t.Errorf("Failed to create temp dirs: %s", err.Error())
	}
	defer os.RemoveAll(tempConfDir)

	// Create the src template.
	srcTemplateFile := filepath.Join(tempConfDir, "templates", "foo.tmpl")
	err = ioutil.WriteFile(srcTemplateFile, []byte(`foo = {{getv "/foo"}}`), 0644)
	if err != nil {
		t.Error(err.Error())
	}

	// Create the dest.
	destFile, err := ioutil.TempFile("", "")
	if err != nil {
		t.Errorf("Failed to create destFile: %s", err.Error())
	}
	defer os.Remove(destFile.Name())

	// Create the template resource configuration file.
	templateResourcePath := filepath.Join(tempConfDir, "conf.d", "foo.toml")
	templateResourceFile, err := os.Create(templateResourcePath)
	if err != nil {
		t.Errorf(err.Error())
	}
	tmpl, err := template.New("templateResourceConfig").Parse(templateResourceConfigTmpl)
	if err != nil {
		t.Errorf("Unable to parse template resource template: %s", err.Error())
	}
	data := make(map[string]string)
	data["src"] = "foo.tmpl"
	data["dest"] = destFile.Name()
	err = tmpl.Execute(templateResourceFile, data)
	if err != nil {
		t.Errorf(err.Error())
	}

	os.Setenv("FOO", "bar")
	storeClient, err := env.NewEnvClient()
	if err != nil {
		t.Errorf(err.Error())
	}
	c := Config{
		ConfDir:     tempConfDir,
		ConfigDir:   filepath.Join(tempConfDir, "conf.d"),
		StoreClient: storeClient,
		TemplateDir: filepath.Join(tempConfDir, "templates"),
	}
	// Process the test template resource.
	err = Process(c)
	if err != nil {
		t.Error(err.Error())
	}
	// Verify the results.
	expected := "foo = bar"
	results, err := ioutil.ReadFile(destFile.Name())
	if err != nil {
		t.Error(err.Error())
	}
	if string(results) != expected {
		t.Errorf("Expected contents of dest == '%s', got %s", expected, string(results))
	}
}