Beispiel #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)
}
Beispiel #2
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)

	_, outPipeWriter := io.Pipe()
	errPipeReader, errPipeWriter := io.Pipe()
	cli := NewCLI(outPipeWriter, errPipeWriter)

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

	go func() {
		buf := bytes.NewBuffer(nil)
		for {
			_, err := buf.ReadFrom(errPipeReader)
			if err != nil {
				if err == io.EOF {
					errPipeReader.CloseWithError(io.EOF)
					return
				}
				t.Fatalf("Error in error reader: %s", err)
			}
			if buf.Len() > 0 {
				out.Write(buf.Bytes())
			}
			buf.Reset()
		}
	}()

	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)
}
Beispiel #3
0
func TestStart_runsCommandOnChange(t *testing.T) {
	t.Parallel()

	consul := testutil.NewTestServerConfig(t, func(c *testutil.TestServerConfig) {
		c.Stdout = ioutil.Discard
		c.Stderr = ioutil.Discard
	})
	consul.SetKV("foo/bar", []byte("one"))
	defer consul.Stop()

	config := testConfig(fmt.Sprintf(`
		consul = "%s"
		upcase = true

		prefix {
			path = "foo"
		}
	`, consul.HTTPAddr), t)

	f := test.CreateTempfile(nil, t)
	defer os.Remove(f.Name())
	os.Remove(f.Name())

	runner, err := NewRunner(config, []string{"sh", "-c", "echo $BAR > " + f.Name()}, true)
	if err != nil {
		t.Fatal(err)
	}

	runner.outStream, runner.errStream = ioutil.Discard, ioutil.Discard

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

	test.WaitForFileContents(f.Name(), []byte("one\n"), t)
}
func TestRunner_execReload(t *testing.T) {
	t.Parallel()

	consul := testutil.NewTestServerConfig(t, func(c *testutil.TestServerConfig) {
		c.Stdout = ioutil.Discard
		c.Stderr = ioutil.Discard
	})
	defer consul.Stop()

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

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

	// Create a tiny bash script for us to run as a "program"
	script := test.CreateTempfile([]byte(strings.TrimSpace(fmt.Sprintf(`
#!/usr/bin/env bash
trap "echo 'one' >> %s" SIGUSR1
trap "echo 'two' >> %s" SIGUSR2

while true; do
	: # Hang
done
	`, out.Name(), out.Name()))), t)
	if err := os.Chmod(script.Name(), 0700); err != nil {
		t.Fatal(err)
	}
	defer test.DeleteTempfile(script, t)

	config := testConfig(fmt.Sprintf(`
		consul = "%s"

		template {
			source = "%s"
		}

		exec {
			command       = "%s"
			reload_signal = "sigusr1"
			kill_signal   = "sigusr2"

			# We used SIGUSR2 to check, so there's force-kill shortly to make the
			# test faster.
			kill_timeout  = "10ms"
		}
	`, consul.HTTPAddr, tmpl.Name(), script.Name()), t)

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

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

	doneCh := make(chan struct{}, 1)
	go func() {
		for {
			if runner.child != nil {
				close(doneCh)
				return
			}
			time.Sleep(50 * time.Millisecond)
		}
	}()

	select {
	case err := <-runner.ErrCh:
		t.Fatal(err)
	case <-doneCh:
		// Childprocess is started, we can send it signals now
	case <-time.After(2 * time.Second):
		t.Fatal("child process should have started")
	}

	// Grab the current child pid - this will help us confirm the child was not
	// restarted on template change.
	opid := runner.child.Pid()

	// Change a dependent value in Consul, which will force the runner to cycle.
	consul.SetKV("foo", []byte("bar"))

	// Check that the reload signal was sent.
	test.WaitForFileContents(out.Name(), []byte("one\n"), t)

	npid := runner.child.Pid()
	if opid != npid {
		t.Errorf("expected %d to be the same as %d", opid, npid)
	}

	// Kill the child to check that the kill signal is properly sent.
	runner.child.Stop()

	test.WaitForFileContents(out.Name(), []byte("one\ntwo\n"), t)
}