diff --git a/.web-docs/components/builder/docker/README.md b/.web-docs/components/builder/docker/README.md index 5ddf499..f3e34a0 100644 --- a/.web-docs/components/builder/docker/README.md +++ b/.web-docs/components/builder/docker/README.md @@ -32,6 +32,11 @@ source "docker" "example" { export_path = "image.tar" } +build { + sources = ["source.docker.example"] +} +``` + **JSON** ```json @@ -42,11 +47,6 @@ source "docker" "example" { } ``` -build { - sources = ["source.docker.example"] -} -``` - ## Basic Example: Commit Below is another example, the same as above but instead of exporting the @@ -298,11 +298,11 @@ You must specify (only) one of `commit`, `discard`, or `export_path`. - `platform` (string) - Set platform if server is multi-platform capable - If using `build`, this field will be ignored, as the `platform` option for - this operation will instead have precedence. + This cannot be used at the same time as `build`; instead, use `build.platform` -- `login` (bool) - This is used to login to dockerhub to pull a private base container. For - pushing to dockerhub, see the docker post-processors +- `login` (bool) - This is used to login to a private docker repository (e.g., dockerhub) + to build or pull a private base container. For pushing to a private + repository, see the docker post-processors. - `login_password` (string) - The password to use to authenticate to login. @@ -310,11 +310,11 @@ You must specify (only) one of `commit`, `discard`, or `export_path`. - `login_username` (string) - The username to use to authenticate to login. -- `ecr_login` (bool) - Defaults to false. If true, the builder will login in order to pull the - image from Amazon EC2 Container Registry (ECR). The builder only logs in - for the duration of the pull. If true login_server is required and - login, login_username, and login_password will be ignored. For more - information see the section on ECR. +- `ecr_login` (bool) - Defaults to false. If true, the builder will login in order to build or + pull the image from Amazon EC2 Container Registry (ECR). The builder + only logs in for the duration of the build or pull step. If true, + login_server is required and login, login_username, and login_password + will be ignored. For more information see the section on ECR. @@ -393,6 +393,9 @@ source "docker" "example" { Defaults to the directory from which we invoke packer. +- `arguments` (map[string]string) - A mapping of additional build args to provide. The key of + the object is the argument name, the value is the argument value. + - `platform` (string) - Set platform if server is multi-platform capable - `pull` (boolean) - Pull the image when building the base docker image. diff --git a/builder/docker/builder_acc_test.go b/builder/docker/builder_acc_test.go index a8f1b23..7253708 100644 --- a/builder/docker/builder_acc_test.go +++ b/builder/docker/builder_acc_test.go @@ -1,3 +1,6 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + package docker import ( diff --git a/builder/docker/config.go b/builder/docker/config.go index 9e9e3b7..eb2060e 100644 --- a/builder/docker/config.go +++ b/builder/docker/config.go @@ -144,8 +144,9 @@ type Config struct { // This cannot be used at the same time as `build`; instead, use `build.platform` Platform string `mapstructure:"platform" required:"false"` - // This is used to login to dockerhub to pull a private base container. For - // pushing to dockerhub, see the docker post-processors + // This is used to login to a private docker repository (e.g., dockerhub) + // to build or pull a private base container. For pushing to a private + // repository, see the docker post-processors. Login bool `mapstructure:"login" required:"false"` // The password to use to authenticate to login. LoginPassword string `mapstructure:"login_password" required:"false"` @@ -153,11 +154,11 @@ type Config struct { LoginServer string `mapstructure:"login_server" required:"false"` // The username to use to authenticate to login. LoginUsername string `mapstructure:"login_username" required:"false"` - // Defaults to false. If true, the builder will login in order to pull the - // image from Amazon EC2 Container Registry (ECR). The builder only logs in - // for the duration of the pull. If true login_server is required and - // login, login_username, and login_password will be ignored. For more - // information see the section on ECR. + // Defaults to false. If true, the builder will login in order to build or + // pull the image from Amazon EC2 Container Registry (ECR). The builder + // only logs in for the duration of the build or pull step. If true, + // login_server is required and login, login_username, and login_password + // will be ignored. For more information see the section on ECR. EcrLogin bool `mapstructure:"ecr_login" required:"false"` AwsAccessConfig `mapstructure:",squash"` diff --git a/builder/docker/dockerfile_config.go b/builder/docker/dockerfile_config.go index dce2239..b866170 100644 --- a/builder/docker/dockerfile_config.go +++ b/builder/docker/dockerfile_config.go @@ -31,10 +31,14 @@ type DockerfileBootstrapConfig struct { // // Defaults to the directory from which we invoke packer. BuildDir string `mapstructure:"build_dir"` - + + // A mapping of additional build args to provide. The key of + // the object is the argument name, the value is the argument value. + Arguments map[string]string `mapstructure:"arguments" required:"false"` + // Set platform if server is multi-platform capable Platform string `mapstructure:"platform" required:"false"` - + // Pull the image when building the base docker image. // // Note: defaults to true, to disable this, explicitly set it to false. @@ -101,6 +105,12 @@ func (c DockerfileBootstrapConfig) BuildArgs() []string { retArgs = append(retArgs, "--compress") } + // Loops through map of build arguments to add to build command + for key, value := range c.Arguments { + arg := key + "=" + value + retArgs = append(retArgs, "--build-arg", arg) + } + return append(retArgs, c.BuildDir) } diff --git a/builder/docker/dockerfile_config.hcl2spec.go b/builder/docker/dockerfile_config.hcl2spec.go index 7d80ae9..6d59fea 100644 --- a/builder/docker/dockerfile_config.hcl2spec.go +++ b/builder/docker/dockerfile_config.hcl2spec.go @@ -10,11 +10,12 @@ import ( // FlatDockerfileBootstrapConfig is an auto-generated flat version of DockerfileBootstrapConfig. // Where the contents of a field with a `mapstructure:,squash` tag are bubbled up. type FlatDockerfileBootstrapConfig struct { - DockerfilePath *string `mapstructure:"path" required:"true" cty:"path" hcl:"path"` - BuildDir *string `mapstructure:"build_dir" cty:"build_dir" hcl:"build_dir"` - Platform *string `mapstructure:"platform" required:"false" cty:"platform" hcl:"platform"` - Pull *bool `mapstructure:"pull" cty:"pull" hcl:"pull"` - Compress *bool `mapstructure:"compress" cty:"compress" hcl:"compress"` + DockerfilePath *string `mapstructure:"path" required:"true" cty:"path" hcl:"path"` + BuildDir *string `mapstructure:"build_dir" cty:"build_dir" hcl:"build_dir"` + Arguments map[string]string `mapstructure:"arguments" required:"false" cty:"arguments" hcl:"arguments"` + Platform *string `mapstructure:"platform" required:"false" cty:"platform" hcl:"platform"` + Pull *bool `mapstructure:"pull" cty:"pull" hcl:"pull"` + Compress *bool `mapstructure:"compress" cty:"compress" hcl:"compress"` } // FlatMapstructure returns a new FlatDockerfileBootstrapConfig. @@ -31,6 +32,7 @@ func (*FlatDockerfileBootstrapConfig) HCL2Spec() map[string]hcldec.Spec { s := map[string]hcldec.Spec{ "path": &hcldec.AttrSpec{Name: "path", Type: cty.String, Required: false}, "build_dir": &hcldec.AttrSpec{Name: "build_dir", Type: cty.String, Required: false}, + "arguments": &hcldec.AttrSpec{Name: "arguments", Type: cty.Map(cty.String), Required: false}, "platform": &hcldec.AttrSpec{Name: "platform", Type: cty.String, Required: false}, "pull": &hcldec.AttrSpec{Name: "pull", Type: cty.Bool, Required: false}, "compress": &hcldec.AttrSpec{Name: "compress", Type: cty.Bool, Required: false}, diff --git a/builder/docker/driver_docker.go b/builder/docker/driver_docker.go index fc1f1e5..4526c05 100644 --- a/builder/docker/driver_docker.go +++ b/builder/docker/driver_docker.go @@ -45,6 +45,7 @@ func (d *DockerDriver) Build(args []string) (string, error) { imageIdFilePath := imageIdFile.Name() imageIdFile.Close() + log.Printf("Building container with args: %v", args) cmd := exec.Command(d.Executable, "build") cmd.Args = append(cmd.Args, "--iidfile", imageIdFilePath) cmd.Args = append(cmd.Args, args...) diff --git a/builder/docker/step_build.go b/builder/docker/step_build.go index 376204b..039d4ca 100644 --- a/builder/docker/step_build.go +++ b/builder/docker/step_build.go @@ -1,10 +1,11 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + package docker import ( "context" - "errors" "fmt" - "reflect" "github.com/hashicorp/packer-plugin-sdk/multistep" "github.com/hashicorp/packer-plugin-sdk/packer" @@ -22,28 +23,60 @@ func (s *stepBuild) Run(ctx context.Context, state multistep.StateBag) multistep ui := state.Get("ui").(packer.Ui) driver := state.Get("driver").(Driver) - ui.Say("Building base image...") - - imageId, err := driver.Build(s.buildArgs.BuildArgs()) - if err != nil { + config, ok := state.Get("config").(*Config) + if !ok { + err := fmt.Errorf("error encountered obtaining docker config") state.Put("error", err) + ui.Error(err.Error()) return multistep.ActionHalt } - ui.Sayf("Finished building base image %q", imageId) + ui.Say("Building base image...") - cfg, ok := state.GetOk("config") - if !ok { - state.Put("error", errors.New("missing config in state; this is a docker plugin bug, please report upstream")) - return multistep.ActionHalt + if config.EcrLogin { + ui.Message("Fetching ECR credentials...") + + username, password, err := config.EcrGetLogin(config.LoginServer) + if err != nil { + err := fmt.Errorf("Error fetching ECR credentials: %s", err) + state.Put("error", err) + ui.Error(err.Error()) + return multistep.ActionHalt + } + + config.LoginUsername = username + config.LoginPassword = password } - config, ok := cfg.(*Config) - if !ok { - state.Put("error", fmt.Errorf("config object set but type (%s) doesn't match. This is a docker plugin bug, please report upstream", reflect.TypeOf(cfg).String())) + if config.Login || config.EcrLogin { + ui.Message("Logging in...") + err := driver.Login( + config.LoginServer, + config.LoginUsername, + config.LoginPassword) + if err != nil { + err := fmt.Errorf("Error logging in: %s", err) + state.Put("error", err) + ui.Error(err.Error()) + return multistep.ActionHalt + } + + defer func() { + ui.Message("Logging out...") + if err := driver.Logout(config.LoginServer); err != nil { + ui.Error(fmt.Sprintf("Error logging out: %s", err)) + } + }() + } + + imageId, err := driver.Build(s.buildArgs.BuildArgs()) + if err != nil { + state.Put("error", err) return multistep.ActionHalt } + ui.Sayf("Finished building base image %q", imageId) + config.Image = imageId s.ran = true diff --git a/docs-partials/builder/docker/Config-not-required.mdx b/docs-partials/builder/docker/Config-not-required.mdx index 62f274e..eebea3c 100644 --- a/docs-partials/builder/docker/Config-not-required.mdx +++ b/docs-partials/builder/docker/Config-not-required.mdx @@ -102,8 +102,9 @@ This cannot be used at the same time as `build`; instead, use `build.platform` -- `login` (bool) - This is used to login to dockerhub to pull a private base container. For - pushing to dockerhub, see the docker post-processors +- `login` (bool) - This is used to login to a private docker repository (e.g., dockerhub) + to build or pull a private base container. For pushing to a private + repository, see the docker post-processors. - `login_password` (string) - The password to use to authenticate to login. @@ -111,10 +112,10 @@ - `login_username` (string) - The username to use to authenticate to login. -- `ecr_login` (bool) - Defaults to false. If true, the builder will login in order to pull the - image from Amazon EC2 Container Registry (ECR). The builder only logs in - for the duration of the pull. If true login_server is required and - login, login_username, and login_password will be ignored. For more - information see the section on ECR. +- `ecr_login` (bool) - Defaults to false. If true, the builder will login in order to build or + pull the image from Amazon EC2 Container Registry (ECR). The builder + only logs in for the duration of the build or pull step. If true, + login_server is required and login, login_username, and login_password + will be ignored. For more information see the section on ECR. diff --git a/docs-partials/builder/docker/DockerfileBootstrapConfig-not-required.mdx b/docs-partials/builder/docker/DockerfileBootstrapConfig-not-required.mdx index 06bc5c5..6c122e6 100644 --- a/docs-partials/builder/docker/DockerfileBootstrapConfig-not-required.mdx +++ b/docs-partials/builder/docker/DockerfileBootstrapConfig-not-required.mdx @@ -4,6 +4,9 @@ Defaults to the directory from which we invoke packer. +- `arguments` (map[string]string) - A mapping of additional build args to provide. The key of + the object is the argument name, the value is the argument value. + - `platform` (string) - Set platform if server is multi-platform capable - `pull` (boolean) - Pull the image when building the base docker image. diff --git a/docs/builders/docker.mdx b/docs/builders/docker.mdx index a99b2aa..1e0ccba 100644 --- a/docs/builders/docker.mdx +++ b/docs/builders/docker.mdx @@ -43,6 +43,11 @@ source "docker" "example" { export_path = "image.tar" } +build { + sources = ["source.docker.example"] +} +``` + **JSON** ```json @@ -53,11 +58,6 @@ source "docker" "example" { } ``` -build { - sources = ["source.docker.example"] -} -``` - ## Basic Example: Commit Below is another example, the same as above but instead of exporting the diff --git a/version/version.go b/version/version.go index aec1f31..fcb2b65 100644 --- a/version/version.go +++ b/version/version.go @@ -6,8 +6,8 @@ package version import "github.com/hashicorp/packer-plugin-sdk/version" var ( - Version = "1.1.0" - VersionPrerelease = "" + Version = "1.1.1" + VersionPrerelease = "dev" VersionMetadata = "" PluginVersion = version.NewPluginVersion(Version, VersionPrerelease, VersionMetadata) )