Пример #1
0
func TestBuilderBuildRequire(t *testing.T) {

	tempDir, err := ioutil.TempDir("/tmp", "rocker_TestBuilderBuildRequire_")
	if err != nil {
		t.Fatal(err)
	}
	defer os.RemoveAll(tempDir)

	err = test.MakeFiles(tempDir, map[string]string{
		"/Rockerfile": `FROM busybox:buildroot-2013.08.1
REQUIRE version
RUN echo "$version" > /testing
CMD cat /testing`,
	})

	// we will need docker client to cleanup and do some cross-checks
	client, err := dockerclient.New()
	if err != nil {
		t.Fatal(err)
	}

	run := func(vars []string) (string, error) {
		tlpVars, err := template.VarsFromStrings(vars)
		if err != nil {
			return "", err
		}

		builder := &Builder{
			Rockerfile: tempDir + "/Rockerfile",
			OutStream:  util.PrefixPipe("[TEST] ", os.Stdout),
			Docker:     client,
			Vars:       tlpVars,
		}

		imageID, err := builder.Build()
		if err != nil {
			return "", err
		}
		t.Logf("Got imageID: %s", imageID)

		defer func() {
			if err := client.RemoveImageExtended(imageID, docker.RemoveImageOptions{Force: true}); err != nil {
				t.Log(err)
			}
		}()

		return runContainer(t, client, &docker.Config{
			Image: imageID,
		}, nil)
	}

	_, err1 := run([]string{})
	result, err2 := run([]string{"version=123"})

	assert.Equal(t, "Var $version is required but not set", err1.Error())
	assert.Nil(t, err2, "expected second run to not give error")
	assert.Equal(t, "123\n", result)
}
Пример #2
0
func TestBuilderBuildVars(t *testing.T) {

	tempDir, err := ioutil.TempDir("/tmp", "rocker_TestBuilderBuildVars_")
	if err != nil {
		t.Fatal(err)
	}
	defer os.RemoveAll(tempDir)

	err = test.MakeFiles(tempDir, map[string]string{
		"/Rockerfile": `FROM busybox:buildroot-2013.08.1
RUN echo "version:$version" > /version`,
	})

	// we will need docker client to cleanup and do some cross-checks
	client, err := dockerclient.New()
	if err != nil {
		t.Fatal(err)
	}

	vars, err := template.VarsFromStrings([]string{"version=125"})
	if err != nil {
		t.Fatal(err)
	}

	builder := &Builder{
		Rockerfile: tempDir + "/Rockerfile",
		OutStream:  util.PrefixPipe("[TEST] ", os.Stdout),
		Vars:       vars,
		// Push:       true,
		Docker: client,
	}

	imageID, err := builder.Build()
	if err != nil {
		t.Fatal(err)
	}
	t.Logf("Got imageID: %s", imageID)

	defer func() {
		if err := client.RemoveImageExtended(imageID, docker.RemoveImageOptions{Force: true}); err != nil {
			t.Log(err)
		}
	}()

	result, err := runContainer(t, client, &docker.Config{
		Image: imageID,
		Cmd:   []string{"cat", "/version"},
	}, nil)

	assert.Equal(t, "version:125\n", result, "failed")
}
Пример #3
0
func buildCommand(c *cli.Context) {
	configFilename := c.String("file")

	wd, err := os.Getwd()
	if err != nil {
		log.Fatal(err)
	}

	if !filepath.IsAbs(configFilename) {
		configFilename = filepath.Clean(path.Join(wd, configFilename))
	}

	// we do not want to outpu anything if "print" was asked
	// TODO: find a more clean way to suppress output
	if !c.Bool("print") {
		fmt.Printf("[Rocker] Building...\n")
	}

	dockerClient, err := dockerclient.NewFromCli(c)
	if err != nil {
		log.Fatal(err)
	}

	// Initialize context dir
	args := c.Args()
	contextDir := filepath.Dir(configFilename)
	if len(args) > 0 {
		if filepath.IsAbs(args[0]) {
			contextDir = args[0]
		} else {
			contextDir = filepath.Clean(path.Join(wd, args[0]))
		}
	}

	cliVars, err := template.VarsFromStrings(c.StringSlice("var"))
	if err != nil {
		log.Fatal(err)
	}

	vars := template.Vars{}.Merge(cliVars)

	// obtain git info about current directory
	gitInfo, err := git.Info(filepath.Dir(configFilename))
	if err != nil {
		// Ignore if given directory is not a git repo
		if _, ok := err.(*git.ErrNotGitRepo); !ok {
			log.Fatal(err)
		}
	}

	// some additional useful vars
	vars["commit"] = stringOr(os.Getenv("GIT_COMMIT"), gitInfo.Sha)
	vars["branch"] = stringOr(os.Getenv("GIT_BRANCH"), gitInfo.Branch)
	vars["git_url"] = stringOr(os.Getenv("GIT_URL"), gitInfo.URL)
	vars["commit_message"] = gitInfo.Message
	vars["commit_author"] = gitInfo.Author

	auth := &docker.AuthConfiguration{}
	authParam := c.String("auth")
	if strings.Contains(authParam, ":") {
		userPass := strings.Split(authParam, ":")
		auth.Username = userPass[0]
		auth.Password = userPass[1]
	}

	builder := build.Builder{
		Rockerfile:    configFilename,
		ContextDir:    contextDir,
		UtilizeCache:  !c.Bool("no-cache"),
		Push:          c.Bool("push"),
		NoReuse:       c.Bool("no-reuse"),
		Verbose:       c.Bool("verbose"),
		Attach:        c.Bool("attach"),
		Print:         c.Bool("print"),
		Auth:          auth,
		Vars:          vars,
		CliVars:       cliVars,
		InStream:      os.Stdin,
		OutStream:     os.Stdout,
		Docker:        dockerClient,
		AddMeta:       c.Bool("meta"),
		Pull:          c.Bool("pull"),
		ID:            c.String("id"),
		ArtifactsPath: c.String("artifacts-path"),
	}

	if _, err := builder.Build(); err != nil {
		log.Fatal(err)
	}
}
Пример #4
0
func TestBuilderBuildVar(t *testing.T) {

	tempDir, err := ioutil.TempDir("/tmp", "rocker_TestBuilderBuildVar_")
	if err != nil {
		t.Fatal(err)
	}
	defer os.RemoveAll(tempDir)

	err = test.MakeFiles(tempDir, map[string]string{
		"/Rockerfile": `FROM busybox:buildroot-2013.08.1
VAR test=true
RUN touch /testing
RUN if [ "$test" == "true" ] ; then echo "done test" > /testing; fi
CMD cat /testing`,
	})

	// we will need docker client to cleanup and do some cross-checks
	client, err := dockerclient.New()
	if err != nil {
		t.Fatal(err)
	}

	run := func(vars []string) (string, error) {
		tplVars, err := template.VarsFromStrings(vars)
		if err != nil {
			return "", err
		}

		builder := &Builder{
			Rockerfile: tempDir + "/Rockerfile",
			OutStream:  util.PrefixPipe("[TEST] ", os.Stdout),
			Docker:     client,
			Vars:       tplVars,
		}

		imageID, err := builder.Build()
		if err != nil {
			return "", err
		}
		t.Logf("Got imageID: %s", imageID)

		defer func() {
			if err := client.RemoveImageExtended(imageID, docker.RemoveImageOptions{Force: true}); err != nil {
				t.Log(err)
			}
		}()

		return runContainer(t, client, &docker.Config{
			Image: imageID,
		}, nil)
	}

	result1, err := run([]string{})
	if err != nil {
		t.Fatal(err)
	}

	result2, err := run([]string{"test=false"})
	if err != nil {
		t.Fatal(err)
	}

	assert.Equal(t, "done test\n", result1)
	assert.Equal(t, "", result2)
}
Пример #5
0
func TestBuilderBuildTagLabels(t *testing.T) {

	tempDir, err := ioutil.TempDir("/tmp", "rocker_TestBuilderBuildTagLabels_")
	if err != nil {
		t.Fatal(err)
	}
	defer os.RemoveAll(tempDir)

	rockerfileContent := `FROM busybox:buildroot-2013.08.1
TAG testing
RUN touch /testing
LABEL foo=bar
PUSH quay.io/testing_project`

	err = test.MakeFiles(tempDir, map[string]string{
		"/Rockerfile": rockerfileContent,
	})

	// we will need docker client to cleanup and do some cross-checks
	client, err := dockerclient.New()
	if err != nil {
		t.Fatal(err)
	}

	vars, err := template.VarsFromStrings([]string{"asd=qwe"})
	if err != nil {
		t.Fatal(err)
	}

	builder := &Builder{
		Rockerfile: tempDir + "/Rockerfile",
		OutStream:  util.PrefixPipe("[TEST] ", os.Stdout),
		CliVars:    vars,
		Docker:     client,
		AddMeta:    true,
	}

	imageID, err := builder.Build()
	if err != nil {
		t.Fatal(err)
	}
	t.Logf("Got imageID: %s", imageID)

	defer func() {
		if err := client.RemoveImageExtended(imageID, docker.RemoveImageOptions{Force: true}); err != nil {
			t.Log(err)
		}
	}()

	inspect, err := client.InspectImage(imageID)
	if err != nil {
		t.Fatal(err)
	}

	// test inherited labels
	assert.Equal(t, "bar", inspect.Config.Labels["foo"])

	// test rockerfile content
	data := &RockerImageData{}
	if err := json.Unmarshal([]byte(inspect.Config.Labels["rocker-data"]), data); err != nil {
		t.Fatal(err)
	}
	assert.Equal(t, rockerfileContent, data.Rockerfile)

	// test vars
	assert.Equal(t, vars, data.Vars)
}
Пример #6
0
func buildCommand(c *cli.Context) {

	var (
		rockerfile *build.Rockerfile
		err        error
	)

	initLogs(c)

	// We don't want info level for 'print' mode
	// So log only errors unless 'debug' is on
	if c.Bool("print") && log.StandardLogger().Level != log.DebugLevel {
		log.StandardLogger().Level = log.ErrorLevel
	}

	vars, err := template.VarsFromFileMulti(c.StringSlice("vars"))
	if err != nil {
		log.Fatal(err)
		os.Exit(1)
	}

	cliVars, err := template.VarsFromStrings(c.StringSlice("var"))
	if err != nil {
		log.Fatal(err)
	}

	vars = vars.Merge(cliVars)

	if c.Bool("demand-artifacts") {
		vars["DemandArtifacts"] = true
	}

	wd, err := os.Getwd()
	if err != nil {
		log.Fatal(err)
	}

	configFilename := c.String("file")
	contextDir := wd

	if configFilename == "-" {

		rockerfile, err = build.NewRockerfile(filepath.Base(wd), os.Stdin, vars, template.Funs{})
		if err != nil {
			log.Fatal(err)
		}

	} else {

		if !filepath.IsAbs(configFilename) {
			configFilename = filepath.Join(wd, configFilename)
		}

		rockerfile, err = build.NewRockerfileFromFile(configFilename, vars, template.Funs{})
		if err != nil {
			log.Fatal(err)
		}

		// Initialize context dir
		contextDir = filepath.Dir(configFilename)
	}

	args := c.Args()
	if len(args) > 0 {
		contextDir = args[0]
		if !filepath.IsAbs(contextDir) {
			contextDir = filepath.Join(wd, args[0])
		}
	}

	log.Debugf("Context directory: %s", contextDir)

	if c.Bool("print") {
		fmt.Print(rockerfile.Content)
		os.Exit(0)
	}

	dockerignore := []string{}

	dockerignoreFilename := filepath.Join(contextDir, ".dockerignore")
	if _, err := os.Stat(dockerignoreFilename); err == nil {
		if dockerignore, err = build.ReadDockerignoreFile(dockerignoreFilename); err != nil {
			log.Fatal(err)
		}
	}

	dockerClient, err := dockerclient.NewFromCli(c)
	if err != nil {
		log.Fatal(err)
	}

	auth := docker.AuthConfiguration{}
	authParam := c.String("auth")
	if strings.Contains(authParam, ":") {
		userPass := strings.Split(authParam, ":")
		auth.Username = userPass[0]
		auth.Password = userPass[1]
	}

	client := build.NewDockerClient(dockerClient, auth, log.StandardLogger())

	var cache build.Cache
	if !c.Bool("no-cache") {
		cacheDir, err := util.MakeAbsolute(c.String("cache-dir"))
		if err != nil {
			log.Fatal(err)
		}
		cache = build.NewCacheFS(cacheDir)
	}

	builder := build.New(client, rockerfile, cache, build.Config{
		InStream:      os.Stdin,
		OutStream:     os.Stdout,
		ContextDir:    contextDir,
		Dockerignore:  dockerignore,
		ArtifactsPath: c.String("artifacts-path"),
		Pull:          c.Bool("pull"),
		NoGarbage:     c.Bool("no-garbage"),
		Attach:        c.Bool("attach"),
		Verbose:       c.GlobalBool("verbose"),
		ID:            c.String("id"),
		NoCache:       c.Bool("no-cache"),
		ReloadCache:   c.Bool("reload-cache"),
		Push:          c.Bool("push"),
	})

	plan, err := build.NewPlan(rockerfile.Commands(), true)
	if err != nil {
		log.Fatal(err)
	}

	// Check the docker connection before we actually run
	if err := dockerclient.Ping(dockerClient, 5000); err != nil {
		log.Fatal(err)
	}

	if err := builder.Run(plan); err != nil {
		log.Fatal(err)
	}

	size := fmt.Sprintf("final size %s (+%s from the base image)",
		units.HumanSize(float64(builder.VirtualSize)),
		units.HumanSize(float64(builder.ProducedSize)),
	)

	log.Infof("Successfully built %.12s | %s", builder.GetImageID(), size)
}