From 476eefa26bc2d51a71176b1dcaa913dff3d5d78e Mon Sep 17 00:00:00 2001 From: Bryan Hundven Date: Thu, 15 Oct 2020 14:56:57 -0700 Subject: [PATCH] Add 'create_image' option to googlecompute When building a CI/CD deployment, during the PR process it's nice to be able to run the builder, but not create the image the build produces. Closes #9965 --- builder/googlecompute/config.go | 17 +++++++++++++++++ builder/googlecompute/config.hcl2spec.go | 2 ++ builder/googlecompute/step_create_image.go | 5 +++++ .../googlecompute/Config-not-required.mdx | 2 ++ 4 files changed, 26 insertions(+) diff --git a/builder/googlecompute/config.go b/builder/googlecompute/config.go index 204fdccb4..04eba33ab 100644 --- a/builder/googlecompute/config.go +++ b/builder/googlecompute/config.go @@ -17,6 +17,7 @@ import ( "github.com/hashicorp/packer/helper/config" "github.com/hashicorp/packer/packer" "github.com/hashicorp/packer/template/interpolate" + "github.com/mitchellh/mapstructure" compute "google.golang.org/api/compute/v1" ) @@ -76,6 +77,8 @@ type Config struct { EnableIntegrityMonitoring bool `mapstructure:"enable_integrity_monitoring" required:"false"` // Whether to use an IAP proxy. IAPConfig `mapstructure:",squash"` + // Create the image. Useful for setting to `false` during a build test stage. Defaults to `true`. + CreateImage bool `mapstructure:"create_image" required:"false"` // The unique name of the resulting image. Defaults to // `packer-{{timestamp}}`. ImageName string `mapstructure:"image_name" required:"false"` @@ -288,7 +291,9 @@ type Config struct { func (c *Config) Prepare(raws ...interface{}) ([]string, error) { c.ctx.Funcs = TemplateFuncs + var md mapstructure.Metadata err := config.Decode(c, &config.DecodeOpts{ + Metadata: &md, Interpolate: true, InterpolateContext: &c.ctx, InterpolateFilter: &interpolate.RenderFilter{ @@ -329,6 +334,18 @@ func (c *Config) Prepare(raws ...interface{}) ([]string, error) { } } + hasCreateImage := false + for _, k := range md.Keys { + if k == "create_image" { + hasCreateImage = true + break + } + } + + if !hasCreateImage { + c.CreateImage = true + } + if c.ImageDescription == "" { c.ImageDescription = "Created by Packer" } diff --git a/builder/googlecompute/config.hcl2spec.go b/builder/googlecompute/config.hcl2spec.go index 3d98e6fca..40b0ac7dc 100644 --- a/builder/googlecompute/config.hcl2spec.go +++ b/builder/googlecompute/config.hcl2spec.go @@ -81,6 +81,7 @@ type FlatConfig struct { IAPHashBang *string `mapstructure:"iap_hashbang" required:"false" cty:"iap_hashbang" hcl:"iap_hashbang"` IAPExt *string `mapstructure:"iap_ext" required:"false" cty:"iap_ext" hcl:"iap_ext"` IAPTunnelLaunchWait *int `mapstructure:"iap_tunnel_launch_wait" required:"false" cty:"iap_tunnel_launch_wait" hcl:"iap_tunnel_launch_wait"` + CreateImage *bool `mapstructure:"create_image" required:"false" cty:"create_image" hcl:"create_image"` ImageName *string `mapstructure:"image_name" required:"false" cty:"image_name" hcl:"image_name"` ImageDescription *string `mapstructure:"image_description" required:"false" cty:"image_description" hcl:"image_description"` ImageEncryptionKey *FlatCustomerEncryptionKey `mapstructure:"image_encryption_key" required:"false" cty:"image_encryption_key" hcl:"image_encryption_key"` @@ -200,6 +201,7 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec { "iap_hashbang": &hcldec.AttrSpec{Name: "iap_hashbang", Type: cty.String, Required: false}, "iap_ext": &hcldec.AttrSpec{Name: "iap_ext", Type: cty.String, Required: false}, "iap_tunnel_launch_wait": &hcldec.AttrSpec{Name: "iap_tunnel_launch_wait", Type: cty.Number, Required: false}, + "create_image": &hcldec.AttrSpec{Name: "create_image", Type: cty.Bool, Required: false}, "image_name": &hcldec.AttrSpec{Name: "image_name", Type: cty.String, Required: false}, "image_description": &hcldec.AttrSpec{Name: "image_description", Type: cty.String, Required: false}, "image_encryption_key": &hcldec.BlockSpec{TypeName: "image_encryption_key", Nested: hcldec.ObjectSpec((*FlatCustomerEncryptionKey)(nil).HCL2Spec())}, diff --git a/builder/googlecompute/step_create_image.go b/builder/googlecompute/step_create_image.go index a7779e6f6..b27f473ae 100644 --- a/builder/googlecompute/step_create_image.go +++ b/builder/googlecompute/step_create_image.go @@ -23,6 +23,11 @@ func (s *StepCreateImage) Run(ctx context.Context, state multistep.StateBag) mul driver := state.Get("driver").(Driver) ui := state.Get("ui").(packer.Ui) + if !config.CreateImage { + ui.Say("Skipping image creation...") + return multistep.ActionContinue + } + if config.PackerForce && config.imageAlreadyExists { ui.Say("Deleting previous image...") diff --git a/website/pages/partials/builder/googlecompute/Config-not-required.mdx b/website/pages/partials/builder/googlecompute/Config-not-required.mdx index bf61c0986..9aebcb64c 100644 --- a/website/pages/partials/builder/googlecompute/Config-not-required.mdx +++ b/website/pages/partials/builder/googlecompute/Config-not-required.mdx @@ -42,6 +42,8 @@ state of your VM instances. Note: integrity monitoring relies on having vTPM enabled. [Details](https://cloud.google.com/security/shielded-cloud/shielded-vm) +- `create_image` (bool) - Create the image. Useful for setting to `false` during a build test stage. Defaults to `true`. + - `image_name` (string) - The unique name of the resulting image. Defaults to `packer-{{timestamp}}`.