Change the quiet flag behavior in the build command
Right now, the quiet (-q, --quiet) flag ignores the output
generated from within the container.
However, it ought to be quiet in a way that all kind
of diagnostic output should be ignored, unless the build
process fails.
This patch makes the quiet flag behave in the following way:
1. If the build process succeeds, stdout contains the image ID
and stderr is empty.
2. If the build process fails, stdout is empty and stderr
has the error message and the diagnostic output of that process.
If the quiet flag is not set, then everything goes to stdout
and error messages, if there are any, go to stderr.
Signed-off-by: Boaz Shuster <ripcurld.github@gmail.com>
Upstream-commit: 60b4db7eb17f4eb509be4a4968364ada2075d60c
Component: engine
This commit is contained in:
committed by
ripcurld00d
parent
fc63a9d65d
commit
1c5df6581b
@@ -4941,6 +4941,110 @@ func (s *DockerSuite) TestBuildLabelsCache(c *check.C) {
|
||||
|
||||
}
|
||||
|
||||
func (s *DockerSuite) TestBuildNotVerboseSuccess(c *check.C) {
|
||||
testRequires(c, DaemonIsLinux)
|
||||
// This test makes sure that -q works correctly when build is successful:
|
||||
// stdout has only the image ID (long image ID) and stderr is empty.
|
||||
var stdout, stderr string
|
||||
var err error
|
||||
outRegexp := regexp.MustCompile("^(sha256:|)[a-z0-9]{64}\\n$")
|
||||
|
||||
tt := []struct {
|
||||
Name string
|
||||
BuildFunc func(string)
|
||||
}{
|
||||
{
|
||||
Name: "quiet_build_stdin_success",
|
||||
BuildFunc: func(name string) {
|
||||
_, stdout, stderr, err = buildImageWithStdoutStderr(name, "FROM busybox", true, "-q", "--force-rm", "--rm")
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "quiet_build_ctx_success",
|
||||
BuildFunc: func(name string) {
|
||||
ctx, err := fakeContext("FROM busybox", map[string]string{
|
||||
"quiet_build_success_fctx": "test",
|
||||
})
|
||||
if err != nil {
|
||||
c.Fatalf("Failed to create context: %s", err.Error())
|
||||
}
|
||||
defer ctx.Close()
|
||||
_, stdout, stderr, err = buildImageFromContextWithStdoutStderr(name, ctx, true, "-q", "--force-rm", "--rm")
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "quiet_build_git_success",
|
||||
BuildFunc: func(name string) {
|
||||
git, err := newFakeGit("repo", map[string]string{
|
||||
"Dockerfile": "FROM busybox",
|
||||
}, true)
|
||||
if err != nil {
|
||||
c.Fatalf("Failed to create the git repo: %s", err.Error())
|
||||
}
|
||||
defer git.Close()
|
||||
_, stdout, stderr, err = buildImageFromGitWithStdoutStderr(name, git, true, "-q", "--force-rm", "--rm")
|
||||
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, te := range tt {
|
||||
te.BuildFunc(te.Name)
|
||||
if err != nil {
|
||||
c.Fatalf("Test %s shouldn't fail, but got the following error: %s", te.Name, err.Error())
|
||||
}
|
||||
if outRegexp.Find([]byte(stdout)) == nil {
|
||||
c.Fatalf("Test %s expected stdout to match the [%v] regexp, but it is [%v]", te.Name, outRegexp, stdout)
|
||||
}
|
||||
if stderr != "" {
|
||||
c.Fatalf("Test %s expected stderr to be empty, but it is [%#v]", te.Name, stderr)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func (s *DockerSuite) TestBuildNotVerboseFailure(c *check.C) {
|
||||
testRequires(c, DaemonIsLinux)
|
||||
// This test makes sure that -q works correctly when build fails by
|
||||
// comparing between the stderr output in quiet mode and in stdout
|
||||
// and stderr output in verbose mode
|
||||
tt := []struct {
|
||||
TestName string
|
||||
BuildCmds string
|
||||
}{
|
||||
{"quiet_build_no_from_at_the_beginning", "RUN whoami"},
|
||||
{"quiet_build_unknown_instr", "FROMD busybox"},
|
||||
{"quiet_build_not_exists_image", "FROM busybox11"},
|
||||
}
|
||||
|
||||
for _, te := range tt {
|
||||
_, _, qstderr, qerr := buildImageWithStdoutStderr(te.TestName, te.BuildCmds, false, "-q", "--force-rm", "--rm")
|
||||
_, vstdout, vstderr, verr := buildImageWithStdoutStderr(te.TestName, te.BuildCmds, false, "--force-rm", "--rm")
|
||||
if verr == nil || qerr == nil {
|
||||
c.Fatal(fmt.Errorf("Test [%s] expected to fail but didn't", te.TestName))
|
||||
}
|
||||
if qstderr != vstdout+vstderr {
|
||||
c.Fatal(fmt.Errorf("Test[%s] expected that quiet stderr and verbose stdout are equal; quiet [%v], verbose [%v]", te.TestName, qstderr, vstdout))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (s *DockerSuite) TestBuildNotVerboseFailureRemote(c *check.C) {
|
||||
testRequires(c, DaemonIsLinux)
|
||||
// This test ensures that when given a wrong URL, stderr in quiet mode and
|
||||
// stdout and stderr in verbose mode are identical.
|
||||
URL := "http://bla.bla.com"
|
||||
Name := "quiet_build_wrong_remote"
|
||||
_, _, qstderr, qerr := buildImageWithStdoutStderr(Name, "", false, "-q", "--force-rm", "--rm", URL)
|
||||
_, vstdout, vstderr, verr := buildImageWithStdoutStderr(Name, "", false, "--force-rm", "--rm", URL)
|
||||
if qerr == nil || verr == nil {
|
||||
c.Fatal(fmt.Errorf("Test [%s] expected to fail but didn't", Name))
|
||||
}
|
||||
if qstderr != vstdout+vstderr {
|
||||
c.Fatal(fmt.Errorf("Test[%s] expected that quiet stderr and verbose stdout are equal; quiet [%v], verbose [%v]", Name, qstderr, vstdout))
|
||||
}
|
||||
}
|
||||
|
||||
func (s *DockerSuite) TestBuildStderr(c *check.C) {
|
||||
testRequires(c, DaemonIsLinux)
|
||||
// This test just makes sure that no non-error output goes
|
||||
@@ -5589,34 +5693,6 @@ func (s *DockerSuite) TestBuildDotDotFile(c *check.C) {
|
||||
}
|
||||
}
|
||||
|
||||
func (s *DockerSuite) TestBuildNotVerbose(c *check.C) {
|
||||
testRequires(c, DaemonIsLinux)
|
||||
ctx, err := fakeContext("FROM busybox\nENV abc=hi\nRUN echo $abc there", map[string]string{})
|
||||
if err != nil {
|
||||
c.Fatal(err)
|
||||
}
|
||||
defer ctx.Close()
|
||||
|
||||
// First do it w/verbose - baseline
|
||||
out, _, err := dockerCmdInDir(c, ctx.Dir, "build", "--no-cache", "-t", "verbose", ".")
|
||||
if err != nil {
|
||||
c.Fatalf("failed to build the image w/o -q: %s, %v", out, err)
|
||||
}
|
||||
if !strings.Contains(out, "hi there") {
|
||||
c.Fatalf("missing output:%s\n", out)
|
||||
}
|
||||
|
||||
// Now do it w/o verbose
|
||||
out, _, err = dockerCmdInDir(c, ctx.Dir, "build", "--no-cache", "-q", "-t", "verbose", ".")
|
||||
if err != nil {
|
||||
c.Fatalf("failed to build the image w/ -q: %s, %v", out, err)
|
||||
}
|
||||
if strings.Contains(out, "hi there") {
|
||||
c.Fatalf("Bad output, should not contain 'hi there':%s", out)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func (s *DockerSuite) TestBuildRUNoneJSON(c *check.C) {
|
||||
testRequires(c, DaemonIsLinux)
|
||||
name := "testbuildrunonejson"
|
||||
|
||||
@@ -1308,6 +1308,47 @@ func buildImageFromContextWithOut(name string, ctx *FakeContext, useCache bool,
|
||||
return id, out, nil
|
||||
}
|
||||
|
||||
func buildImageFromContextWithStdoutStderr(name string, ctx *FakeContext, useCache bool, buildFlags ...string) (string, string, string, error) {
|
||||
args := []string{"build", "-t", name}
|
||||
if !useCache {
|
||||
args = append(args, "--no-cache")
|
||||
}
|
||||
args = append(args, buildFlags...)
|
||||
args = append(args, ".")
|
||||
buildCmd := exec.Command(dockerBinary, args...)
|
||||
buildCmd.Dir = ctx.Dir
|
||||
|
||||
stdout, stderr, exitCode, err := runCommandWithStdoutStderr(buildCmd)
|
||||
if err != nil || exitCode != 0 {
|
||||
return "", stdout, stderr, fmt.Errorf("failed to build the image: %s", stdout)
|
||||
}
|
||||
id, err := getIDByName(name)
|
||||
if err != nil {
|
||||
return "", stdout, stderr, err
|
||||
}
|
||||
return id, stdout, stderr, nil
|
||||
}
|
||||
|
||||
func buildImageFromGitWithStdoutStderr(name string, ctx *fakeGit, useCache bool, buildFlags ...string) (string, string, string, error) {
|
||||
args := []string{"build", "-t", name}
|
||||
if !useCache {
|
||||
args = append(args, "--no-cache")
|
||||
}
|
||||
args = append(args, buildFlags...)
|
||||
args = append(args, ctx.RepoURL)
|
||||
buildCmd := exec.Command(dockerBinary, args...)
|
||||
|
||||
stdout, stderr, exitCode, err := runCommandWithStdoutStderr(buildCmd)
|
||||
if err != nil || exitCode != 0 {
|
||||
return "", stdout, stderr, fmt.Errorf("failed to build the image: %s", stdout)
|
||||
}
|
||||
id, err := getIDByName(name)
|
||||
if err != nil {
|
||||
return "", stdout, stderr, err
|
||||
}
|
||||
return id, stdout, stderr, nil
|
||||
}
|
||||
|
||||
func buildImageFromPath(name, path string, useCache bool, buildFlags ...string) (string, error) {
|
||||
args := []string{"build", "-t", name}
|
||||
if !useCache {
|
||||
|
||||
Reference in New Issue
Block a user