diff --git a/builder/hcloud/artifact.go b/builder/hcloud/artifact.go index d7f54d8c..1f57a3eb 100644 --- a/builder/hcloud/artifact.go +++ b/builder/hcloud/artifact.go @@ -55,10 +55,14 @@ func (a *Artifact) State(name string) interface{} { func (a *Artifact) stateHCPPackerRegistryMetadata() interface{} { // create labels map labels := make(map[string]string) + + // This label contains the value the user specified in their template sourceImage, ok := a.StateData["source_image"].(string) if ok { labels["source_image"] = sourceImage } + // This is the canonical ID of the source image that was used, useful for ancestry tracking + sourceImageID, ok := a.StateData["source_image_id"].(int64) // get and set region from stateData into labels region, ok := a.StateData["region"].(string) if ok { @@ -70,17 +74,13 @@ func (a *Artifact) stateHCPPackerRegistryMetadata() interface{} { labels["server_type"] = serverType } - image, err := registryimage.FromArtifact(a, - registryimage.WithProvider("hetznercloud"), - registryimage.WithID(strconv.FormatInt(a.snapshotId, 10)), - registryimage.WithSourceID(sourceImage), - registryimage.WithRegion(region)) - if err != nil { - log.Printf("[DEBUG] error encountered when creating registry image %s", err) - return nil + return ®istryimage.Image{ + ProviderName: "hetznercloud", + ImageID: a.Id(), + ProviderRegion: region, + Labels: labels, + SourceImageID: strconv.FormatInt(sourceImageID, 10), } - image.Labels = labels - return image } func (a *Artifact) Destroy() error { diff --git a/builder/hcloud/step_create_server.go b/builder/hcloud/step_create_server.go index 88320109..09dd8c0d 100644 --- a/builder/hcloud/step_create_server.go +++ b/builder/hcloud/step_create_server.go @@ -55,11 +55,17 @@ func (s *stepCreateServer) Run(ctx context.Context, state multistep.StateBag) mu sshKeys = append(sshKeys, sshKey) } + serverType := state.Get("serverType").(*hcloud.ServerType) var image *hcloud.Image if c.Image != "" { - image = &hcloud.Image{Name: c.Image} + var err error + image, _, err = client.Image.GetForArchitecture(ctx, c.Image, serverType.Architecture) + if err != nil { + ui.Error(err.Error()) + state.Put("error", err) + return multistep.ActionHalt + } } else { - serverType := state.Get("serverType").(*hcloud.ServerType) var err error image, err = getImageWithSelectors(ctx, client, c, serverType) if err != nil { @@ -69,6 +75,7 @@ func (s *stepCreateServer) Run(ctx context.Context, state multistep.StateBag) mu } ui.Message(fmt.Sprintf("Using image %s with ID %d", image.Description, image.ID)) } + state.Put("source_image_id", image.ID) var networks []*hcloud.Network for _, k := range c.Networks { diff --git a/example/hcp-build.pkr.hcl b/example/hcp-build.pkr.hcl new file mode 100644 index 00000000..1e1d1277 --- /dev/null +++ b/example/hcp-build.pkr.hcl @@ -0,0 +1,50 @@ +# Copyright (c) HashiCorp, Inc. +# SPDX-License-Identifier: MPL-2.0 + +packer { + required_plugins { + hcloud = { + version = ">=v1.0.5" + source = "github.com/hashicorp/hcloud" + } + } +} + +variable "hcloud_token" { + type = string + default = "${env("HCLOUD_TOKEN")}" + sensitive = true +} + +source "hcloud" "example" { + image = "ubuntu-22.04" + location = "hel1" + server_name = "hcloud-example" + server_type = "cx11" + snapshot_labels = { + app = "hcloud-example" + } + snapshot_name = "hcloud-example" + ssh_username = "root" + token = var.hcloud_token +} + +build { + hcp_packer_registry { + bucket_name = "hcloud-hcp-test" + description = "A nice test description" + bucket_labels = { + "foo" = "bar" + } + } + + sources = ["source.hcloud.example"] + + provisioner "shell" { + inline = ["cloud-init status --wait"] + } + + provisioner "shell" { + inline = ["echo \"Hello World!\" > /var/log/packer.log"] + } +}