Skip to content

Commit

Permalink
Merge pull request #3551 from austinvazquez/support-load-container-qu…
Browse files Browse the repository at this point in the history
…iet-mode

Add image load and container run quiet mode
  • Loading branch information
AkihiroSuda authored Oct 15, 2024
2 parents 0a79d30 + 90b9635 commit 1123a60
Show file tree
Hide file tree
Showing 9 changed files with 80 additions and 12 deletions.
5 changes: 5 additions & 0 deletions cmd/nerdctl/container/container_create.go
Original file line number Diff line number Diff line change
Expand Up @@ -409,12 +409,17 @@ func processContainerCreateOptions(cmd *cobra.Command) (types.ContainerCreateOpt
if err != nil {
return opt, err
}
quiet, err := cmd.Flags().GetBool("quiet")
if err != nil {
return opt, err
}
opt.ImagePullOpt = types.ImagePullOptions{
GOptions: opt.GOptions,
VerifyOptions: imageVerifyOpt,
IPFSAddress: opt.IPFSAddress,
Stdout: opt.Stdout,
Stderr: opt.Stderr,
Quiet: quiet,
}
// #endregion

Expand Down
1 change: 1 addition & 0 deletions cmd/nerdctl/container/container_run.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ func setCreateFlags(cmd *cobra.Command) {
})
cmd.Flags().Bool("rm", false, "Automatically remove the container when it exits")
cmd.Flags().String("pull", "missing", `Pull image before running ("always"|"missing"|"never")`)
cmd.Flags().BoolP("quiet", "q", false, "Suppress the pull output")
cmd.RegisterFlagCompletionFunc("pull", func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
return []string{"always", "missing", "never"}, cobra.ShellCompDirectiveNoFileComp
})
Expand Down
27 changes: 27 additions & 0 deletions cmd/nerdctl/container/container_run_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -631,3 +631,30 @@ func TestRunAttachFlag(t *testing.T) {
})
}
}

func TestRunQuiet(t *testing.T) {
base := testutil.NewBase(t)

teardown := func() {
base.Cmd("rmi", "-f", testutil.CommonImage).Run()
}
defer teardown()
teardown()

sentinel := "test run quiet"
result := base.Cmd("run", "--rm", "--quiet", testutil.CommonImage, fmt.Sprintf(`echo "%s"`, sentinel)).Run()
assert.Assert(t, strings.Contains(result.Combined(), sentinel))

wasQuiet := func(output, sentinel string) bool {
return !strings.Contains(output, sentinel)
}

// Docker and nerdctl image pulls are not 1:1.
if testutil.GetTarget() == testutil.Docker {
sentinel = "Pull complete"
} else {
sentinel = "resolved"
}

assert.Assert(t, wasQuiet(result.Combined(), sentinel), "Found %s in container run output", sentinel)
}
6 changes: 6 additions & 0 deletions cmd/nerdctl/image/image_load.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ func NewLoadCommand() *cobra.Command {
}

loadCommand.Flags().StringP("input", "i", "", "Read from tar archive file, instead of STDIN")
loadCommand.Flags().BoolP("quiet", "q", false, "Suppress the load output")

// #region platform flags
// platform is defined as StringSlice, not StringArray, to allow specifying "--platform=amd64,arm64"
Expand Down Expand Up @@ -66,13 +67,18 @@ func processLoadCommandFlags(cmd *cobra.Command) (types.ImageLoadOptions, error)
if err != nil {
return types.ImageLoadOptions{}, err
}
quiet, err := cmd.Flags().GetBool("quiet")
if err != nil {
return types.ImageLoadOptions{}, err
}
return types.ImageLoadOptions{
GOptions: globalOptions,
Input: input,
Platform: platform,
AllPlatforms: allPlatforms,
Stdout: cmd.OutOrStdout(),
Stdin: cmd.InOrStdin(),
Quiet: quiet,
}, nil
}

Expand Down
30 changes: 30 additions & 0 deletions cmd/nerdctl/image/image_load_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,3 +79,33 @@ func TestLoadStdinEmpty(t *testing.T) {

testCase.Run(t)
}

func TestLoadQuiet(t *testing.T) {
nerdtest.Setup()

testCase := &test.Case{
Description: "TestLoadQuiet",
Setup: func(data test.Data, helpers test.Helpers) {
helpers.Ensure("pull", testutil.CommonImage)
helpers.Ensure("tag", testutil.CommonImage, data.Identifier())
helpers.Ensure("save", data.Identifier(), "-o", filepath.Join(data.TempDir(), "common.tar"))
helpers.Ensure("rmi", "-f", data.Identifier())
},
Cleanup: func(data test.Data, helpers test.Helpers) {
helpers.Anyhow("rmi", "-f", data.Identifier())
},
Command: func(data test.Data, helpers test.Helpers) test.TestableCommand {
return helpers.Command("load", "--quiet", "--input", filepath.Join(data.TempDir(), "common.tar"))
},
Expected: func(data test.Data, helpers test.Helpers) *test.Expected {
return &test.Expected{
Output: test.All(
test.Contains(fmt.Sprintf("Loaded image: %s:latest", data.Identifier())),
test.DoesNotContain("Loading layer"),
),
}
},
}

testCase.Run(t)
}
4 changes: 2 additions & 2 deletions docs/command-reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,7 @@ Basic flags:
- :whale: `--rm`: Automatically remove the container when it exits
- :whale: `--pull=(always|missing|never)`: Pull image before running
- Default: "missing"
- :whale: `-q, --quiet`: Suppress the pull output
- :whale: `--pid=(host|container:<container>)`: PID namespace to use
- :whale: `--uts=(host)` : UTS namespace to use
- :whale: `--stop-signal`: Signal to stop a container (default "SIGTERM")
Expand Down Expand Up @@ -815,11 +816,10 @@ Usage: `nerdctl load [OPTIONS]`
Flags:

- :whale: `-i, --input`: Read from tar archive file, instead of STDIN
- :whale: `-q, --quiet`: Suppress the load output
- :nerd_face: `--platform=(amd64|arm64|...)`: Import content for a specific platform
- :nerd_face: `--all-platforms`: Import content for all platforms

Unimplemented `docker load` flags: `--quiet`

### :whale: nerdctl save

Save one or more images to a tar archive (streamed to STDOUT by default)
Expand Down
2 changes: 2 additions & 0 deletions pkg/api/types/load_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,4 +29,6 @@ type ImageLoadOptions struct {
Platform []string
// AllPlatforms import content for all platforms
AllPlatforms bool
// Quiet suppresses the load output.
Quiet bool
}
1 change: 0 additions & 1 deletion pkg/cmd/container/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,6 @@ func Create(ctx context.Context, client *containerd.Client, args []string, netMa
options.ImagePullOpt.Mode = options.Pull
options.ImagePullOpt.OCISpecPlatform = ocispecPlatforms
options.ImagePullOpt.Unpack = nil
options.ImagePullOpt.Quiet = false

ensuredImage, err = image.EnsureImage(ctx, client, rawRef, options.ImagePullOpt)
if err != nil {
Expand Down
16 changes: 7 additions & 9 deletions pkg/cmd/image/load.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,10 +73,10 @@ func Load(ctx context.Context, client *containerd.Client, options types.ImageLoa
if err != nil {
return err
}
return loadImage(ctx, client, decompressor, platMC, false, options)
return loadImage(ctx, client, decompressor, platMC, options)
}

func loadImage(ctx context.Context, client *containerd.Client, in io.Reader, platMC platforms.MatchComparer, quiet bool, options types.ImageLoadOptions) error {
func loadImage(ctx context.Context, client *containerd.Client, in io.Reader, platMC platforms.MatchComparer, options types.ImageLoadOptions) error {
// In addition to passing WithImagePlatform() to client.Import(), we also need to pass WithDefaultPlatform() to NewClient().
// Otherwise unpacking may fail.
r := &readCounter{Reader: in}
Expand All @@ -95,19 +95,17 @@ func loadImage(ctx context.Context, client *containerd.Client, in io.Reader, pla
image := containerd.NewImageWithPlatform(client, img, platMC)

// TODO: Show unpack status
if !quiet {
if !options.Quiet {
fmt.Fprintf(options.Stdout, "unpacking %s (%s)...\n", img.Name, img.Target.Digest)
}
err = image.Unpack(ctx, options.GOptions.Snapshotter)
if err != nil {
return err
}
if quiet {
fmt.Fprintln(options.Stdout, img.Target.Digest)
} else {
repo, tag := imgutil.ParseRepoTag(img.Name)
fmt.Fprintf(options.Stdout, "Loaded image: %s:%s\n", repo, tag)
}

// Loaded message is shown even when quiet.
repo, tag := imgutil.ParseRepoTag(img.Name)
fmt.Fprintf(options.Stdout, "Loaded image: %s:%s\n", repo, tag)
}

return nil
Expand Down

0 comments on commit 1123a60

Please sign in to comment.