Skip to content

Add --pull option to build command #3074

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jun 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions cmd/nerdctl/builder_build.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ If Dockerfile is not present and -f is not specified, it will look for Container
buildCommand.Flags().StringP("output", "o", "", "Output destination (format: type=local,dest=path)")
buildCommand.Flags().String("progress", "auto", "Set type of progress output (auto, plain, tty). Use plain to show container output")
buildCommand.Flags().String("provenance", "", "Shorthand for \"--attest=type=provenance\"")
buildCommand.Flags().Bool("pull", false, "On true, always attempt to pull latest image version from remote. Default uses buildkit's default.")
buildCommand.Flags().StringArray("secret", nil, "Secret file to expose to the build: id=mysecret,src=/local/secret")
buildCommand.Flags().StringArray("allow", nil, "Allow extra privileged entitlement, e.g. network.host, security.insecure")
buildCommand.RegisterFlagCompletionFunc("allow", func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
Expand Down Expand Up @@ -133,6 +134,14 @@ func processBuildCommandFlag(cmd *cobra.Command, args []string) (types.BuilderBu
if err != nil {
return types.BuilderBuildOptions{}, err
}
var pull *bool
if cmd.Flags().Changed("pull") {
pullFlag, err := cmd.Flags().GetBool("pull")
if err != nil {
return types.BuilderBuildOptions{}, err
}
pull = &pullFlag
}
secret, err := cmd.Flags().GetStringArray("secret")
if err != nil {
return types.BuilderBuildOptions{}, err
Expand Down Expand Up @@ -205,6 +214,7 @@ func processBuildCommandFlag(cmd *cobra.Command, args []string) (types.BuilderBu
BuildArgs: buildArgs,
Label: label,
NoCache: noCache,
Pull: pull,
Secret: secret,
Allow: allow,
Attest: attest,
Expand Down
90 changes: 90 additions & 0 deletions cmd/nerdctl/builder_linux_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,13 @@ package main
import (
"bytes"
"fmt"
"os"
"os/exec"
"path/filepath"
"testing"

"github.com/containerd/nerdctl/v2/pkg/testutil"
"gotest.tools/v3/assert"
)

func TestBuilderDebug(t *testing.T) {
Expand All @@ -36,3 +40,89 @@ CMD ["echo", "nerdctl-builder-debug-test-string"]

base.Cmd("builder", "debug", buildCtx).CmdOption(testutil.WithStdin(bytes.NewReader([]byte("c\n")))).AssertOK()
}

func TestBuildWithPull(t *testing.T) {
testutil.DockerIncompatible(t)
testutil.RequiresBuild(t)

oldImage := testutil.BusyboxImage
oldImageSha := "141c253bc4c3fd0a201d32dc1f493bcf3fff003b6df416dea4f41046e0f37d47"
newImage := testutil.AlpineImage

buildkitConfig := fmt.Sprintf(`[worker.oci]
enabled = false

[worker.containerd]
enabled = true
namespace = "%s"`, testutil.Namespace)

cleanup := useBuildkitConfig(t, buildkitConfig)
defer cleanup()

testCases := []struct {
name string
pull string
}{
{
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you add a test case for the default behaviour? (i.e. not specifying --pull)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

name: "build with local image",
pull: "false",
},
{
name: "build with newest image",
pull: "true",
},
{
name: "build with buildkit default",
// buildkit default pulls from remote
pull: "default",
},
}

for _, tc := range testCases {
tc := tc
t.Run(tc.name, func(t *testing.T) {
base := testutil.NewBase(t)
defer base.Cmd("builder", "prune").AssertOK()
base.Cmd("image", "prune", "--force", "--all").AssertOK()

base.Cmd("pull", oldImage).Run()
base.Cmd("tag", oldImage, newImage).Run()

dockerfile := fmt.Sprintf(`FROM %s`, newImage)
tmpDir := t.TempDir()
err := os.WriteFile(filepath.Join(tmpDir, "Dockerfile"), []byte(dockerfile), 0644)
assert.NilError(t, err)

buildCtx := createBuildContext(t, dockerfile)

buildCmd := []string{"build", buildCtx}
switch tc.pull {
case "false":
buildCmd = append(buildCmd, "--pull=false")
base.Cmd(buildCmd...).AssertErrContains(oldImageSha)
case "true":
buildCmd = append(buildCmd, "--pull=true")
base.Cmd(buildCmd...).AssertErrNotContains(oldImageSha)
case "default":
base.Cmd(buildCmd...).AssertErrNotContains(oldImageSha)
}
})
}
}

func useBuildkitConfig(t *testing.T, config string) (cleanup func()) {
buildkitConfigPath := "/etc/buildkit/buildkitd.toml"

currConfig, err := exec.Command("cat", buildkitConfigPath).Output()
assert.NilError(t, err)

os.WriteFile(buildkitConfigPath, []byte(config), 0644)
_, err = exec.Command("systemctl", "restart", "buildkit").Output()
assert.NilError(t, err)

return func() {
assert.NilError(t, os.WriteFile(buildkitConfigPath, currConfig, 0644))
_, err = exec.Command("systemctl", "restart", "buildkit").Output()
assert.NilError(t, err)
}
}
1 change: 1 addition & 0 deletions docs/command-reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -692,6 +692,7 @@ Flags:
- :whale: `type=image,name=example.com/image,push=true`: Push to a registry (see [`buildctl build`](https://github.com/moby/buildkit/tree/v0.9.0#imageregistry) documentation)
- :whale: `--progress=(auto|plain|tty)`: Set type of progress output (auto, plain, tty). Use plain to show container output
- :whale: `--provenance`: Shorthand for \"--attest=type=provenance\", see [`buildx_build.md`](https://github.com/docker/buildx/blob/v0.12.1/docs/reference/buildx_build.md#provenance) documentation
- :whale: `--pull=(true|false)`: On true, always attempt to pull latest image version from remote. Default uses buildkit's default.
- :whale: `--secret`: Secret file to expose to the build: id=mysecret,src=/local/secret
- :whale: `--allow`: Allow extra privileged entitlement, e.g. network.host, security.insecure (It’s required to configure the buildkitd to enable the feature, see [`buildkitd.toml`](https://github.com/moby/buildkit/blob/master/docs/buildkitd.toml.md) documentation)
- :whale: `--attest`: Attestation parameters (format: "type=sbom,generator=image"), see [`buildx_build.md`](https://github.com/docker/buildx/blob/v0.12.1/docs/reference/buildx_build.md#attest) documentation
Expand Down
2 changes: 2 additions & 0 deletions pkg/api/types/builder_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,8 @@ type BuilderBuildOptions struct {
ExtendedBuildContext []string
// NetworkMode mode for the build context
NetworkMode string
// Pull determines if we should try to pull latest image from remote. Default is buildkit's default.
Pull *bool
}

// BuilderPruneOptions specifies options for `nerdctl builder prune`.
Expand Down
9 changes: 9 additions & 0 deletions pkg/cmd/builder/build.go
Original file line number Diff line number Diff line change
Expand Up @@ -367,6 +367,15 @@ func generateBuildctlArgs(ctx context.Context, client *containerd.Client, option
buildctlArgs = append(buildctlArgs, "--no-cache")
}

if options.Pull != nil {
switch *options.Pull {
case true:
buildctlArgs = append(buildctlArgs, "--opt=image-resolve-mode=pull")
case false:
buildctlArgs = append(buildctlArgs, "--opt=image-resolve-mode=local")
}
}

for _, s := range strutil.DedupeStrSlice(options.Secret) {
buildctlArgs = append(buildctlArgs, "--secret="+s)
}
Expand Down
Loading