From 3da99f7bdc18a6c2817320fb4d619fb6aead2e82 Mon Sep 17 00:00:00 2001 From: Megan Marsh Date: Thu, 12 Nov 2020 14:01:41 -0800 Subject: [PATCH] add more documentation to the packages in common directory --- common/adapter/doc.go | 8 +++++++ common/bootcommand/doc.go | 13 +++++++++++ common/chroot/doc.go | 25 ++++++++++++++++++++++ common/command.go | 9 +++++++- common/commonsteps/doc.go | 16 ++++++++++++++ common/filelock/doc.go | 6 ++++++ common/guestexec/doc.go | 12 +++++++++++ common/net/configure_port.go | 10 ++++----- common/packer_config.go | 3 ++- common/packerbuilderdata/generated_data.go | 8 ++++--- common/random/string.go | 16 ++++++++++++-- common/retry/retry.go | 11 +++++++++- common/shell-local/doc.go | 14 ++++++++++++ common/shell/shell.go | 12 ++++++++++- common/shutdowncommand/config.go | 7 ++++++ common/template/funcs.go | 8 ++++++- 16 files changed, 163 insertions(+), 15 deletions(-) create mode 100644 common/adapter/doc.go create mode 100644 common/bootcommand/doc.go create mode 100644 common/chroot/doc.go create mode 100644 common/commonsteps/doc.go create mode 100644 common/filelock/doc.go create mode 100644 common/guestexec/doc.go create mode 100644 common/shell-local/doc.go diff --git a/common/adapter/doc.go b/common/adapter/doc.go new file mode 100644 index 000000000..f079dc594 --- /dev/null +++ b/common/adapter/doc.go @@ -0,0 +1,8 @@ +/* +Package adapter helps command line tools connect to the guest via a Packer +communicator. A typical use is for custom provisioners that wrap command line +tools. For example, the Ansible provisioner and the Inspec provisioner both +use this package to proxy communicator calls. +*/ + +package adapter diff --git a/common/bootcommand/doc.go b/common/bootcommand/doc.go new file mode 100644 index 000000000..9a908528c --- /dev/null +++ b/common/bootcommand/doc.go @@ -0,0 +1,13 @@ +/* +Package bootcommand generates and sends boot commands to the remote instance. + +This package is relevant to people who want to create new builders, particularly +builders with the capacity to build a VM from an iso. + +You can choose between three different drivers to send the command: a vnc +driver, a usb driver, and a PX-XT keyboard driver. The driver you choose will +depend on what kind of keyboard codes your hypervisor expects, and how you want +to implement the connection. +*/ + +package bootcommand diff --git a/common/chroot/doc.go b/common/chroot/doc.go new file mode 100644 index 000000000..d433e0618 --- /dev/null +++ b/common/chroot/doc.go @@ -0,0 +1,25 @@ +/* +Package chroot provides convenience tooling specific to chroot builders. + +Chroot builders work by creating a new volume from an existing source image and +attaching it into an already-running instance. Once attached, a chroot is used +to provision the system within that volume. After provisioning, the volume is +detached, snapshotted, and a cloud-specific image is made. + +Using this process, minutes can be shaved off image build processes because a +new instance doesn't need to be launched in the cloud before provisioning can +take place. + +There are some restrictions, however. The host instance where the volume is +attached to must be a similar system (generally the same OS version, kernel +versions, etc.) as the image being built. Additionally, this process is much +more expensive because the instance used to perform the build must be kept +running persistently in order to build images, whereas the other non-chroot +cloud image builders start instances on-demand to build images as needed. + +The HashiCorp-maintained Amazon and Azure builder plugins have chroot builders +which use this option and can serve as an example for how the chroot steps and +communicator are used. +*/ + +package chroot diff --git a/common/command.go b/common/command.go index eaceb75a2..cdc8f7b95 100644 --- a/common/command.go +++ b/common/command.go @@ -4,8 +4,15 @@ import ( "os/exec" ) -// CommandWrapper is a type that given a command, will possibly modify that +// CommandWrapper is a type that given a command, will modify that // command in-flight. This might return an error. +// For example, your command could be `foo` and your CommandWrapper could be +// func(s string) (string, error) { +// return fmt.Sprintf("/bin/sh/ %s", s) +// } +// Using the CommandWrapper, you can set environment variables or perform +// string interpolation once rather than many times, to save some lines of code +// if similar wrapping needs to be performed many times during a plugin run. type CommandWrapper func(string) (string, error) // ShellCommand takes a command string and returns an *exec.Cmd to execute diff --git a/common/commonsteps/doc.go b/common/commonsteps/doc.go new file mode 100644 index 000000000..b5b7e90af --- /dev/null +++ b/common/commonsteps/doc.go @@ -0,0 +1,16 @@ +/* +The commonsteps package contains the multistep runner that comprises the main +architectural convention of Packer builder plugins. It enables builders +to respect global Packer flags like "on-error" and "debug". It also contains +a selection of convenience "multistep" steps that perform globally relevant +tasks that many or most builders will want to implement -- for example, +launching Packer's internal HTTP server for serving files to the instance. + +It also provides step_provision, which contains the hooks necessary for allowing +provisioners to run inside your builder. + +While it is possible to create a simple builder without using the multistep +runner or step_provision, your builder will lack core Packer functionality. +*/ + +package commonsteps diff --git a/common/filelock/doc.go b/common/filelock/doc.go new file mode 100644 index 000000000..28a5c9ad6 --- /dev/null +++ b/common/filelock/doc.go @@ -0,0 +1,6 @@ +/* +Package filelock makes it easy to create and check file locks for concurrent +processes. +*/ + +package filelock diff --git a/common/guestexec/doc.go b/common/guestexec/doc.go new file mode 100644 index 000000000..391ee5c29 --- /dev/null +++ b/common/guestexec/doc.go @@ -0,0 +1,12 @@ +/* +Package guestexec provides a shim for running common operating system commands +on the guest/remote instance that is being provisioned. It helps provisioners +which need to perform operating-system specific calls do so in a way that is +simple and repeatable. + +Note that to successfully use this package your provisioner must have knowledge +of the guest type, which is not information that builders generally collect -- +your provisioner will have to require guest information in its config. +*/ + +package guestexec diff --git a/common/net/configure_port.go b/common/net/configure_port.go index 796acd5e6..950e7a892 100644 --- a/common/net/configure_port.go +++ b/common/net/configure_port.go @@ -17,11 +17,11 @@ import ( var _ net.Listener = &Listener{} -// Listener wraps a net.Lister with some magic packer capabilies. For example -// until you call Listener.Close, any call to ListenRangeConfig.Listen cannot -// bind to Port. Packer tries tells moving parts which port they can use, but -// often the port has to be released before a 3rd party is started, like a VNC -// server. +// Listener wraps a net.Lister with some Packer-specific capabilies. For +// example, until you call Listener.Close, any call to ListenRangeConfig.Listen +// cannot bind to a Port. Packer tries to tell moving parts which port they can +// use, but often the port has to be released before a 3rd party is started, +// like a VNC server. type Listener struct { // Listener can be closed but Port will be file locked by packer until // Close is called. diff --git a/common/packer_config.go b/common/packer_config.go index 028e58f17..2a666bc5d 100644 --- a/common/packer_config.go +++ b/common/packer_config.go @@ -2,7 +2,8 @@ package common // PackerConfig is a struct that contains the configuration keys that // are sent by packer, properly tagged already so mapstructure can load -// them. Embed this structure into your configuration class to get it. +// them. Embed this structure into your configuration class to get access to +// this information from the Packer Core. type PackerConfig struct { PackerBuildName string `mapstructure:"packer_build_name"` PackerBuilderType string `mapstructure:"packer_builder_type"` diff --git a/common/packerbuilderdata/generated_data.go b/common/packerbuilderdata/generated_data.go index de62677f6..932627297 100644 --- a/common/packerbuilderdata/generated_data.go +++ b/common/packerbuilderdata/generated_data.go @@ -7,9 +7,11 @@ import "github.com/hashicorp/packer/helper/multistep" const PlaceholderMsg = "To set this dynamically in the Packer template, " + "you must use the `build` function" -// GeneratedData manages variables exported by a builder after -// it started. It uses the builder's multistep.StateBag internally, make sure it -// is not nil before calling any functions. +// GeneratedData manages variables created and exported by a builder after +// it starts, so that provisioners and post-processors can have access to +// build data generated at runtime -- for example, instance ID or instance IP +// address. Internally, it uses the builder's multistep.StateBag. The user +// must make sure that the State field is not is not nil before calling Put(). type GeneratedData struct { // The builder's StateBag State multistep.StateBag diff --git a/common/random/string.go b/common/random/string.go index 17926c401..bac4a355b 100644 --- a/common/random/string.go +++ b/common/random/string.go @@ -19,11 +19,23 @@ var ( var rnd = rand.New(rand.NewSource(time.Now().UnixNano() + int64(os.Getpid()))) -func Numbers(length int) string { return String(PossibleNumbers, length) } -func AlphaNum(length int) string { return String(PossibleAlphaNum, length) } +// Numbers returns a random numeric string of the given length +func Numbers(length int) string { return String(PossibleNumbers, length) } + +// AlphaNum returns a random alphanumeric string of the given length. The +// returned string can contain both uppercase and lowercase letters. +func AlphaNum(length int) string { return String(PossibleAlphaNum, length) } + +// AlphaNumLower returns a random alphanumeric string of the given length. The +// returned string can contain lowercase letters, but not uppercase. func AlphaNumLower(length int) string { return String(PossibleAlphaNumLower, length) } + +// AlphaNumUpper returns a random alphanumeric string of the given length. The +// returned string can contain uppercase letters, but not lowercase. func AlphaNumUpper(length int) string { return String(PossibleAlphaNumUpper, length) } +// String returns a random string of the given length, using only the component +// characters provided in the "chooseFrom" string. func String(chooseFrom string, length int) (randomString string) { cflen := len(chooseFrom) bytes := make([]byte, length) diff --git a/common/retry/retry.go b/common/retry/retry.go index 746a6fc28..61e47050e 100644 --- a/common/retry/retry.go +++ b/common/retry/retry.go @@ -36,7 +36,16 @@ func (err *RetryExhaustedError) Error() string { return fmt.Sprintf("retry count exhausted. Last err: %s", err.Err) } -// Run fn until context is cancelled up until StartTimeout time has passed. +// Run will repeatedly retry the proivided fn within the constraints set in the +// retry Config. It will retry until one of the following conditions is met: +// - The provided context is cancelled. +// - The Config.StartTimeout time has passed. +// - The function returns without an error. +// - The maximum number of tries, Config.Tries is exceeded. +// - The function returns with an error that does not satisfy conditions +// set in the Config.ShouldRetry function. +// If the given function (fn) does not return an error, then Run will return +// nil. Otherwise, Run will return a relevant error. func (cfg Config) Run(ctx context.Context, fn func(context.Context) error) error { retryDelay := func() time.Duration { return 2 * time.Second } if cfg.RetryDelay != nil { diff --git a/common/shell-local/doc.go b/common/shell-local/doc.go new file mode 100644 index 000000000..a27dec1fe --- /dev/null +++ b/common/shell-local/doc.go @@ -0,0 +1,14 @@ +/* +Package shell-local is designed to make it easier to shell out locally on the +machine running Packer. The top level tools in this package are probably not +relevant to plugin maintainers, as they are implementation details shared +between the HashiCorp-maintained shell-local provisioner and shell-local +post-processor. + +The localexec sub-package can be used in any plugins that need local shell +access, whether that is in a driver for a hypervisor, or a command to a third +party cli tool. Please make sure that any third party tool dependencies are +noted in your plugin's documentation. +*/ + +package shell_local diff --git a/common/shell/shell.go b/common/shell/shell.go index 2484de74d..845e158eb 100644 --- a/common/shell/shell.go +++ b/common/shell/shell.go @@ -3,7 +3,17 @@ package shell import "github.com/hashicorp/packer/common" -// Provisioner contains common fields to all shell provisioners +// Provisioner contains common fields to all shell provisioners. +// It is provided as a convenience to encourage plugin developers to +// consider implementing these options, which we believe are valuable for all +// shell-type provisioners. It also helps guarantee that option names for +// similar options are the same across the various shell provisioners. +// Validation and defaulting are left to the maintainer because appropriate +// values and defaults will be different depending on which shell is used. +// To use the Provisioner struct, embed it in your shell provisioner's config +// using the `mapstructure:",squash"` struct tag. Examples can be found in the +// HashiCorp-maintained "shell", "shell-local", "windows-shell" and "powershell" +// provisioners. type Provisioner struct { common.PackerConfig `mapstructure:",squash"` diff --git a/common/shutdowncommand/config.go b/common/shutdowncommand/config.go index ba8427206..108b56d85 100644 --- a/common/shutdowncommand/config.go +++ b/common/shutdowncommand/config.go @@ -8,6 +8,13 @@ import ( "github.com/hashicorp/packer/packer-plugin-sdk/template/interpolate" ) +// ShutdownConfig defines implementation details for shutting down a VM once it +// is done provisioned. +// It is provided as a convenience to encourage builder developers to +// consider implementing these options, which we believe are valuable for all +// builders. It also helps guarantee that option names for similar options +// are the same across the various builders. Embed it in your builder config +// using the `mapstructure:",squash"` struct tag. type ShutdownConfig struct { // The command to use to gracefully shut down the machine once all // provisioning is complete. By default this is an empty string, which diff --git a/common/template/funcs.go b/common/template/funcs.go index 01d19d25a..5c89553c0 100644 --- a/common/template/funcs.go +++ b/common/template/funcs.go @@ -26,7 +26,8 @@ func DeprecatedTemplateFunc(funcName, useInstead string, deprecated func(string) } } -// Vault retrieves a secret from an HC vault KV store +// Vault retrieves a secret from a HashiCorp Vault KV store. +// It assumes the necessary environment variables are set. func Vault(path string, key string) (string, error) { if token := os.Getenv("VAULT_TOKEN"); token == "" { @@ -64,6 +65,8 @@ func Vault(path string, key string) (string, error) { return "", errors.New("Vault path does not contain the requested key") } +// Consul retrieves a value from a HashiCorp Consul KV store. +// It assumes the necessary environment variables are set. func Consul(k string) (string, error) { consulConfig := consulapi.DefaultConfig() client, err := consulapi.NewClient(consulConfig) @@ -88,6 +91,9 @@ func Consul(k string) (string, error) { return value, nil } +// GetAwsSecret retrieves a value from an AWS Secrets Manager. +// It assumes that credentials are properly set in the AWS SDK's credential +// chain. func GetAWSSecret(name, key string) (string, error) { // Check if at least 1 parameter has been used if len(name) == 0 {