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) }
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") }
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) } }
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) }
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) }
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) }