mirror of
https://github.com/hashicorp/packer.git
synced 2026-09-23 08:21:43 -04:00
create a null data source for testing. We can choose to document if we want to, but it's a convenience for us add a test to catch cyclic datasource dependency, update tests to include out of order data sources, and update the code to clean up the returned diagnostics generated from the recursive evaluation PR review comments
150 lines
5.3 KiB
Go
150 lines
5.3 KiB
Go
//go:generate packer-sdc struct-markdown
|
|
//go:generate packer-sdc mapstructure-to-hcl2 -type DatasourceOutput,Config
|
|
package hcp_packer_image
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"log"
|
|
|
|
"github.com/zclconf/go-cty/cty"
|
|
|
|
"github.com/hashicorp/hcl/v2/hcldec"
|
|
"github.com/hashicorp/packer-plugin-sdk/common"
|
|
"github.com/hashicorp/packer-plugin-sdk/hcl2helper"
|
|
packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
|
|
"github.com/hashicorp/packer-plugin-sdk/template/config"
|
|
packerregistry "github.com/hashicorp/packer/internal/packer_registry"
|
|
)
|
|
|
|
type Datasource struct {
|
|
config Config
|
|
}
|
|
|
|
type Config struct {
|
|
common.PackerConfig `mapstructure:",squash"`
|
|
// The name of the bucket your image is in.
|
|
Bucket string `mapstructure:"bucket_name" required:"true"`
|
|
// The name of the iteration Id to use when retrieving your image
|
|
IterationID string `mapstructure:"iteration_id" required:"true"`
|
|
// The name of the cloud provider that your image is for. For example,
|
|
// "aws" or "gce".
|
|
CloudProvider string `mapstructure:"cloud_provider" required:"true"`
|
|
// The name of the cloud region your image is in. For example "us-east-1".
|
|
Region string `mapstructure:"region" required:"true"`
|
|
// TODO: Version string `mapstructure:"version"`
|
|
// TODO: Fingerprint string `mapstructure:"fingerprint"`
|
|
// TODO: Label string `mapstructure:"label"`
|
|
}
|
|
|
|
func (d *Datasource) ConfigSpec() hcldec.ObjectSpec {
|
|
return d.config.FlatMapstructure().HCL2Spec()
|
|
}
|
|
|
|
func (d *Datasource) Configure(raws ...interface{}) error {
|
|
err := config.Decode(&d.config, nil, raws...)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
var errs *packersdk.MultiError
|
|
|
|
if d.config.Bucket == "" {
|
|
errs = packersdk.MultiErrorAppend(errs, fmt.Errorf("The `bucket_name` must be specified"))
|
|
}
|
|
if d.config.IterationID == "" {
|
|
errs = packersdk.MultiErrorAppend(errs, fmt.Errorf("The `iteration_id`"+
|
|
" must be specified. If you do not know your iteration_id, you "+
|
|
"can retrieve it using the bucket name and desired channel using"+
|
|
" the hcp-packer-iteration data source."))
|
|
}
|
|
if d.config.Region == "" {
|
|
errs = packersdk.MultiErrorAppend(errs, fmt.Errorf("`region` is "+
|
|
"currently a required field."))
|
|
}
|
|
if d.config.CloudProvider == "" {
|
|
errs = packersdk.MultiErrorAppend(errs, fmt.Errorf("`cloud_provider` is "+
|
|
"currently a required field."))
|
|
}
|
|
|
|
if errs != nil && len(errs.Errors) > 0 {
|
|
return errs
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// Information from []*models.HashicorpCloudPackerImage with some information
|
|
// from the parent []*models.HashicorpCloudPackerBuild included where it seemed
|
|
// like it might be relevant. Need to copy so we can generate
|
|
type DatasourceOutput struct {
|
|
// The name of the cloud provider that the image exists in. For example,
|
|
// "aws", "azure", or "gce".
|
|
CloudProvider string `mapstructure:"cloud_provider"`
|
|
// The specific Packer builder or post-processor used to create the image.
|
|
ComponentType string `mapstructure:"component_type"`
|
|
// The date and time at which the image was created.
|
|
CreatedAt string `mapstructure:"created_at"`
|
|
// The id of the build that created the image. This is a ULID, which is a
|
|
// unique identifier similar to a UUID. It is created by the HCP Packer
|
|
// Registry when an build is first created, and is unique to this build.
|
|
BuildID string `mapstructure:"build_id"`
|
|
// The iteration id. This is a ULID, which is a unique identifier similar
|
|
// to a UUID. It is created by the HCP Packer Registry when an iteration is
|
|
// first created, and is unique to this iteration.
|
|
IterationID string `mapstructure:"iteration_id"`
|
|
// The UUID associated with the Packer run that created this image.
|
|
PackerRunUUID string `mapstructure:"packer_run_uuid"`
|
|
// ID or URL of the remote cloud image as given by a build.
|
|
ID string `mapstructure:"id"`
|
|
// The cloud region as given by `packer build`. eg. "ap-east-1".
|
|
// For locally managed clouds, this may map instead to a cluster, server
|
|
// or datastore.
|
|
Region string `mapstructure:"region"`
|
|
}
|
|
|
|
func (d *Datasource) OutputSpec() hcldec.ObjectSpec {
|
|
return (&DatasourceOutput{}).FlatMapstructure().HCL2Spec()
|
|
}
|
|
|
|
func (d *Datasource) Execute() (cty.Value, error) {
|
|
cli, err := packerregistry.NewClient()
|
|
if err != nil {
|
|
return cty.NullVal(cty.EmptyObject), err
|
|
}
|
|
|
|
// Load channel.
|
|
log.Printf("[INFO] Reading info from HCP Packer registry (%s) [project_id=%s, organization_id=%s, iteration_id=%s]",
|
|
d.config.Bucket, cli.ProjectID, cli.OrganizationID, d.config.IterationID)
|
|
|
|
iteration, err := packerregistry.GetIterationFromId(context.TODO(), cli, d.config.Bucket, d.config.IterationID)
|
|
if err != nil {
|
|
return cty.NullVal(cty.EmptyObject), fmt.Errorf("error retrieving "+
|
|
"image iteration from HCP Packer registry: %s", err.Error())
|
|
}
|
|
|
|
output := DatasourceOutput{}
|
|
|
|
for _, build := range iteration.Builds {
|
|
if build.CloudProvider != d.config.CloudProvider {
|
|
continue
|
|
}
|
|
for _, image := range build.Images {
|
|
if image.Region == d.config.Region {
|
|
// This is the desired image.
|
|
output = DatasourceOutput{
|
|
CloudProvider: build.CloudProvider,
|
|
ComponentType: build.ComponentType,
|
|
CreatedAt: image.CreatedAt.String(),
|
|
BuildID: build.ID,
|
|
IterationID: build.IterationID,
|
|
PackerRunUUID: build.PackerRunUUID,
|
|
ID: image.ImageID,
|
|
Region: image.Region,
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return hcl2helper.HCL2ValueFromConfig(output, d.OutputSpec()), nil
|
|
}
|