packer-cn/builder/docker/config.go

211 lines
8.2 KiB
Go
Raw Normal View History

//go:generate struct-markdown
//go:generate mapstructure-to-hcl2 -type Config
2013-11-08 19:55:02 -05:00
package docker
import (
2013-11-09 14:47:32 -05:00
"fmt"
"os"
2017-04-04 16:39:01 -04:00
"github.com/hashicorp/packer/common"
"github.com/hashicorp/packer/helper/communicator"
"github.com/hashicorp/packer/helper/config"
"github.com/hashicorp/packer/packer"
"github.com/hashicorp/packer/template/interpolate"
"github.com/mitchellh/mapstructure"
2013-11-08 19:55:02 -05:00
)
var (
2015-08-19 16:12:16 -04:00
errArtifactNotUsed = fmt.Errorf("No instructions given for handling the artifact; expected commit, discard, or export_path")
errArtifactUseConflict = fmt.Errorf("Cannot specify more than one of commit, discard, and export_path")
errExportPathNotFile = fmt.Errorf("export_path must be a file, not a directory")
errImageNotSpecified = fmt.Errorf("Image must be specified")
)
2013-11-08 19:55:02 -05:00
type Config struct {
common.PackerConfig `mapstructure:",squash"`
Comm communicator.Config `mapstructure:",squash"`
2013-11-08 19:55:02 -05:00
// Set the author (e-mail) of a commit.
Author string `mapstructure:"author"`
// Dockerfile instructions to add to the commit. Example of instructions
// are CMD, ENTRYPOINT, ENV, and EXPOSE. Example: [ "USER ubuntu", "WORKDIR
// /app", "EXPOSE 8080" ]
Changes []string `mapstructure:"changes"`
// If true, the container will be committed to an image rather than exported.
Commit bool `mapstructure:"commit" required:"true"`
// The directory inside container to mount temp directory from host server
// for work [file provisioner](/docs/provisioners/file). This defaults
// to c:/packer-files on windows and /packer-files on other systems.
2019-06-06 10:29:25 -04:00
ContainerDir string `mapstructure:"container_dir" required:"false"`
// An array of devices which will be accessible in container when it's run
// without `--privileged` flag.
Device []string `mapstructure:"device" required:"false"`
// Throw away the container when the build is complete. This is useful for
// the [artifice
// post-processor](/docs/post-processors/artifice).
Discard bool `mapstructure:"discard" required:"true"`
// An array of additional [Linux
// capabilities](https://docs.docker.com/engine/reference/run/#runtime-privilege-and-linux-capabilities)
// to grant to the container.
CapAdd []string `mapstructure:"cap_add" required:"false"`
// An array of [Linux
// capabilities](https://docs.docker.com/engine/reference/run/#runtime-privilege-and-linux-capabilities)
// to drop from the container.
CapDrop []string `mapstructure:"cap_drop" required:"false"`
// Username (UID) to run remote commands with. You can also set the group
// name/ID if you want: (UID or UID:GID). You may need this if you get
// permission errors trying to run the shell or other provisioners.
ExecUser string `mapstructure:"exec_user" required:"false"`
// The path where the final container will be exported as a tar file.
ExportPath string `mapstructure:"export_path" required:"true"`
// The base image for the Docker container that will be started. This image
// will be pulled from the Docker registry if it doesn't already exist.
Image string `mapstructure:"image" required:"true"`
// Set a message for the commit.
Message string `mapstructure:"message" required:"true"`
// If true, run the docker container with the `--privileged` flag. This
// defaults to false if not set.
2019-06-06 10:29:25 -04:00
Privileged bool `mapstructure:"privileged" required:"false"`
Pty bool
// If true, the configured image will be pulled using `docker pull` prior
// to use. Otherwise, it is assumed the image already exists and can be
// used. This defaults to true if not set.
Pull bool `mapstructure:"pull" required:"false"`
// An array of arguments to pass to docker run in order to run the
2020-03-23 20:02:12 -04:00
// container. By default this is set to `["-d", "-i", "-t",
// "--entrypoint=/bin/sh", "--", "{{.Image}}"]` if you are using a linux
// container, and `["-d", "-i", "-t", "--entrypoint=powershell", "--",
// "{{.Image}}"]` if you are running a windows container. `{{.Image}}` is a
// template variable that corresponds to the image template option. Passing
// the entrypoint option this way will make it the default entrypoint of
// the resulting image, so running docker run -it --rm will start the
// docker image from the /bin/sh shell interpreter; you could run a script
// or another shell by running docker run -it --rm -c /bin/bash. If your
// docker image embeds a binary intended to be run often, you should
// consider changing the default entrypoint to point to it.
2019-06-06 10:29:25 -04:00
RunCommand []string `mapstructure:"run_command" required:"false"`
// An array of additional tmpfs volumes to mount into this container.
TmpFs []string `mapstructure:"tmpfs" required:"false"`
// A mapping of additional volumes to mount into this container. The key of
// the object is the host path, the value is the container path.
Volumes map[string]string `mapstructure:"volumes" required:"false"`
// If true, files uploaded to the container will be owned by the user the
// container is running as. If false, the owner will depend on the version
// of docker installed in the system. Defaults to true.
2019-06-06 10:29:25 -04:00
FixUploadOwner bool `mapstructure:"fix_upload_owner" required:"false"`
// If "true", tells Packer that you are building a Windows container
// running on a windows host. This is necessary for building Windows
// containers, because our normal docker bindings do not work for them.
WindowsContainer bool `mapstructure:"windows_container" required:"false"`
2013-11-09 01:00:57 -05:00
2015-08-18 19:55:29 -04:00
// This is used to login to dockerhub to pull a private base container. For
// pushing to dockerhub, see the docker post-processors
Login bool `mapstructure:"login" required:"false"`
// The password to use to authenticate to login.
2019-06-06 10:29:25 -04:00
LoginPassword string `mapstructure:"login_password" required:"false"`
// The server address to login to.
2019-06-06 10:29:25 -04:00
LoginServer string `mapstructure:"login_server" required:"false"`
// The username to use to authenticate to login.
2019-06-06 10:29:25 -04:00
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
2019-06-06 10:29:25 -04:00
// information see the section on ECR.
EcrLogin bool `mapstructure:"ecr_login" required:"false"`
AwsAccessConfig `mapstructure:",squash"`
2015-07-16 22:34:36 -04:00
ctx interpolate.Context
2013-11-08 19:55:02 -05:00
}
2013-11-09 14:47:32 -05:00
build using HCL2 (#8423) This follows #8232 which added the code to generate the code required to parse HCL files for each packer component. All old config files of packer will keep on working the same. Packer takes one argument. When a directory is passed, all files in the folder with a name ending with “.pkr.hcl” or “.pkr.json” will be parsed using the HCL2 format. When a file ending with “.pkr.hcl” or “.pkr.json” is passed it will be parsed using the HCL2 format. For every other case; the old packer style will be used. ## 1. the hcl2template pkg can create a packer.Build from a set of HCL (v2) files I had to make the packer.coreBuild (which is our one and only packer.Build ) a public struct with public fields ## 2. Components interfaces get a new ConfigSpec Method to read a file from an HCL file. This is a breaking change for packer plugins. a packer component can be a: builder/provisioner/post-processor each component interface now gets a `ConfigSpec() hcldec.ObjectSpec` which allows packer to tell what is the layout of the hcl2 config meant to configure that specific component. This ObjectSpec is sent through the wire (RPC) and a cty.Value is now sent through the already existing configuration entrypoints: Provisioner.Prepare(raws ...interface{}) error Builder.Prepare(raws ...interface{}) ([]string, error) PostProcessor.Configure(raws ...interface{}) error close #1768 Example hcl files: ```hcl // file amazon-ebs-kms-key/run.pkr.hcl build { sources = [ "source.amazon-ebs.first", ] provisioner "shell" { inline = [ "sleep 5" ] } post-processor "shell-local" { inline = [ "sleep 5" ] } } // amazon-ebs-kms-key/source.pkr.hcl source "amazon-ebs" "first" { ami_name = "hcl2-test" region = "us-east-1" instance_type = "t2.micro" kms_key_id = "c729958f-c6ba-44cd-ab39-35ab68ce0a6c" encrypt_boot = true source_ami_filter { filters { virtualization-type = "hvm" name = "amzn-ami-hvm-????.??.?.????????-x86_64-gp2" root-device-type = "ebs" } most_recent = true owners = ["amazon"] } launch_block_device_mappings { device_name = "/dev/xvda" volume_size = 20 volume_type = "gp2" delete_on_termination = "true" } launch_block_device_mappings { device_name = "/dev/xvdf" volume_size = 500 volume_type = "gp2" delete_on_termination = true encrypted = true } ami_regions = ["eu-central-1"] run_tags { Name = "packer-solr-something" stack-name = "DevOps Tools" } communicator = "ssh" ssh_pty = true ssh_username = "ec2-user" associate_public_ip_address = true } ```
2019-12-17 05:25:56 -05:00
func (c *Config) Prepare(raws ...interface{}) ([]string, error) {
2013-11-09 20:07:14 -05:00
c.FixUploadOwner = true
var md mapstructure.Metadata
err := config.Decode(c, &config.DecodeOpts{
Metadata: &md,
Interpolate: true,
InterpolateContext: &c.ctx,
InterpolateFilter: &interpolate.RenderFilter{
Exclude: []string{
"run_command",
},
},
}, raws...)
2013-11-09 20:07:14 -05:00
if err != nil {
build using HCL2 (#8423) This follows #8232 which added the code to generate the code required to parse HCL files for each packer component. All old config files of packer will keep on working the same. Packer takes one argument. When a directory is passed, all files in the folder with a name ending with “.pkr.hcl” or “.pkr.json” will be parsed using the HCL2 format. When a file ending with “.pkr.hcl” or “.pkr.json” is passed it will be parsed using the HCL2 format. For every other case; the old packer style will be used. ## 1. the hcl2template pkg can create a packer.Build from a set of HCL (v2) files I had to make the packer.coreBuild (which is our one and only packer.Build ) a public struct with public fields ## 2. Components interfaces get a new ConfigSpec Method to read a file from an HCL file. This is a breaking change for packer plugins. a packer component can be a: builder/provisioner/post-processor each component interface now gets a `ConfigSpec() hcldec.ObjectSpec` which allows packer to tell what is the layout of the hcl2 config meant to configure that specific component. This ObjectSpec is sent through the wire (RPC) and a cty.Value is now sent through the already existing configuration entrypoints: Provisioner.Prepare(raws ...interface{}) error Builder.Prepare(raws ...interface{}) ([]string, error) PostProcessor.Configure(raws ...interface{}) error close #1768 Example hcl files: ```hcl // file amazon-ebs-kms-key/run.pkr.hcl build { sources = [ "source.amazon-ebs.first", ] provisioner "shell" { inline = [ "sleep 5" ] } post-processor "shell-local" { inline = [ "sleep 5" ] } } // amazon-ebs-kms-key/source.pkr.hcl source "amazon-ebs" "first" { ami_name = "hcl2-test" region = "us-east-1" instance_type = "t2.micro" kms_key_id = "c729958f-c6ba-44cd-ab39-35ab68ce0a6c" encrypt_boot = true source_ami_filter { filters { virtualization-type = "hvm" name = "amzn-ami-hvm-????.??.?.????????-x86_64-gp2" root-device-type = "ebs" } most_recent = true owners = ["amazon"] } launch_block_device_mappings { device_name = "/dev/xvda" volume_size = 20 volume_type = "gp2" delete_on_termination = "true" } launch_block_device_mappings { device_name = "/dev/xvdf" volume_size = 500 volume_type = "gp2" delete_on_termination = true encrypted = true } ami_regions = ["eu-central-1"] run_tags { Name = "packer-solr-something" stack-name = "DevOps Tools" } communicator = "ssh" ssh_pty = true ssh_username = "ec2-user" associate_public_ip_address = true } ```
2019-12-17 05:25:56 -05:00
return nil, err
2013-11-09 20:07:14 -05:00
}
// Defaults
if len(c.RunCommand) == 0 {
c.RunCommand = []string{"-d", "-i", "-t", "--entrypoint=/bin/sh", "--", "{{.Image}}"}
if c.WindowsContainer {
c.RunCommand = []string{"-d", "-i", "-t", "--entrypoint=powershell", "--", "{{.Image}}"}
}
}
// Default Pull if it wasn't set
hasPull := false
for _, k := range md.Keys {
if k == "pull" {
hasPull = true
break
}
}
if !hasPull {
c.Pull = true
}
// Default to the normal Docker type
if c.Comm.Type == "" {
c.Comm.Type = "docker"
if c.WindowsContainer {
c.Comm.Type = "dockerWindowsContainer"
}
}
var errs *packer.MultiError
if es := c.Comm.Prepare(&c.ctx); len(es) > 0 {
errs = packer.MultiErrorAppend(errs, es...)
}
2013-11-09 14:47:32 -05:00
if c.Image == "" {
2015-08-19 16:12:16 -04:00
errs = packer.MultiErrorAppend(errs, errImageNotSpecified)
2013-11-09 20:07:14 -05:00
}
if (c.ExportPath != "" && c.Commit) || (c.ExportPath != "" && c.Discard) || (c.Commit && c.Discard) {
2015-08-19 16:12:16 -04:00
errs = packer.MultiErrorAppend(errs, errArtifactUseConflict)
}
if c.ExportPath == "" && !c.Commit && !c.Discard {
2015-08-19 16:12:16 -04:00
errs = packer.MultiErrorAppend(errs, errArtifactNotUsed)
}
if c.ExportPath != "" {
if fi, err := os.Stat(c.ExportPath); err == nil && fi.IsDir() {
2015-08-19 16:12:16 -04:00
errs = packer.MultiErrorAppend(errs, errExportPathNotFile)
}
}
2017-07-17 12:08:33 -04:00
if c.ContainerDir == "" {
if c.WindowsContainer {
c.ContainerDir = "c:/packer-files"
} else {
c.ContainerDir = "/packer-files"
}
2017-07-17 12:08:33 -04:00
}
if c.EcrLogin && c.LoginServer == "" {
errs = packer.MultiErrorAppend(errs, fmt.Errorf("ECR login requires login server to be provided."))
}
2013-11-09 20:07:14 -05:00
if errs != nil && len(errs.Errors) > 0 {
build using HCL2 (#8423) This follows #8232 which added the code to generate the code required to parse HCL files for each packer component. All old config files of packer will keep on working the same. Packer takes one argument. When a directory is passed, all files in the folder with a name ending with “.pkr.hcl” or “.pkr.json” will be parsed using the HCL2 format. When a file ending with “.pkr.hcl” or “.pkr.json” is passed it will be parsed using the HCL2 format. For every other case; the old packer style will be used. ## 1. the hcl2template pkg can create a packer.Build from a set of HCL (v2) files I had to make the packer.coreBuild (which is our one and only packer.Build ) a public struct with public fields ## 2. Components interfaces get a new ConfigSpec Method to read a file from an HCL file. This is a breaking change for packer plugins. a packer component can be a: builder/provisioner/post-processor each component interface now gets a `ConfigSpec() hcldec.ObjectSpec` which allows packer to tell what is the layout of the hcl2 config meant to configure that specific component. This ObjectSpec is sent through the wire (RPC) and a cty.Value is now sent through the already existing configuration entrypoints: Provisioner.Prepare(raws ...interface{}) error Builder.Prepare(raws ...interface{}) ([]string, error) PostProcessor.Configure(raws ...interface{}) error close #1768 Example hcl files: ```hcl // file amazon-ebs-kms-key/run.pkr.hcl build { sources = [ "source.amazon-ebs.first", ] provisioner "shell" { inline = [ "sleep 5" ] } post-processor "shell-local" { inline = [ "sleep 5" ] } } // amazon-ebs-kms-key/source.pkr.hcl source "amazon-ebs" "first" { ami_name = "hcl2-test" region = "us-east-1" instance_type = "t2.micro" kms_key_id = "c729958f-c6ba-44cd-ab39-35ab68ce0a6c" encrypt_boot = true source_ami_filter { filters { virtualization-type = "hvm" name = "amzn-ami-hvm-????.??.?.????????-x86_64-gp2" root-device-type = "ebs" } most_recent = true owners = ["amazon"] } launch_block_device_mappings { device_name = "/dev/xvda" volume_size = 20 volume_type = "gp2" delete_on_termination = "true" } launch_block_device_mappings { device_name = "/dev/xvdf" volume_size = 500 volume_type = "gp2" delete_on_termination = true encrypted = true } ami_regions = ["eu-central-1"] run_tags { Name = "packer-solr-something" stack-name = "DevOps Tools" } communicator = "ssh" ssh_pty = true ssh_username = "ec2-user" associate_public_ip_address = true } ```
2019-12-17 05:25:56 -05:00
return nil, errs
2013-11-09 14:47:32 -05:00
}
build using HCL2 (#8423) This follows #8232 which added the code to generate the code required to parse HCL files for each packer component. All old config files of packer will keep on working the same. Packer takes one argument. When a directory is passed, all files in the folder with a name ending with “.pkr.hcl” or “.pkr.json” will be parsed using the HCL2 format. When a file ending with “.pkr.hcl” or “.pkr.json” is passed it will be parsed using the HCL2 format. For every other case; the old packer style will be used. ## 1. the hcl2template pkg can create a packer.Build from a set of HCL (v2) files I had to make the packer.coreBuild (which is our one and only packer.Build ) a public struct with public fields ## 2. Components interfaces get a new ConfigSpec Method to read a file from an HCL file. This is a breaking change for packer plugins. a packer component can be a: builder/provisioner/post-processor each component interface now gets a `ConfigSpec() hcldec.ObjectSpec` which allows packer to tell what is the layout of the hcl2 config meant to configure that specific component. This ObjectSpec is sent through the wire (RPC) and a cty.Value is now sent through the already existing configuration entrypoints: Provisioner.Prepare(raws ...interface{}) error Builder.Prepare(raws ...interface{}) ([]string, error) PostProcessor.Configure(raws ...interface{}) error close #1768 Example hcl files: ```hcl // file amazon-ebs-kms-key/run.pkr.hcl build { sources = [ "source.amazon-ebs.first", ] provisioner "shell" { inline = [ "sleep 5" ] } post-processor "shell-local" { inline = [ "sleep 5" ] } } // amazon-ebs-kms-key/source.pkr.hcl source "amazon-ebs" "first" { ami_name = "hcl2-test" region = "us-east-1" instance_type = "t2.micro" kms_key_id = "c729958f-c6ba-44cd-ab39-35ab68ce0a6c" encrypt_boot = true source_ami_filter { filters { virtualization-type = "hvm" name = "amzn-ami-hvm-????.??.?.????????-x86_64-gp2" root-device-type = "ebs" } most_recent = true owners = ["amazon"] } launch_block_device_mappings { device_name = "/dev/xvda" volume_size = 20 volume_type = "gp2" delete_on_termination = "true" } launch_block_device_mappings { device_name = "/dev/xvdf" volume_size = 500 volume_type = "gp2" delete_on_termination = true encrypted = true } ami_regions = ["eu-central-1"] run_tags { Name = "packer-solr-something" stack-name = "DevOps Tools" } communicator = "ssh" ssh_pty = true ssh_username = "ec2-user" associate_public_ip_address = true } ```
2019-12-17 05:25:56 -05:00
return nil, nil
2013-11-09 14:47:32 -05:00
}