Esempio n. 1
0
func TestReload_sighup(t *testing.T) {
	template := test.CreateTempfile([]byte("initial value"), t)
	defer test.DeleteTempfile(template, t)

	out := test.CreateTempfile(nil, t)
	defer test.DeleteTempfile(out, t)

	outStream := gatedio.NewByteBuffer()
	cli := NewCLI(outStream, outStream)

	command := fmt.Sprintf("consul-template -template %s:%s", template.Name(), out.Name())
	args := strings.Split(command, " ")

	go func(args []string) {
		if exit := cli.Run(args); exit != 0 {
			t.Fatalf("bad exit code: %d", exit)
		}
	}(args)
	defer cli.stop()

	// Ensure we have run at least once
	test.WaitForFileContents(out.Name(), []byte("initial value"), t)

	newValue := []byte("new value")
	ioutil.WriteFile(template.Name(), newValue, 0644)
	syscall.Kill(syscall.Getpid(), syscall.SIGHUP)

	test.WaitForFileContents(out.Name(), []byte("new value"), t)
}
Esempio n. 2
0
func TestRunner_onceAlreadyRenderedDoesNotHangOrRunCommands(t *testing.T) {
	outFile := test.CreateTempfile(nil, t)
	os.Remove(outFile.Name())
	defer os.Remove(outFile.Name())

	out := test.CreateTempfile([]byte("redis"), t)
	defer os.Remove(out.Name())

	in := test.CreateTempfile([]byte(`{{ key "service_name"}}`), t)
	defer test.DeleteTempfile(in, t)

	outTemplateA := test.CreateTempfile(nil, t)
	defer test.DeleteTempfile(outTemplateA, t)

	config := DefaultConfig()
	config.Merge(&Config{
		ConfigTemplates: []*ConfigTemplate{
			&ConfigTemplate{
				Source:      in.Name(),
				Destination: out.Name(),
				Command:     fmt.Sprintf("echo 'foo' >> %s", outFile.Name()),
			},
		},
	})

	runner, err := NewRunner(config, false, true, &sync.RWMutex{})
	if err != nil {
		t.Fatal(err)
	}

	d, err := dep.ParseStoreKey("service_name")
	if err != nil {
		t.Fatal(err)
	}
	data := "redis"
	runner.dependencies[d.HashCode()] = d
	runner.watcher.ForceWatching(d, true)
	runner.Receive(d, data)

	go runner.Start()

	select {
	case err := <-runner.ErrCh:
		t.Fatal(err)
	case <-runner.DoneCh:
	case <-time.After(5 * time.Millisecond):
		t.Fatal("runner should have stopped")
		runner.Stop()
	}

	_, err = os.Stat(outFile.Name())
	if err == nil {
		t.Fatal("expected command to not be run")
	}
	if !os.IsNotExist(err) {
		t.Fatal(err)
	}
}
Esempio n. 3
0
func TestRun_executesCommand(t *testing.T) {
	outFile := test.CreateTempfile(nil, t)
	os.Remove(outFile.Name())
	defer os.Remove(outFile.Name())

	inTemplate := test.CreateTempfile([]byte(`
    {{ range service "consul@nyc1"}}{{ end }}
  `), t)
	defer test.DeleteTempfile(inTemplate, t)

	outTemplate := test.CreateTempfile(nil, t)
	defer test.DeleteTempfile(outTemplate, t)

	config := DefaultConfig()
	config.Merge(&Config{
		ConfigTemplates: []*ConfigTemplate{
			&ConfigTemplate{
				Source:      inTemplate.Name(),
				Destination: outTemplate.Name(),
				Command:     fmt.Sprintf("echo 'foo' > %s", outFile.Name()),
			},
		},
	})

	runner, err := NewRunner(config, false, false, &sync.RWMutex{})
	if err != nil {
		t.Fatal(err)
	}

	d, err := dep.ParseHealthServices("consul@nyc1")
	if err != nil {
		t.Fatal(err)
	}
	data := []*dep.HealthService{
		&dep.HealthService{
			Node:    "consul",
			Address: "1.2.3.4",
			ID:      "consul@nyc1",
			Name:    "consul",
		},
	}
	runner.dependencies[d.HashCode()] = d
	runner.watcher.ForceWatching(d, true)
	runner.Receive(d, data)

	if err := runner.Run(); err != nil {
		t.Fatal(err)
	}

	_, err = os.Stat(outFile.Name())
	if err != nil {
		t.Fatal(err)
	}
}
Esempio n. 4
0
func TestRender_sameContentsDoesNotExecuteCommand(t *testing.T) {
	outFile := test.CreateTempfile(nil, t)
	os.Remove(outFile.Name())
	defer os.Remove(outFile.Name())

	inTemplate := test.CreateTempfile([]byte(`
    {{ range service "consul@nyc1" }}{{.Node}}{{ end }}
  `), t)
	defer test.DeleteTempfile(inTemplate, t)

	outTemplate := test.CreateTempfile([]byte(`
    consul1consul2
  `), t)
	defer test.DeleteTempfile(outTemplate, t)

	config := DefaultConfig()
	config.Merge(&Config{
		ConfigTemplates: []*ConfigTemplate{
			&ConfigTemplate{
				Source:      inTemplate.Name(),
				Destination: outTemplate.Name(),
				Command:     fmt.Sprintf("echo 'foo' > %s", outFile.Name()),
			},
		},
	})

	runner, err := NewRunner(config, false, false, &sync.RWMutex{})
	if err != nil {
		t.Fatal(err)
	}

	d, err := dep.ParseHealthServices("consul@nyc1")
	if err != nil {
		t.Fatal(err)
	}
	data := []*dep.HealthService{
		&dep.HealthService{Node: "consul1"},
		&dep.HealthService{Node: "consul2"},
	}
	runner.Receive(d, data)

	if err := runner.Run(); err != nil {
		t.Fatal(err)
	}

	_, err = os.Stat(outFile.Name())
	if !os.IsNotExist(err) {
		t.Fatalf("expected command to not be run")
	}
}
Esempio n. 5
0
// Warning: this is a super fragile and time-dependent test. If it's failing,
// check the demo Consul cluster and your own sanity before you assume your
// code broke something...
func TestRunner_quiescence(t *testing.T) {
	consul := testutil.NewTestServerConfig(t, func(c *testutil.TestServerConfig) {
		c.Stdout = ioutil.Discard
		c.Stderr = ioutil.Discard
	})
	defer consul.Stop()

	in := test.CreateTempfile([]byte(`
    {{ range service "consul" "any" }}{{.Node}}{{ end }}
  `), t)
	defer test.DeleteTempfile(in, t)

	out := test.CreateTempfile(nil, t)
	test.DeleteTempfile(out, t)

	config := testConfig(fmt.Sprintf(`
		consul = "%s"
		wait = "50ms:200ms"

		template {
			source = "%s"
			destination = "%s"
		}
	`, consul.HTTPAddr, in.Name(), out.Name()), t)

	runner, err := NewRunner(config, false, false, &sync.RWMutex{})
	if err != nil {
		t.Fatal(err)
	}

	go runner.Start()
	defer runner.Stop()

	min := time.After(10 * time.Millisecond)
	max := time.After(500 * time.Millisecond)
	for {
		select {
		case <-min:
			if _, err = os.Stat(out.Name()); !os.IsNotExist(err) {
				t.Errorf("expected quiescence timer to not fire for yet")
			}
			continue
		case <-max:
			if _, err = os.Stat(out.Name()); os.IsNotExist(err) {
				t.Errorf("expected template to be rendered by now")
			}
			return
		}
	}
}
Esempio n. 6
0
func TestRun_singlePass(t *testing.T) {
	in := test.CreateTempfile([]byte(`
    {{ range service "consul@nyc1"}}{{ end }}
    {{ range service "consul@nyc2"}}{{ end }}
    {{ range service "consul@nyc3"}}{{ end }}
  `), t)
	defer test.DeleteTempfile(in, t)

	config := DefaultConfig()
	config.Merge(&Config{
		ConfigTemplates: []*ConfigTemplate{
			&ConfigTemplate{Source: in.Name()},
		},
	})

	runner, err := NewRunner(config, true, false, &sync.RWMutex{})
	if err != nil {
		t.Fatal(err)
	}

	if len(runner.dependencies) != 0 {
		t.Errorf("expected %d to be %d", len(runner.dependencies), 0)
	}

	if err := runner.Run(); err != nil {
		t.Fatal(err)
	}

	if len(runner.dependencies) != 3 {
		t.Errorf("expected %d to be %d", len(runner.dependencies), 3)
	}
}
Esempio n. 7
0
func TestExecte_badFuncs(t *testing.T) {
	in := test.CreateTempfile([]byte(`{{ tickle_me_pink }}`), t)
	defer test.DeleteTempfile(in, t)

	tmpl, err := NewTemplate(in.Name())
	if err != nil {
		t.Fatal(err)
	}

	brain := NewBrain()
	used, missing, result, err := tmpl.Execute(brain)
	if err == nil {
		t.Fatal("expected error, but nothing was returned")
	}

	expected := `function "tickle_me_pink" not defined`
	if !strings.Contains(err.Error(), expected) {
		t.Errorf("expected %q to contain %q", err.Error(), expected)
	}

	if used != nil {
		t.Errorf("expected used to be nil")
	}

	if missing != nil {
		t.Errorf("expected missing to be nil")
	}

	if result != nil {
		t.Errorf("expected result to be nil")
	}
}
Esempio n. 8
0
func TestRun_noopIfMissingData(t *testing.T) {
	in := test.CreateTempfile([]byte(`
    {{ range service "consul@nyc1" }}{{ end }}
  `), t)
	defer test.DeleteTempfile(in, t)

	config := DefaultConfig()
	config.Merge(&Config{
		ConfigTemplates: []*ConfigTemplate{
			&ConfigTemplate{Source: in.Name()},
		},
	})

	runner, err := NewRunner(config, false, false, &sync.RWMutex{})
	if err != nil {
		t.Fatal(err)
	}

	buff := gatedio.NewByteBuffer()
	runner.outStream, runner.errStream = buff, buff

	if err := runner.Run(); err != nil {
		t.Fatal(err)
	}

	if num := len(buff.Bytes()); num != 0 {
		t.Errorf("expected %d to be %d", num, 0)
	}
}
Esempio n. 9
0
func TestExecute_timeout(t *testing.T) {
	tmpfile := test.CreateTempfile(nil, t)
	defer test.DeleteTempfile(tmpfile, t)

	config := testConfig(`
		consul = "1.2.3.4:5678"
		token = "abcd1234"

		auth {
			username = "******"
			password = "******"
		}

		ssl {
			enabled = true
			verify = false
		}
	`, t)

	runner, err := NewRunner(config, false, false, &sync.RWMutex{})
	if err != nil {
		t.Fatal(err)
	}

	err = runner.execute("sleep 10", 100*time.Millisecond)
	if err == nil {
		t.Fatal("expected error, but nothing was returned")
	}

	expected := "did not return for 100ms"
	if !strings.Contains(err.Error(), expected) {
		t.Errorf("expected %q to include %q", err.Error(), expected)
	}
}
Esempio n. 10
0
func TestDedup_IsLeader(t *testing.T) {
	t.Parallel()

	// Create a template
	in := test.CreateTempfile([]byte(`
    {{ range service "consul" }}{{.Node}}{{ end }}
  `), t)
	defer test.DeleteTempfile(in, t)
	tmpl, err := NewTemplate(in.Name())
	if err != nil {
		t.Fatalf("err: %v", err)
	}

	consul, dedup := testDedupManager(t, []*Template{tmpl})
	defer consul.Stop()

	// Start dedup
	if err := dedup.Start(); err != nil {
		t.Fatalf("err: %v", err)
	}
	defer dedup.Stop()

	// Wait until we are leader
	select {
	case <-dedup.UpdateCh():
	case <-time.After(2 * time.Second):
		t.Fatalf("timeout")
	}

	// Check that we are the leader
	if !dedup.IsLeader(tmpl) {
		t.Fatalf("should be leader")
	}
}
Esempio n. 11
0
func TestExecute_funcs(t *testing.T) {
	in := test.CreateTempfile([]byte(`
    {{ range service "release.webapp" }}{{.Address}}{{ end }}
    {{ key "service/redis/maxconns" }}
    {{ range ls "service/redis/config" }}{{.Key}}{{ end }}
  `), t)
	defer test.DeleteTempfile(in, t)

	tmpl, err := NewTemplate(in.Name())
	if err != nil {
		t.Fatal(err)
	}

	brain := NewBrain()
	used, missing, _, err := tmpl.Execute(brain)
	if err != nil {
		t.Fatal(err)
	}

	if num := len(missing); num != 3 {
		t.Fatalf("expected 3 missing, got: %d", num)
	}

	if num := len(used); num != 3 {
		t.Fatalf("expected 3 used, got: %d", num)
	}
}
Esempio n. 12
0
func TestExecute_duplicateFuncs(t *testing.T) {
	in := test.CreateTempfile([]byte(`
    {{ key "service/redis/maxconns" }}
    {{ key "service/redis/maxconns" }}
    {{ key "service/redis/maxconns" }}
  `), t)
	defer test.DeleteTempfile(in, t)

	tmpl, err := NewTemplate(in.Name())
	if err != nil {
		t.Fatal(err)
	}

	brain := NewBrain()
	used, missing, _, err := tmpl.Execute(brain)
	if err != nil {
		t.Fatal(err)
	}

	if num := len(missing); num != 1 {
		t.Fatalf("expected 1 missing, got: %d", num)
	}

	if num := len(used); num != 1 {
		t.Fatalf("expected 1 used, got: %d", num)
	}
}
Esempio n. 13
0
func TestFileFetch_waits(t *testing.T) {
	data := `{"foo":"bar"}`
	inTemplate := test.CreateTempfile([]byte(data), t)
	defer test.DeleteTempfile(inTemplate, t)

	dep := &File{
		rawKey: inTemplate.Name(),
	}

	_, _, err := dep.Fetch(nil, nil)
	if err != nil {
		t.Fatal(err)
	}

	doneCh := make(chan struct{})
	errCh := make(chan error)
	go func() {
		if _, _, err := dep.Fetch(nil, nil); err != nil {
			errCh <- err
			return
		}
		close(doneCh)
	}()

	select {
	case err := <-errCh:
		t.Fatal(err)
	case <-doneCh:
		t.Fatal("received data, but should not have")
	case <-time.After(1000 * time.Nanosecond):
		return
	}
}
Esempio n. 14
0
func TestExecute_noDependencies(t *testing.T) {
	contents := []byte("This is a template with just text")

	in := test.CreateTempfile(contents, t)
	defer test.DeleteTempfile(in, t)

	tmpl, err := NewTemplate(in.Name())
	if err != nil {
		t.Fatal(err)
	}

	brain := NewBrain()
	used, missing, result, err := tmpl.Execute(brain)
	if err != nil {
		t.Fatal(err)
	}

	if num := len(used); num != 0 {
		t.Errorf("expected 0 missing, got: %d", num)
	}

	if num := len(missing); num != 0 {
		t.Errorf("expected 0 missing, got: %d", num)
	}

	if !bytes.Equal(result, contents) {
		t.Errorf("expected %q to be %q", result, contents)
	}
}
Esempio n. 15
0
func TestRun_doublePass(t *testing.T) {
	in := test.CreateTempfile([]byte(`
		{{ range ls "services" }}
			{{ range service .Key }}
				{{.Node}} {{.Address}}:{{.Port}}
			{{ end }}
		{{ end }}
  `), t)
	defer test.DeleteTempfile(in, t)

	config := DefaultConfig()
	config.Merge(&Config{
		ConfigTemplates: []*ConfigTemplate{
			&ConfigTemplate{Source: in.Name()},
		},
	})

	runner, err := NewRunner(config, true, false, &sync.RWMutex{})
	if err != nil {
		t.Fatal(err)
	}

	if len(runner.dependencies) != 0 {
		t.Errorf("expected %d to be %d", len(runner.dependencies), 0)
	}

	if err := runner.Run(); err != nil {
		t.Fatal(err)
	}

	if len(runner.dependencies) != 1 {
		t.Errorf("expected %d to be %d", len(runner.dependencies), 1)
	}

	d, err := dep.ParseStoreKeyPrefix("services")
	if err != nil {
		t.Fatal(err)
	}
	data := []*dep.KeyPair{
		&dep.KeyPair{Key: "service1"},
		&dep.KeyPair{Key: "service2"},
		&dep.KeyPair{Key: "service3"},
	}
	runner.Receive(d, data)

	if err := runner.Run(); err != nil {
		t.Fatal(err)
	}

	if len(runner.dependencies) != 4 {
		t.Errorf("expected %d to be %d", len(runner.dependencies), 4)
	}
}
Esempio n. 16
0
func TestRun_onceFlag(t *testing.T) {
	consul := testutil.NewTestServerConfig(t, func(c *testutil.TestServerConfig) {
		c.Stdout = ioutil.Discard
		c.Stderr = ioutil.Discard
	})
	defer consul.Stop()

	consul.SetKV("foo", []byte("bar"))

	template := test.CreateTempfile([]byte(`
	{{key "foo"}}
  `), t)
	defer test.DeleteTempfile(template, t)

	out := test.CreateTempfile(nil, t)
	defer test.DeleteTempfile(out, t)

	outStream := gatedio.NewByteBuffer()
	cli := NewCLI(outStream, outStream)

	command := fmt.Sprintf("consul-template -consul %s -template %s:%s -once -log-level debug",
		consul.HTTPAddr, template.Name(), out.Name())
	args := strings.Split(command, " ")

	ch := make(chan int, 1)
	go func() {
		ch <- cli.Run(args)
	}()

	select {
	case status := <-ch:
		if status != ExitCodeOK {
			t.Errorf("expected %d to eq %d", status, ExitCodeOK)
			t.Errorf("out: %s", outStream.String())
		}
	case <-time.After(500 * time.Millisecond):
		t.Errorf("expected exit, did not exit after 500ms")
		t.Errorf("out: %s", outStream.String())
	}
}
Esempio n. 17
0
func TestRun_doesNotExecuteCommandMissingDependencies(t *testing.T) {
	outFile := test.CreateTempfile(nil, t)
	os.Remove(outFile.Name())
	defer os.Remove(outFile.Name())

	inTemplate := test.CreateTempfile([]byte(`
    {{ range service "consul@nyc1"}}{{ end }}
  `), t)
	defer test.DeleteTempfile(inTemplate, t)

	outTemplate := test.CreateTempfile(nil, t)
	defer test.DeleteTempfile(outTemplate, t)

	config := DefaultConfig()
	config.Merge(&Config{
		ConfigTemplates: []*ConfigTemplate{
			&ConfigTemplate{
				Source:      inTemplate.Name(),
				Destination: outTemplate.Name(),
				Command:     fmt.Sprintf("echo 'foo' > %s", outFile.Name()),
			},
		},
	})

	runner, err := NewRunner(config, false, false, &sync.RWMutex{})
	if err != nil {
		t.Fatal(err)
	}

	if err := runner.Run(); err != nil {
		t.Fatal(err)
	}

	_, err = os.Stat(outFile.Name())
	if !os.IsNotExist(err) {
		t.Fatalf("expected command to not be run")
	}
}
Esempio n. 18
0
func TestRun_dry(t *testing.T) {
	in := test.CreateTempfile([]byte(`
    {{ range service "consul@nyc1" }}{{.Node}}{{ end }}
  `), t)
	defer test.DeleteTempfile(in, t)

	config := DefaultConfig()
	config.Merge(&Config{
		ConfigTemplates: []*ConfigTemplate{
			&ConfigTemplate{
				Source:      in.Name(),
				Destination: "/out/file.txt",
			},
		},
	})

	runner, err := NewRunner(config, true, false, &sync.RWMutex{})
	if err != nil {
		t.Fatal(err)
	}

	d, err := dep.ParseHealthServices("consul@nyc1")
	if err != nil {
		t.Fatal(err)
	}
	data := []*dep.HealthService{
		&dep.HealthService{Node: "consul1"},
		&dep.HealthService{Node: "consul2"},
	}
	runner.dependencies[d.HashCode()] = d
	runner.watcher.ForceWatching(d, true)
	runner.Receive(d, data)

	buff := gatedio.NewByteBuffer()
	runner.outStream, runner.errStream = buff, buff

	if err := runner.Run(); err != nil {
		t.Fatal(err)
	}

	actual := bytes.TrimSpace(buff.Bytes())
	expected := bytes.TrimSpace([]byte(`
    > /out/file.txt

    consul1consul2
  `))
	if !bytes.Equal(actual, expected) {
		t.Errorf("expected \n%q\n to equal \n%q\n", actual, expected)
	}
}
Esempio n. 19
0
func TestConfigFromPath_singleFile(t *testing.T) {
	configFile := test.CreateTempfile([]byte(`
		consul = "127.0.0.1"
	`), t)
	defer test.DeleteTempfile(configFile, t)

	config, err := ConfigFromPath(configFile.Name())
	if err != nil {
		t.Fatal(err)
	}

	expected := "127.0.0.1"
	if config.Consul != expected {
		t.Errorf("expected %q to be %q", config.Consul, expected)
	}
}
Esempio n. 20
0
func TestParseConfig_parseWaitError(t *testing.T) {
	configFile := test.CreateTempfile([]byte(`
    wait = "not_valid:duration"
  `), t)
	defer test.DeleteTempfile(configFile, t)

	_, err := ParseConfig(configFile.Name())
	if err == nil {
		t.Fatal("expected error, but nothing was returned")
	}

	expectedErr := "time: invalid duration"
	if !strings.Contains(err.Error(), expectedErr) {
		t.Fatalf("expected error %q to contain %q", err.Error(), expectedErr)
	}
}
Esempio n. 21
0
func TestParseConfig_mapstructureError(t *testing.T) {
	configFile := test.CreateTempfile([]byte(`
    consul = true
  `), t)
	defer test.DeleteTempfile(configFile, t)

	_, err := ParseConfig(configFile.Name())
	if err == nil {
		t.Fatal("expected error, but nothing was returned")
	}

	expectedErr := "unconvertible type 'bool'"
	if !strings.Contains(err.Error(), expectedErr) {
		t.Fatalf("expected error %q to contain %q", err.Error(), expectedErr)
	}
}
Esempio n. 22
0
func TestExecute_missingDependencies(t *testing.T) {
	contents := []byte(`{{key "foo"}}`)

	in := test.CreateTempfile(contents, t)
	defer test.DeleteTempfile(in, t)

	tmpl, err := NewTemplate(in.Name())
	if err != nil {
		t.Fatal(err)
	}

	brain := NewBrain()
	used, missing, result, err := tmpl.Execute(brain)
	if err != nil {
		t.Fatal(err)
	}

	if num := len(used); num != 1 {
		t.Fatalf("expected 1 used, got: %d", num)
	}

	if num := len(missing); num != 1 {
		t.Fatalf("expected 1 missing, got: %d", num)
	}

	expected, err := dep.ParseStoreKey("foo")
	if err != nil {
		t.Fatal(err)
	}
	if !reflect.DeepEqual(missing[0], expected) {
		t.Errorf("expected %v to be %v", missing[0], expected)
	}

	if num := len(used); num != 1 {
		t.Fatalf("expected 1 used, got %d", num)
	}

	if !reflect.DeepEqual(used[0], expected) {
		t.Errorf("expected %v to be %v", used[0], expected)
	}

	expectedResult := []byte("")
	if !bytes.Equal(result, expectedResult) {
		t.Errorf("expected %q to be %q", result, expectedResult)
	}
}
Esempio n. 23
0
func TestParseConfig_extraKeys(t *testing.T) {
	configFile := test.CreateTempfile([]byte(`
		fake_key = "nope"
		another_fake_key = "never"
	`), t)
	defer test.DeleteTempfile(configFile, t)

	_, err := ParseConfig(configFile.Name())
	if err == nil {
		t.Fatal("expected error")
	}

	expected := "invalid keys: another_fake_key, fake_key"
	if !strings.Contains(err.Error(), expected) {
		t.Errorf("expected %q to be %q", err.Error(), expected)
	}
}
Esempio n. 24
0
func TestFileFetch(t *testing.T) {
	data := `{"foo":"bar"}`
	inTemplate := test.CreateTempfile([]byte(data), t)
	defer test.DeleteTempfile(inTemplate, t)

	dep := &File{
		rawKey: inTemplate.Name(),
	}

	read, _, err := dep.Fetch(nil, nil)
	if err != nil {
		t.Fatal(err)
	}

	if read != data {
		t.Fatalf("expected %q to be %q", read, data)
	}
}
Esempio n. 25
0
func TestDedup_UpdateDeps(t *testing.T) {
	t.Parallel()

	// Create a template
	in := test.CreateTempfile([]byte(`
    {{ range service "consul" }}{{.Node}}{{ end }}
  `), t)
	defer test.DeleteTempfile(in, t)
	tmpl, err := NewTemplate(in.Name())
	if err != nil {
		t.Fatalf("err: %v", err)
	}

	consul, dedup := testDedupManager(t, []*Template{tmpl})
	defer consul.Stop()

	// Start dedup
	if err := dedup.Start(); err != nil {
		t.Fatalf("err: %v", err)
	}
	defer dedup.Stop()

	// Wait until we are leader
	select {
	case <-dedup.UpdateCh():
	case <-time.After(2 * time.Second):
		t.Fatalf("timeout")
	}

	// Create the dependency
	dep, err := dependency.ParseHealthServices("consul")
	if err != nil {
		t.Fatalf("err: %v", err)
	}

	// Inject data into the brain
	dedup.brain.Remember(dep, 123)

	// Update the dependencies
	err = dedup.UpdateDeps(tmpl, []dependency.Dependency{dep})
	if err != nil {
		t.Fatalf("err: %v", err)
	}
}
Esempio n. 26
0
func TestNewTemplate_setsPathAndContents(t *testing.T) {
	contents := []byte("some content")

	in := test.CreateTempfile(contents, t)
	defer test.DeleteTempfile(in, t)

	tmpl, err := NewTemplate(in.Name())
	if err != nil {
		t.Fatal(err)
	}

	if tmpl.Path != in.Name() {
		t.Errorf("expected %q to be %q", tmpl.Path, in.Name())
	}

	if tmpl.contents != string(contents) {
		t.Errorf("expected %q to be %q", tmpl.contents, string(contents))
	}
}
Esempio n. 27
0
func TestNewTemplate_setsPathAndMD5(t *testing.T) {
	contents := []byte("some content")

	in := test.CreateTempfile(contents, t)
	defer test.DeleteTempfile(in, t)

	tmpl, err := NewTemplate(in.Name())
	if err != nil {
		t.Fatal(err)
	}

	if tmpl.Path != in.Name() {
		t.Errorf("expected %q to be %q", tmpl.Path, in.Name())
	}

	expect := "9893532233caff98cd083a116b013c0b"
	if tmpl.hexMD5 != expect {
		t.Errorf("expected %q to be %q", tmpl.hexMD5, expect)
	}
}
Esempio n. 28
0
func TestRun_removesUnusedDependencies(t *testing.T) {
	in := test.CreateTempfile([]byte(nil), t)
	defer test.DeleteTempfile(in, t)

	config := DefaultConfig()
	config.Merge(&Config{
		ConfigTemplates: []*ConfigTemplate{
			&ConfigTemplate{Source: in.Name()},
		},
	})

	runner, err := NewRunner(config, true, false, &sync.RWMutex{})
	if err != nil {
		t.Fatal(err)
	}

	d, err := dep.ParseHealthServices("consul@nyc2")
	if err != nil {
		t.Fatal(err)
	}

	runner.dependencies = map[string]dep.Dependency{"consul@nyc2": d}

	if err := runner.Run(); err != nil {
		t.Fatal(err)
	}

	if len(runner.dependencies) != 0 {
		t.Errorf("expected %d to be %d", len(runner.dependencies), 0)
	}

	if runner.watcher.Watching(d) {
		t.Errorf("expected watcher to stop watching dependency")
	}

	if _, ok := runner.brain.Recall(d); ok {
		t.Errorf("expected brain to forget dependency")
	}
}
Esempio n. 29
0
func TestFileFetch_firesChanges(t *testing.T) {
	data := `{"foo":"bar"}`
	inTemplate := test.CreateTempfile([]byte(data), t)
	defer test.DeleteTempfile(inTemplate, t)

	dep := &File{
		rawKey: inTemplate.Name(),
	}

	_, _, err := dep.Fetch(nil, nil)
	if err != nil {
		t.Fatal(err)
	}

	dataCh := make(chan interface{})
	errCh := make(chan error)
	go func() {
		data, _, err := dep.Fetch(nil, nil)
		if err != nil {
			errCh <- err
			return
		}
		dataCh <- data
	}()

	newData := `{"bar": "baz"}`
	ioutil.WriteFile(inTemplate.Name(), []byte(newData), 0644)

	select {
	case d := <-dataCh:
		if d != newData {
			t.Fatalf("expected %q to be %q", d, newData)
		}
	case <-time.After(5 * time.Second):
		t.Fatal("did not receive data from file changes")
	}
}
Esempio n. 30
0
func TestExecute_multipass(t *testing.T) {
	in := test.CreateTempfile([]byte(`
		{{ range ls "services" }}{{.Key}}:{{ range service .Key }}
			{{.Node}} {{.Address}}:{{.Port}}{{ end }}
		{{ end }}
	`), t)
	defer test.DeleteTempfile(in, t)

	tmpl, err := NewTemplate(in.Name())
	if err != nil {
		t.Fatal(err)
	}

	brain := NewBrain()

	used, missing, result, err := tmpl.Execute(brain)
	if err != nil {
		t.Fatal(err)
	}

	if num := len(missing); num != 1 {
		t.Errorf("expected 1 missing, got: %d", num)
	}

	if num := len(used); num != 1 {
		t.Errorf("expected 1 used, got: %d", num)
	}

	expected := bytes.TrimSpace([]byte(""))
	result = bytes.TrimSpace(result)
	if !bytes.Equal(result, expected) {
		t.Errorf("expected %q to be %q", result, expected)
	}

	// Receive data for the key prefix dependency
	d1, err := dep.ParseStoreKeyPrefix("services")
	brain.Remember(d1, []*dep.KeyPair{
		&dep.KeyPair{Key: "webapp", Value: "1"},
		&dep.KeyPair{Key: "database", Value: "1"},
	})

	used, missing, result, err = tmpl.Execute(brain)
	if err != nil {
		t.Fatal(err)
	}

	if num := len(missing); num != 2 {
		t.Errorf("expected 2 missing, got: %d", num)
	}

	if num := len(used); num != 3 {
		t.Errorf("expected 3 used, got: %d", num)
	}

	expected = bytes.TrimSpace([]byte(`
		webapp:
		database:
	`))
	result = bytes.TrimSpace(result)
	if !bytes.Equal(result, expected) {
		t.Errorf("expected \n%q\n to be \n%q\n", result, expected)
	}

	// Receive data for the services
	d2, err := dep.ParseHealthServices("webapp")
	brain.Remember(d2, []*dep.HealthService{
		&dep.HealthService{Node: "web01", Address: "1.2.3.4", Port: 1234},
	})

	d3, err := dep.ParseHealthServices("database")
	brain.Remember(d3, []*dep.HealthService{
		&dep.HealthService{Node: "db01", Address: "5.6.7.8", Port: 5678},
	})

	used, missing, result, err = tmpl.Execute(brain)
	if err != nil {
		t.Fatal(err)
	}

	if num := len(missing); num != 0 {
		t.Errorf("expected 0 missing, got: %d", num)
	}

	if num := len(used); num != 3 {
		t.Errorf("expected 3 used, got: %d", num)
	}

	expected = bytes.TrimSpace([]byte(`
		webapp:
			web01 1.2.3.4:1234
		database:
			db01 5.6.7.8:5678
	`))
	result = bytes.TrimSpace(result)
	if !bytes.Equal(result, expected) {
		t.Errorf("expected \n%q\n to be \n%q\n", result, expected)
	}
}