From 802e7d467d0e5f570cd24d9c039365bcced82f2b Mon Sep 17 00:00:00 2001 From: Kevin Bulebush Date: Fri, 23 Nov 2018 19:27:28 -0500 Subject: [PATCH] openstack: Add support for tagging new images. --- builder/openstack/builder.go | 1 + builder/openstack/image_config.go | 1 + builder/openstack/step_update_image_tags.go | 52 +++++++++++++++++++ .../source/docs/builders/openstack.html.md | 3 ++ 4 files changed, 57 insertions(+) create mode 100644 builder/openstack/step_update_image_tags.go diff --git a/builder/openstack/builder.go b/builder/openstack/builder.go index 7ab5fa6c3..bc87c3375 100644 --- a/builder/openstack/builder.go +++ b/builder/openstack/builder.go @@ -142,6 +142,7 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe &stepCreateImage{ UseBlockStorageVolume: b.config.UseBlockStorageVolume, }, + &stepUpdateImageTags{}, &stepUpdateImageVisibility{}, &stepAddImageMembers{}, } diff --git a/builder/openstack/image_config.go b/builder/openstack/image_config.go index f17ad753d..ffc9c6896 100644 --- a/builder/openstack/image_config.go +++ b/builder/openstack/image_config.go @@ -15,6 +15,7 @@ type ImageConfig struct { ImageVisibility imageservice.ImageVisibility `mapstructure:"image_visibility"` ImageMembers []string `mapstructure:"image_members"` ImageDiskFormat string `mapstructure:"image_disk_format"` + ImageTags []string `mapstructure:"image_tags"` } func (c *ImageConfig) Prepare(ctx *interpolate.Context) []error { diff --git a/builder/openstack/step_update_image_tags.go b/builder/openstack/step_update_image_tags.go new file mode 100644 index 000000000..b3c93d5de --- /dev/null +++ b/builder/openstack/step_update_image_tags.go @@ -0,0 +1,52 @@ +package openstack + +import ( + "context" + "fmt" + "strings" + + imageservice "github.com/gophercloud/gophercloud/openstack/imageservice/v2/images" + "github.com/hashicorp/packer/helper/multistep" + "github.com/hashicorp/packer/packer" +) + +type stepUpdateImageTags struct{} + +func (s *stepUpdateImageTags) Run(_ context.Context, state multistep.StateBag) multistep.StepAction { + imageId := state.Get("image").(string) + ui := state.Get("ui").(packer.Ui) + config := state.Get("config").(*Config) + + if len(config.ImageTags) == 0 { + return multistep.ActionContinue + } + imageClient, err := config.imageV2Client() + if err != nil { + err = fmt.Errorf("Error initializing image service client: %s", err) + state.Put("error", err) + return multistep.ActionHalt + } + + ui.Say(fmt.Sprintf("Updating image tags to %s", strings.Join(config.ImageTags, ", "))) + r := imageservice.Update( + imageClient, + imageId, + imageservice.UpdateOpts{ + imageservice.ReplaceImageTags{ + NewTags: config.ImageTags, + }, + }, + ) + + if _, err = r.Extract(); err != nil { + err = fmt.Errorf("Error updating image tags: %s", err) + state.Put("error", err) + return multistep.ActionHalt + } + + return multistep.ActionContinue +} + +func (s *stepUpdateImageTags) Cleanup(multistep.StateBag) { + // No cleanup... +} diff --git a/website/source/docs/builders/openstack.html.md b/website/source/docs/builders/openstack.html.md index 263610c0f..064f1e313 100644 --- a/website/source/docs/builders/openstack.html.md +++ b/website/source/docs/builders/openstack.html.md @@ -127,6 +127,9 @@ builder. after creation. An image member is usually a project (also called the "tenant") with whom the image is shared. +- `image_tags` (array of strings) - List of tags to add to the image after + creation. + - `image_visibility` (string) - One of "public", "private", "shared", or "community".