Skip to content

Commit

Permalink
Support docker build --build-context parameter (#3273)
Browse files Browse the repository at this point in the history
* Support docker build --build-context parameter

Signed-off-by: jonnyry <[email protected]>

* 1) Use dockerx buildflags.ParseContextNames function for improved error handling (instead of own function) 2) Add toNamedContexts function and tests 3) Improve help output to make format clearer.

Signed-off-by: jonnyry <[email protected]>

---------

Signed-off-by: jonnyry <[email protected]>
  • Loading branch information
jonnyry authored Dec 9, 2024
1 parent 61dfc21 commit 38dcc21
Show file tree
Hide file tree
Showing 6 changed files with 74 additions and 24 deletions.
2 changes: 2 additions & 0 deletions cmd/porter/bundle.go
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,8 @@ The docker driver builds the bundle image using the local Docker host. To use a
_ = f.MarkHidden("driver") // Hide the driver flag since there aren't any choices to make right now
f.StringArrayVar(&opts.BuildArgs, "build-arg", nil,
"Set build arguments in the template Dockerfile (format: NAME=VALUE). May be specified multiple times. Max length is 5,000 characters.")
f.StringArrayVar(&opts.BuildContexts, "build-context", nil,
"Define additional build context with specified contents (format: NAME=PATH). May be specified multiple times.")
f.StringArrayVar(&opts.SSH, "ssh", nil,
"SSH agent socket or keys to expose to the build (format: default|<id>[=<socket>|<key>[,<key>]]). May be specified multiple times.")
f.StringArrayVar(&opts.Secrets, "secret", nil,
Expand Down
25 changes: 13 additions & 12 deletions docs/content/docs/references/cli/build.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,18 +37,19 @@ porter build [flags]
### Options

```
--build-arg stringArray Set build arguments in the template Dockerfile (format: NAME=VALUE). May be specified multiple times. Max length is 5,000 characters.
--custom stringArray Define an individual key-value pair for the custom section in the form of NAME=VALUE. Use dot notation to specify a nested custom field. May be specified multiple times. Max length is 5,000 characters when used as a build argument.
-d, --dir string Path to the build context directory where all bundle assets are located. Defaults to the current directory.
-f, --file string Path to the Porter manifest. The path is relative to the build context directory. Defaults to porter.yaml in the current directory.
-h, --help help for build
--insecure-registry Don't require TLS when pulling referenced images
--name string Override the bundle name
--no-cache Do not use the Docker cache when building the bundle image.
--no-lint Do not run the linter
--secret stringArray Secret file to expose to the build (format: id=mysecret,src=/local/secret). Custom values are accessible as build arguments in the template Dockerfile and in the manifest using template variables. May be specified multiple times.
--ssh stringArray SSH agent socket or keys to expose to the build (format: default|<id>[=<socket>|<key>[,<key>]]). May be specified multiple times.
--version string Override the bundle version
--build-arg stringArray Set build arguments in the template Dockerfile (format: NAME=VALUE). May be specified multiple times. Max length is 5,000 characters.
--build-context stringArray Define additional build context with specified contents (format: NAME=PATH). May be specified multiple times.
--custom stringArray Define an individual key-value pair for the custom section in the form of NAME=VALUE. Use dot notation to specify a nested custom field. May be specified multiple times. Max length is 5,000 characters when used as a build argument.
-d, --dir string Path to the build context directory where all bundle assets are located. Defaults to the current directory.
-f, --file string Path to the Porter manifest. The path is relative to the build context directory. Defaults to porter.yaml in the current directory.
-h, --help help for build
--insecure-registry Don't require TLS when pulling referenced images
--name string Override the bundle name
--no-cache Do not use the Docker cache when building the bundle image.
--no-lint Do not run the linter
--secret stringArray Secret file to expose to the build (format: id=mysecret,src=/local/secret). Custom values are accessible as build arguments in the template Dockerfile and in the manifest using template variables. May be specified multiple times.
--ssh stringArray SSH agent socket or keys to expose to the build (format: default|<id>[=<socket>|<key>[,<key>]]). May be specified multiple times.
--version string Override the bundle version
```

### Options inherited from parent commands
Expand Down
25 changes: 13 additions & 12 deletions docs/content/docs/references/cli/bundles_build.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,18 +37,19 @@ porter bundles build [flags]
### Options

```
--build-arg stringArray Set build arguments in the template Dockerfile (format: NAME=VALUE). May be specified multiple times. Max length is 5,000 characters.
--custom stringArray Define an individual key-value pair for the custom section in the form of NAME=VALUE. Use dot notation to specify a nested custom field. May be specified multiple times. Max length is 5,000 characters when used as a build argument.
-d, --dir string Path to the build context directory where all bundle assets are located. Defaults to the current directory.
-f, --file string Path to the Porter manifest. The path is relative to the build context directory. Defaults to porter.yaml in the current directory.
-h, --help help for build
--insecure-registry Don't require TLS when pulling referenced images
--name string Override the bundle name
--no-cache Do not use the Docker cache when building the bundle image.
--no-lint Do not run the linter
--secret stringArray Secret file to expose to the build (format: id=mysecret,src=/local/secret). Custom values are accessible as build arguments in the template Dockerfile and in the manifest using template variables. May be specified multiple times.
--ssh stringArray SSH agent socket or keys to expose to the build (format: default|<id>[=<socket>|<key>[,<key>]]). May be specified multiple times.
--version string Override the bundle version
--build-arg stringArray Set build arguments in the template Dockerfile (format: NAME=VALUE). May be specified multiple times. Max length is 5,000 characters.
--build-context stringArray Define additional build context with specified contents (format: NAME=PATH). May be specified multiple times.
--custom stringArray Define an individual key-value pair for the custom section in the form of NAME=VALUE. Use dot notation to specify a nested custom field. May be specified multiple times. Max length is 5,000 characters when used as a build argument.
-d, --dir string Path to the build context directory where all bundle assets are located. Defaults to the current directory.
-f, --file string Path to the Porter manifest. The path is relative to the build context directory. Defaults to porter.yaml in the current directory.
-h, --help help for build
--insecure-registry Don't require TLS when pulling referenced images
--name string Override the bundle name
--no-cache Do not use the Docker cache when building the bundle image.
--no-lint Do not run the linter
--secret stringArray Secret file to expose to the build (format: id=mysecret,src=/local/secret). Custom values are accessible as build arguments in the template Dockerfile and in the manifest using template variables. May be specified multiple times.
--ssh stringArray SSH agent socket or keys to expose to the build (format: default|<id>[=<socket>|<key>[,<key>]]). May be specified multiple times.
--version string Override the bundle version
```

### Options inherited from parent commands
Expand Down
3 changes: 3 additions & 0 deletions pkg/build/build.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,9 @@ type BuildImageOptions struct {
// BuildArgs is the set of docker build --build-arg specified.
BuildArgs []string

// BuildContexts is the set of docker build --build-context specified.
BuildContexts []string

// NoCache is the docker build --no-cache flag specified.
NoCache bool
}
14 changes: 14 additions & 0 deletions pkg/build/buildkit/buildx.go
Original file line number Diff line number Diff line change
Expand Up @@ -120,13 +120,19 @@ func (b *Builder) BuildBundleImage(ctx context.Context, manifest *manifest.Manif
}
span.SetAttributes(tracing.ObjectAttribute("build-args", args))

buildContexts, err := buildflags.ParseContextNames(opts.BuildContexts)
if err != nil {
return span.Errorf("error parsing the --build-context flags: %w", err)
}

buildxOpts := map[string]buildx.Options{
"default": {
Tags: []string{manifest.Image},
Inputs: buildx.Inputs{
ContextPath: b.Getwd(),
DockerfilePath: b.getDockerfilePath(),
InStream: buildx.NewSyncMultiReader(b.In),
NamedContexts: toNamedContexts(buildContexts),
},
BuildArgs: args,
Session: currentSession,
Expand Down Expand Up @@ -243,6 +249,14 @@ func parseBuildArgs(unparsed []string, parsed map[string]string) {
}
}

func toNamedContexts(m map[string]string) map[string]buildx.NamedContext {
m2 := make(map[string]buildx.NamedContext, len(m))
for k, v := range m {
m2[k] = buildx.NamedContext{Path: v}
}
return m2
}

func (b *Builder) TagBundleImage(ctx context.Context, origTag, newTag string) error {
ctx, log := tracing.StartSpan(ctx, attribute.String("source-tag", origTag), attribute.String("destination-tag", newTag))
defer log.EndSpan()
Expand Down
29 changes: 29 additions & 0 deletions pkg/build/buildkit/buildx_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"get.porter.sh/porter/pkg/build"
"get.porter.sh/porter/pkg/config"
"get.porter.sh/porter/pkg/manifest"
buildx "github.com/docker/buildx/build"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
Expand All @@ -33,6 +34,34 @@ func Test_parseBuildArgs(t *testing.T) {
}
}

func Test_toNamedContexts(t *testing.T) {
testcases := []struct {
name string
inputArgs map[string]string
wantArgs map[string]buildx.NamedContext
}{
{name: "Basic conversion",
inputArgs: map[string]string{"context1": "/path/to/context1", "context2": "/path/to/context2"},
wantArgs: map[string]buildx.NamedContext{"context1": {Path: "/path/to/context1"}, "context2": {Path: "/path/to/context2"}}},
{name: "Single entry",
inputArgs: map[string]string{"singlecontext": "/single/path"},
wantArgs: map[string]buildx.NamedContext{"singlecontext": {Path: "/single/path"}}},
{name: "Empty path",
inputArgs: map[string]string{"singlecontext": ""},
wantArgs: map[string]buildx.NamedContext{"singlecontext": {Path: ""}}},
{name: "Empty input map",
inputArgs: map[string]string{},
wantArgs: map[string]buildx.NamedContext{}},
}

for _, tc := range testcases {
t.Run(tc.name, func(t *testing.T) {
var gotArgs = toNamedContexts(tc.inputArgs)
assert.Equal(t, tc.wantArgs, gotArgs)
})
}
}

func Test_flattenMap(t *testing.T) {
tt := []struct {
desc string
Expand Down

0 comments on commit 38dcc21

Please sign in to comment.