From 17d4c4396c182ba77518d9d06f639b0ee49f295c Mon Sep 17 00:00:00 2001 From: Seth Vargo Date: Tue, 3 Feb 2015 16:27:57 -0500 Subject: [PATCH 01/13] Always create the build configuration if it does not exist --- command/push.go | 70 ++++++++++++++----------------------------------- 1 file changed, 19 insertions(+), 51 deletions(-) diff --git a/command/push.go b/command/push.go index 42c1bc465..f0ff1e1e4 100644 --- a/command/push.go +++ b/command/push.go @@ -32,12 +32,10 @@ type pushUploadFn func( io.Reader, *uploadOpts) (<-chan struct{}, <-chan error, error) func (c *PushCommand) Run(args []string) int { - var create bool var token string f := flag.NewFlagSet("push", flag.ContinueOnError) f.Usage = func() { c.Ui.Error(c.Help()) } - f.BoolVar(&create, "create", false, "create") f.StringVar(&token, "token", "", "token") if err := f.Parse(args); err != nil { return 1 @@ -169,12 +167,6 @@ func (c *PushCommand) Run(args []string) int { "Builds: %s\n\n", strings.Join(badBuilds, ", "))) } - // Create the build config if it doesn't currently exist. - if err := c.create(uploadOpts.Slug, create); err != nil { - c.Ui.Error(err.Error()) - return 1 - } - // Start the archiving process r, err := archive.CreateArchive(path, &opts) if err != nil { @@ -217,16 +209,18 @@ func (*PushCommand) Help() string { helpText := ` Usage: packer push [options] TEMPLATE - Push the template and the files it needs to a Packer build service. - This will not initiate any builds, it will only update the templates - used for builds. + Push the given template and supporting files to a Packer build service such as + Atlas. - The configuration about what is pushed is configured within the - template's "push" section. + If a build configuration for the given template does not exist, it will be + created automatically. If the build configuration already exists, a new + version will be created with this template and the supporting files. -Options: + Additional configuration options (such as the Atlas server URL and files to + include) may be specified in the "push" section of the Packer template. Please + see the online documentation for more information about these configurables. - -create Create the build configuration if it doesn't exist. +Options: -token= Access token to use to upload. If blank, the ATLAS_TOKEN environmental variable will be used. @@ -236,40 +230,7 @@ Options: } func (*PushCommand) Synopsis() string { - return "push template files to a Packer build service" -} - -func (c *PushCommand) create(name string, create bool) error { - if c.uploadFn != nil { - return nil - } - - // Separate the slug into the user and name components - user, name, err := atlas.ParseSlug(name) - if err != nil { - return fmt.Errorf("Malformed push name: %s", err) - } - - // Check if it exists. If so, we're done. - if _, err := c.client.BuildConfig(user, name); err == nil { - return nil - } else if err != atlas.ErrNotFound { - return err - } - - // Otherwise, show an error if we're not creating. - if !create { - return fmt.Errorf( - "Push target doesn't exist: %s. Either create this online via\n"+ - "the website or pass the -create flag.", name) - } - - // Create it - if err := c.client.CreateBuildConfig(user, name); err != nil { - return err - } - - return nil + return "push a template and supporting files to a Packer build service" } func (c *PushCommand) upload( @@ -284,10 +245,17 @@ func (c *PushCommand) upload( return nil, nil, fmt.Errorf("upload: %s", err) } - // Get the app + // Get the build configuration bc, err := c.client.BuildConfig(user, name) if err != nil { - return nil, nil, fmt.Errorf("upload: %s", err) + if err == atlas.ErrNotFound { + // Build configuration doesn't exist, attempt to create it + bc, err = c.client.CreateBuildConfig(user, name) + } + + if err != nil { + return nil, nil, fmt.Errorf("upload: %s", err) + } } // Build the version to send up From 677ddd34bd812325ccc3d489b24c02388102f2e8 Mon Sep 17 00:00:00 2001 From: Seth Vargo Date: Tue, 3 Feb 2015 17:36:57 -0500 Subject: [PATCH 02/13] Update default value for push VCS documentation --- website/source/docs/templates/push.html.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/website/source/docs/templates/push.html.markdown b/website/source/docs/templates/push.html.markdown index 1f97a3048..9c3b6cc24 100644 --- a/website/source/docs/templates/push.html.markdown +++ b/website/source/docs/templates/push.html.markdown @@ -62,4 +62,4 @@ each category, the available configuration keys are alphabetized. * `vcs` (bool) - If true, Packer will detect your VCS (if there is one) and only upload the files that are tracked by the VCS. This is useful - for automatically excluding ignored files. This defaults to true. + for automatically excluding ignored files. This defaults to false. From 75b4f50f8f164047006890d611790dd02a15fa37 Mon Sep 17 00:00:00 2001 From: Seth Vargo Date: Tue, 3 Feb 2015 17:37:15 -0500 Subject: [PATCH 03/13] Add examples for Push template configuration --- .../source/docs/templates/push.html.markdown | 34 ++++++++++++++++--- 1 file changed, 30 insertions(+), 4 deletions(-) diff --git a/website/source/docs/templates/push.html.markdown b/website/source/docs/templates/push.html.markdown index 9c3b6cc24..73b37feef 100644 --- a/website/source/docs/templates/push.html.markdown +++ b/website/source/docs/templates/push.html.markdown @@ -46,8 +46,8 @@ each category, the available configuration keys are alphabetized. this is `https://atlas.hashicorp.com`. * `base_dir` (string) - The base directory of the files to upload. This - will be the CWD when the build service executes your template. This - path is relative to the template. + will be the current working directory when the build service executes your + template. This path is relative to the template. * `include` (array of strings) - Glob patterns to include relative to the `base_dir`. If this is specified, only files that match the include @@ -57,9 +57,35 @@ each category, the available configuration keys are alphabetized. the `base_dir`. * `token` (string) - An access token to use to authenticate to the build - service. For Atlas, you can retrieve this access token in your account - section by clicking your account name in the upper right corner. + service. * `vcs` (bool) - If true, Packer will detect your VCS (if there is one) and only upload the files that are tracked by the VCS. This is useful for automatically excluding ignored files. This defaults to false. + +## Examples + +A push configuration section with minimal options: + +```javascript +{ + "push": { + "name": "hashicorp/precise64" + } +} +``` + +A push configuration specifying Packer to inspect the VCS and list individual +files to include: + +```javascript +{ + "push": { + "name": "hashicorp/precise64", + "vcs": true, + "include": [ + "other_file/outside_of.vcs" + ] + } +} +``` From 8194846d8631c09487879828b7f872880199e561 Mon Sep 17 00:00:00 2001 From: Seth Vargo Date: Tue, 3 Feb 2015 17:37:55 -0500 Subject: [PATCH 04/13] Update push command docs to remove `-token` --- .../docs/command-line/push.html.markdown | 39 +++++++++++-------- 1 file changed, 23 insertions(+), 16 deletions(-) diff --git a/website/source/docs/command-line/push.html.markdown b/website/source/docs/command-line/push.html.markdown index 10165cc22..177892150 100644 --- a/website/source/docs/command-line/push.html.markdown +++ b/website/source/docs/command-line/push.html.markdown @@ -7,27 +7,34 @@ description: |- # Command-Line: Push -The `packer push` Packer command takes a template and pushes it to a build -service. The build service will automatically build your Packer template and -expose the artifacts. +The `packer push` Packer command takes a template and pushes it to a Packer +build service such as [HashiCorp's Atlas](https://atlas.hashicorp.com). The +build service will automatically build your Packer template and expose the +artifacts. -This command currently only sends templates to -[Atlas](https://atlas.hashicorp.com) by HashiCorp, but the command will -be pluggable in the future with alternate implementations. - -External build services such as Atlas make it easy to iterate on Packer -templates, especially when the builder you're running may not be easily +External build services such as HashiCorp's Atlas make it easy to iterate on +Packer templates, especially when the builder you are running may not be easily accessable (such as developing `qemu` builders on Mac or Windows). -For the `push` command to work, the -[push configuration](/docs/templates/push.html) +For the `push` command to work, the [push configuration](/docs/templates/push.html) must be completed within the template. ## Options -* `-create=true` - If the build configuration matching the name of the push - doesn't exist, it will be created if this is true. This defaults to true. +* `-token` - An access token for authenticating the push to the Packer build + service such as Atlas. This can also be specified within the push + configuration in the template. + +## Examples + +Push a Packer template: + +```shell +$ packer push template.json +``` + +Push a Packer template with a custom token: -* `-token=FOO` - An access token for authenticating the push. This can also - be specified within the push configuration in the template. By setting this - in the template, you can take advantage of user variables. +```shell +$ packer push -token ABCD1234 template.json +``` From 08ba23f10f96b7eb4a1ffa845904c5c51b117ebb Mon Sep 17 00:00:00 2001 From: Seth Vargo Date: Tue, 3 Feb 2015 18:13:15 -0500 Subject: [PATCH 05/13] Unset the ATLAS_TOKEN environment variable before that test --- post-processor/atlas/post-processor_test.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/post-processor/atlas/post-processor_test.go b/post-processor/atlas/post-processor_test.go index db35b8790..1fe629a88 100644 --- a/post-processor/atlas/post-processor_test.go +++ b/post-processor/atlas/post-processor_test.go @@ -9,6 +9,10 @@ import ( ) func TestPostProcessorConfigure(t *testing.T) { + currentEnv := os.Getenv("ATLAS_TOKEN") + os.Unsetenv("ATLAS_TOKEN") + defer os.Setenv("ATLAS_TOKEN", currentEnv) + var p PostProcessor if err := p.Configure(validDefaults()); err != nil { t.Fatalf("err: %s", err) From 5d37c584575b0b2bb165c5559d6b02c7522f505f Mon Sep 17 00:00:00 2001 From: Seth Vargo Date: Tue, 3 Feb 2015 18:14:21 -0500 Subject: [PATCH 06/13] Store the RawContents of the template on the template object This allows children to get the raw templates without re-reading the file. --- packer/template.go | 9 ++++++--- packer/template_test.go | 4 ++++ 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/packer/template.go b/packer/template.go index 5cbef4fac..717ae7682 100644 --- a/packer/template.go +++ b/packer/template.go @@ -3,15 +3,16 @@ package packer import ( "bytes" "fmt" - "github.com/hashicorp/go-version" - "github.com/mitchellh/mapstructure" - jsonutil "github.com/mitchellh/packer/common/json" "io" "io/ioutil" "os" "sort" "text/template" "time" + + "github.com/hashicorp/go-version" + "github.com/mitchellh/mapstructure" + jsonutil "github.com/mitchellh/packer/common/json" ) // The rawTemplate struct represents the structure of a template read @@ -33,6 +34,7 @@ type rawTemplate struct { // The Template struct represents a parsed template, parsed into the most // completed form it can be without additional processing by the caller. type Template struct { + RawContents []byte Description string Variables map[string]RawVariable Builders map[string]RawBuilderConfig @@ -163,6 +165,7 @@ func ParseTemplate(data []byte, vars map[string]string) (t *Template, err error) } t = &Template{} + t.RawContents = data t.Description = rawTpl.Description t.Variables = make(map[string]RawVariable) t.Builders = make(map[string]RawBuilderConfig) diff --git a/packer/template_test.go b/packer/template_test.go index d42895665..bf11fc7d0 100644 --- a/packer/template_test.go +++ b/packer/template_test.go @@ -58,6 +58,10 @@ func TestParseTemplateFile_basic(t *testing.T) { if len(result.Builders) != 1 { t.Fatalf("bad: %#v", result.Builders) } + + if string(result.RawContents) != data { + t.Fatalf("expected %q to be %q", result.RawContents, data) + } } func TestParseTemplateFile_minPackerVersionBad(t *testing.T) { From 8e0c7ace3aac455b0e51d20009c014406060aa21 Mon Sep 17 00:00:00 2001 From: Seth Vargo Date: Tue, 3 Feb 2015 18:15:02 -0500 Subject: [PATCH 07/13] Add a -message option to pushes --- command/push.go | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/command/push.go b/command/push.go index f0ff1e1e4..9cb9e6b67 100644 --- a/command/push.go +++ b/command/push.go @@ -33,10 +33,12 @@ type pushUploadFn func( func (c *PushCommand) Run(args []string) int { var token string + var message string f := flag.NewFlagSet("push", flag.ContinueOnError) f.Usage = func() { c.Ui.Error(c.Help()) } f.StringVar(&token, "token", "", "token") + f.StringVar(&message, "message", "", "message") if err := f.Parse(args); err != nil { return 1 } @@ -222,8 +224,10 @@ Usage: packer push [options] TEMPLATE Options: - -token= Access token to use to upload. If blank, the - ATLAS_TOKEN environmental variable will be used. + -message= A message to identify the purpose or changes in this + Packer template much like a VCS commit message + + -token= The access token to use to when uploading ` return strings.TrimSpace(helpText) From 7911d988367185a99f246541b171633bc9904fad Mon Sep 17 00:00:00 2001 From: Seth Vargo Date: Tue, 3 Feb 2015 18:32:57 -0500 Subject: [PATCH 08/13] Warn about pushing sensitive data in Packer templates --- website/source/docs/command-line/push.html.markdown | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/website/source/docs/command-line/push.html.markdown b/website/source/docs/command-line/push.html.markdown index 177892150..bf344aadc 100644 --- a/website/source/docs/command-line/push.html.markdown +++ b/website/source/docs/command-line/push.html.markdown @@ -16,6 +16,10 @@ External build services such as HashiCorp's Atlas make it easy to iterate on Packer templates, especially when the builder you are running may not be easily accessable (such as developing `qemu` builders on Mac or Windows). +!> The Packer build service will receive the raw copy of your Packer template +when you push. **If you have sensitive data in your Packer template, you should +move that data into Packer variables or environment variables!** + For the `push` command to work, the [push configuration](/docs/templates/push.html) must be completed within the template. From 983b0b89880c50329043a13be91b22d07cb6820e Mon Sep 17 00:00:00 2001 From: Seth Vargo Date: Tue, 3 Feb 2015 18:34:05 -0500 Subject: [PATCH 09/13] Allow specifying a -message when pushing --- command/push.go | 23 +++++++++++++------ .../docs/command-line/push.html.markdown | 6 ++++- 2 files changed, 21 insertions(+), 8 deletions(-) diff --git a/command/push.go b/command/push.go index 9cb9e6b67..6ba27bada 100644 --- a/command/push.go +++ b/command/push.go @@ -38,6 +38,7 @@ func (c *PushCommand) Run(args []string) int { f := flag.NewFlagSet("push", flag.ContinueOnError) f.Usage = func() { c.Ui.Error(c.Help()) } f.StringVar(&token, "token", "", "token") + f.StringVar(&message, "m", "", "message") f.StringVar(&message, "message", "", "message") if err := f.Parse(args); err != nil { return 1 @@ -149,6 +150,13 @@ func (c *PushCommand) Run(args []string) int { uploadOpts.Builds[b.Name] = info } + // Add the upload metadata + metadata := make(map[string]interface{}) + if message != "" { + metadata["message"] = message + } + uploadOpts.Metadata = metadata + // Warn about builds not having post-processors. var badBuilds []string for name, b := range uploadOpts.Builds { @@ -224,10 +232,10 @@ Usage: packer push [options] TEMPLATE Options: - -message= A message to identify the purpose or changes in this - Packer template much like a VCS commit message + -m, -message= A message to identify the purpose or changes in this + Packer template much like a VCS commit message - -token= The access token to use to when uploading + -token= The access token to use to when uploading ` return strings.TrimSpace(helpText) @@ -279,7 +287,7 @@ func (c *PushCommand) upload( // Start the upload doneCh, errCh := make(chan struct{}), make(chan error) go func() { - err := c.client.UploadBuildConfigVersion(&version, r, r.Size) + err := c.client.UploadBuildConfigVersion(&version, opts.Metadata, r, r.Size) if err != nil { errCh <- err return @@ -292,9 +300,10 @@ func (c *PushCommand) upload( } type uploadOpts struct { - URL string - Slug string - Builds map[string]*uploadBuildInfo + URL string + Slug string + Builds map[string]*uploadBuildInfo + Metadata map[string]interface{} } type uploadBuildInfo struct { diff --git a/website/source/docs/command-line/push.html.markdown b/website/source/docs/command-line/push.html.markdown index bf344aadc..be4040527 100644 --- a/website/source/docs/command-line/push.html.markdown +++ b/website/source/docs/command-line/push.html.markdown @@ -25,6 +25,10 @@ must be completed within the template. ## Options +* `-message` - A message to identify the purpose or changes in this Packer + template much like a VCS commit message. This message will be passed to the + Packer build service. This option is also available as a short option `-m`. + * `-token` - An access token for authenticating the push to the Packer build service such as Atlas. This can also be specified within the push configuration in the template. @@ -34,7 +38,7 @@ must be completed within the template. Push a Packer template: ```shell -$ packer push template.json +$ packer push -m "Updating the apache version" template.json ``` Push a Packer template with a custom token: From 6728326cc3af33e12f8631a977c5fd8c477c6415 Mon Sep 17 00:00:00 2001 From: Seth Vargo Date: Tue, 3 Feb 2015 18:34:20 -0500 Subject: [PATCH 10/13] Also pass in the template contents and name of the template when pushing --- command/push.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/command/push.go b/command/push.go index 6ba27bada..f3a790bce 100644 --- a/command/push.go +++ b/command/push.go @@ -155,6 +155,8 @@ func (c *PushCommand) Run(args []string) int { if message != "" { metadata["message"] = message } + metadata["template"] = tpl.RawContents + metadata["template_name"] = filepath.Base(args[0]) uploadOpts.Metadata = metadata // Warn about builds not having post-processors. From 444fe40588f688e4914e6fba2edc4e8db47dc1a6 Mon Sep 17 00:00:00 2001 From: Seth Vargo Date: Tue, 3 Feb 2015 18:43:53 -0500 Subject: [PATCH 11/13] Do not use Unsetenv --- post-processor/atlas/post-processor_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/post-processor/atlas/post-processor_test.go b/post-processor/atlas/post-processor_test.go index 1fe629a88..2f8c63c47 100644 --- a/post-processor/atlas/post-processor_test.go +++ b/post-processor/atlas/post-processor_test.go @@ -10,7 +10,7 @@ import ( func TestPostProcessorConfigure(t *testing.T) { currentEnv := os.Getenv("ATLAS_TOKEN") - os.Unsetenv("ATLAS_TOKEN") + os.Setenv("ATLAS_TOKEN", "") defer os.Setenv("ATLAS_TOKEN", currentEnv) var p PostProcessor From bfc4f4ff7d8ba4d856605de48f0ba1afdb6696f9 Mon Sep 17 00:00:00 2001 From: Seth Vargo Date: Tue, 3 Feb 2015 21:13:24 -0500 Subject: [PATCH 12/13] Clarify push interpolation caveat --- website/source/docs/templates/push.html.markdown | 3 +++ 1 file changed, 3 insertions(+) diff --git a/website/source/docs/templates/push.html.markdown b/website/source/docs/templates/push.html.markdown index 73b37feef..691d4f34d 100644 --- a/website/source/docs/templates/push.html.markdown +++ b/website/source/docs/templates/push.html.markdown @@ -89,3 +89,6 @@ files to include: } } ``` + +~> **Variable interpolation** is not currently possible in Packer push +configurations. This will be fixed in an upcoming release. From cd0d3269343f1665c994344708c24d7726ed40d4 Mon Sep 17 00:00:00 2001 From: Seth Vargo Date: Wed, 4 Feb 2015 13:34:16 -0500 Subject: [PATCH 13/13] Allow -create to be passed still for BC --- command/push.go | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/command/push.go b/command/push.go index f3a790bce..74915de3f 100644 --- a/command/push.go +++ b/command/push.go @@ -34,12 +34,14 @@ type pushUploadFn func( func (c *PushCommand) Run(args []string) int { var token string var message string + var create bool f := flag.NewFlagSet("push", flag.ContinueOnError) f.Usage = func() { c.Ui.Error(c.Help()) } f.StringVar(&token, "token", "", "token") f.StringVar(&message, "m", "", "message") f.StringVar(&message, "message", "", "message") + f.BoolVar(&create, "create", false, "create (deprecated)") if err := f.Parse(args); err != nil { return 1 } @@ -50,6 +52,12 @@ func (c *PushCommand) Run(args []string) int { return 1 } + // Print deprecations + if create { + c.Ui.Error(fmt.Sprintf("The '-create' option is now the default and is\n" + + "longer used. It will be removed in the next version.")) + } + // Read the template tpl, err := packer.ParseTemplateFile(args[0], nil) if err != nil {