Exemple #1
0
// Tests the Start command.
func TestStart(t *testing.T) {
	ctx, tempDir := NewTestContext(t)
	defer cleanTestDir(t, tempDir)

	const testPipeline = "test-start"
	const testBundle = "bazbux"
	createTestBundleAndPipeline(t, ctx, testPipeline, testBundle, tempDir)
	defer shell.RunAndLog("docker", "rmi", ctx.GetImage(testBundle))
	defer shell.RunAndLog("docker", "rmi", ctx.GetManagerImage())

	// set the interrupt handler to go off after 5 seconds
	go func() {
		time.Sleep(5 * time.Second)
		syscall.Kill(syscall.Getpid(), syscall.SIGINT)
	}()

	// send a post request to the "server" and see what we get back
	go func() {
		time.Sleep(4 * time.Second)
		hostIp, err := ctx.GetDockerHost()
		if err != nil {
			t.Errorf("TestStart: Got an error getting the docker host: '%v'", err)
		}
		resp, err := http.Post(fmt.Sprintf("http://%s:9800", hostIp), "application/json", bytes.NewBufferString(`{"a": "trusty"}`))
		if err != nil {
			t.Error(err)
		}
		buf := new(bytes.Buffer)
		buf.ReadFrom(resp.Body)
		result := buf.String()
		if result != `{"a": "trusty", "b": "echo trusty"}` {
			t.Errorf("TestStart: Got '%s'; did not get expected response", result)
		}
	}()

	// start the pipeline locally (set the gce project to '' to run
	// locally)
	err := ctx.Start(testPipeline, "")
	if err != nil {
		t.Errorf("TestStart: '%v'", err)
	}

	// now attempt to start it remotely
	const projectId = "gce-project-id"
	err = ctx.Start(testPipeline, projectId)
	if err != nil {
		t.Errorf("TestStart: [remote] '%v'", err)
	}
	remoteImage := fmt.Sprintf("gcr.io/%s/plumber-%s", projectId, "manager")
	defer shell.RunAndLog("docker", "rmi", remoteImage)
	remoteImage = fmt.Sprintf("gcr.io/%s/plumber-%s", projectId, testBundle)
	defer shell.RunAndLog("docker", "rmi", remoteImage)
}
Exemple #2
0
// Bundle stuff...
// BUG(echu): need to figure out how to handle conflicts in bundle names
func (ctx *Context) Bundle(bundlePath string) error {
	log.Printf("==> Creating bundle from '%s'", bundlePath)
	defer log.Printf("<== Bundling complete.")

	log.Printf(" |  Parsing bundle config.")
	bundleConfig, err := ParseBundleFromDir(bundlePath)
	if err != nil {
		return err
	}
	log.Printf("    %v", bundleConfig)

	log.Printf(" |  Making temp file for python wrapper")
	wrapper, err := ioutil.TempFile(bundlePath, "plumber")
	defer removeTempFile(wrapper)
	if err != nil {
		return err
	}
	log.Printf("    Created '%s'", wrapper.Name())

	templateCtx := templateContext{
		Wrapper: path.Base(wrapper.Name()),
		Plumber: bundleConfig,
	}

	log.Printf(" |  Writing wrapper.")
	tmpl, err := template.New("wrapper").Parse(wrapperTemplate)
	if err != nil {
		return err
	}
	if err := tmpl.Execute(wrapper, templateCtx); err != nil {
		return err
	}
	log.Printf("    Done.")

	log.Printf(" |  Making temp file for Dockerfile")
	dockerfile, err := ioutil.TempFile(bundlePath, "plumber")
	defer removeTempFile(dockerfile)
	if err != nil {
		return err
	}
	log.Printf("    Created '%s'", dockerfile.Name())

	log.Printf(" |  Writing Dockerfile.")
	tmpl, err = template.New("dockerfile").Parse(dockerfileTemplate)
	if err != nil {
		return err
	}
	if err := tmpl.Execute(dockerfile, templateCtx); err != nil {
		return err
	}
	log.Printf("    Done.")

	log.Printf(" |  Building container.")
	err = shell.RunAndLog(ctx.DockerCmd, "build", "--pull", "-t", ctx.GetImage(bundleConfig.Name), "-f", dockerfile.Name(), bundlePath)
	if err != nil {
		return err
	}
	log.Printf("    Container '%s' built.", ctx.GetImage(bundleConfig.Name))
	return nil
}
Exemple #3
0
func (ctx *Context) Create(name string) error {
	// creates a pipeline by initializing a git repo at ~/.plumb/<NAME>
	log.Printf("==> Creating '%s' pipeline", name)
	defer log.Printf("<== Creation complete.")

	if name == "" {
		return errors.New("Cannot create a pipeline with no name.")
	}

	log.Printf(" |  Making directory")
	// note that we use PipelinePath instead of GetPipeline here; this
	// is because we only need the path to create it
	path := ctx.PipelinePath(name)

	// if the path already exists, give an error
	if _, err := os.Stat(path); err == nil {
		return errors.New("Pipeline already exists.")
	}

	if err := os.MkdirAll(path, 0755); err != nil {
		return err
	}
	log.Printf("    Created pipeline directory at '%s'", path)

	log.Printf(" |  Initializing pipeline with git")
	if err := shell.RunAndLog("git", "init", path); err != nil {
		return err
	}
	log.Printf("    Done.")

	return nil
}
Exemple #4
0
func addOne(ctx *Context, pipeline string, bundle string) error {
	log.Printf(" |  Adding '%s' to '%s'.", bundle, pipeline)
	defer log.Printf("    Added '%s'.", bundle)

	path, err := ctx.GetPipeline(pipeline)
	if err != nil {
		return err
	}

	log.Printf(" |  Parsing bundle config.")
	bundleConfig, err := ParseBundleFromDir(bundle)
	if err != nil {
		return err
	}
	log.Printf("    Done.")

	log.Printf(" |  Copying `.plumber.yml` config to `%s.yml`.", bundleConfig.Name)
	config := fmt.Sprintf("%s/%s.yml", path, bundleConfig.Name)
	bytes, err := yaml.Marshal(&bundleConfig)
	if err != nil {
		return err
	}

	if err := ioutil.WriteFile(config, bytes, 0644); err != nil {
		return err
	}
	log.Printf("    Done.")

	log.Printf(" |  Adding `%s.yml` to version control.", bundleConfig.Name)

	if err := shell.RunAndLog("git", "-C", path, "add", config); err != nil {
		return err
	}

	message := fmt.Sprintf("Updated '%s' config.", bundleConfig.Name)
	if err := shell.RunAndLog("git", "-C", path, "commit", "-m", message, "--author", "\"Plumber Bot <*****@*****.**>\""); err != nil {
		return err
	}

	return nil
}
Exemple #5
0
func TestInterrupt(t *testing.T) {
	// set the interrupt handler to go off after 50 milliseconds
	go func() {
		time.Sleep(50 * time.Millisecond)
		syscall.Kill(syscall.Getpid(), syscall.SIGINT)
	}()

	err := shell.RunAndLog("/bin/bash", "-c", "while true; do true; done")
	if err == nil || err.Error() != "signal: interrupt" {
		t.Error("Should've received a SIGINT")
	}
}
Exemple #6
0
// this is a *functional test*
// we check that boostrap works by actually running the boostrap command
// and checking that the container is built and runs
func TestBootstrap(t *testing.T) {
	ctx, tempDir := NewTestContext(t)
	defer cleanTestDir(t, tempDir)

	// step 1. remove any image named plumber/test-manager from the current
	// set of docker images (ignore any errors)
	_ = shell.RunAndLog(ctx.DockerCmd, "rmi", ctx.GetManagerImage())

	// step 2. invoke Bootstrap for building ctx.GetManagerImage()
	if err := ctx.Bootstrap(); err != nil {
		t.Errorf("Bootstrap: Got an error during bootstrap: '%v'", err)
	}
	defer shell.RunAndLog(ctx.DockerCmd, "rmi", ctx.GetManagerImage())

	// step 3. run the image (it *should* just echo in response)
	if err := shell.RunAndLog(ctx.DockerCmd, "run", "-d", "-p", "9800:9800", "--name", "plumber-test", ctx.GetManagerImage()); err != nil {
		t.Errorf("Bootstrap: Got an error during docker run: '%v'", err)
	}
	defer shell.RunAndLog(ctx.DockerCmd, "rm", "-f", "plumber-test")
	// wait a bit for the container to come up
	time.Sleep(1 * time.Second)

	// step 4. send some JSON and check for echos
	hostIp, err := ctx.GetDockerHost()
	if err != nil {
		t.Errorf("Bootstrap: Got an error getting the docker host: '%v'", err)
	}

	// second, send over some JSON and verify result
	resp, err := http.Post(fmt.Sprintf("http://%s:9800", hostIp), "application/json", bytes.NewBufferString(`{"foo": 3}`))
	if err != nil {
		t.Error(err)
	}
	buf := new(bytes.Buffer)
	buf.ReadFrom(resp.Body)
	result := buf.String()
	if result != `{"foo": 3}` {
		t.Errorf("Bootstrap: Got '%s'; did not get expected response", result)
	}
}
Exemple #7
0
func (ctx *Context) Bootstrap() error {
	// use docker to compile the manager and copy the binary into
	// another docker container
	//
	// tag this new container
	log.Printf("==> Bootstraping plumb.")
	defer log.Printf("<== Bootstrap complete.")

	log.Printf(" |  Creating temp directory.")
	if err := os.MkdirAll(ctx.BootstrapDir, 0755); err != nil {
		return err
	}
	defer func() {
		if err := os.RemoveAll(ctx.BootstrapDir); err != nil {
			panic(err)
		}
	}()
	log.Printf("    Temp directory created at '%s'", ctx.BootstrapDir)

	log.Printf(" |  Writing manager source files.")
	if err := writeAsset("manager.go", ctx.BootstrapDir); err != nil {
		return err
	}
	if err := writeAsset("Dockerfile", ctx.BootstrapDir); err != nil {
		return err
	}
	if err := writeAsset("README.md", ctx.BootstrapDir); err != nil {
		return err
	}
	if err := writeAsset("manager_test.go", ctx.BootstrapDir); err != nil {
		return err
	}
	log.Printf("    Done")

	if err := shell.RunAndLog(ctx.DockerCmd,
		"run",
		"--rm",
		"-v",
		"/var/run/docker.sock:/var/run/docker.sock",
		"-v",
		fmt.Sprintf("%s:/src", ctx.BootstrapDir),
		"centurylink/golang-builder",
		ctx.GetManagerImage()); err != nil {
		return err
	}

	return nil
}
Exemple #8
0
func BenchmarkRunAndLog(b *testing.B) {
	log.SetOutput(ioutil.Discard)
	for i := 0; i < b.N; i++ {
		shell.RunAndLog("echo", "true")
	}
}
Exemple #9
0
func TestRunAndLogFails(t *testing.T) {
	err := shell.RunAndLog("-notlikely-to-be-a*-cmd")
	if err == nil {
		t.Error("Expected an error but never got one!")
	}
}
Exemple #10
0
func TestRunAndLog(t *testing.T) {
	err := shell.RunAndLog("true")
	if err != nil {
		t.Error(err)
	}
}