/
data.go
189 lines (169 loc) · 7.2 KB
/
data.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
//go:generate packer-sdc struct-markdown
//go:generate packer-sdc mapstructure-to-hcl2 -type DatasourceOutput,Config,ParBuild,ParImage
package packer_image_iteration
import (
"context"
"fmt"
"log"
"github.com/zclconf/go-cty/cty"
"github.com/hashicorp/hcl/v2/hcldec"
"github.com/hashicorp/hcp-sdk-go/clients/cloud-packer-service/preview/2021-04-30/models"
"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/registry"
)
// Type for Packer datasource has been renamed temporarily to prevent it from being
// automatically registered as a viable datasource plugin in command/plugin.go.
// In the future this type will be renamed to allow for the use of the datasource.
type DeactivatedDatasource 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 channel to use when retrieving your image
Channel string `mapstructure:"channel" required:"true"`
// TODO: Version string `mapstructure:"version"`
// TODO: Label string `mapstructure:"label"`
}
func (d *DeactivatedDatasource) ConfigSpec() hcldec.ObjectSpec {
return d.config.FlatMapstructure().HCL2Spec()
}
func (d *DeactivatedDatasource) 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.Channel == "" {
errs = packersdk.MultiErrorAppend(errs, fmt.Errorf("`channel` is currently a required field."))
}
if errs != nil && len(errs.Errors) > 0 {
return errs
}
return nil
}
// Copy of []*models.HashicorpCloudPackerBuild. Need to copy so we can generate
// the HCL spec.
type ParBuild struct {
// The name of the cloud provider that the build exists in. For example,
// "aws", "azure", or "gce".
CloudProvider string `mapstructure:"cloud_provider"`
// The specific Packer builder or post-processor used to create the build.
ComponentType string `mapstructure:"component_type"`
// The date and time at which the build was run.
CreatedAt string `mapstructure:"created_at"`
// The build id. 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.
ID string `mapstructure:"id"`
// A list of images as stored in the HCP Packer registry. See the ParImage
// docs for more information.
Images []ParImage `mapstructure:"images"`
// 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"`
// Unstructured key:value metadata associated with the build.
Labels map[string]string `mapstructure:"labels"`
// The UUID associated with the Packer run that created this build.
PackerRunUUID string `mapstructure:"packer_run_uuid"`
// Whether the build is considered "complete" (the Packer build ran
// successfully and created an artifact), or "incomplete" (the Packer
// build did not finish, and there is no uploaded artifact).
Status string `mapstructure:"status"`
// The date and time at which the build was last updated.
UpdatedAt string `mapstructure:"updated_at"`
}
// Copy of []*models.HashicorpCloudPackerImage Need to copy so we can generate
// the HCL spec.
type ParImage struct {
// The date and time at which the build was last updated.
CreatedAt string `mapstructure:"created_at,omitempty"`
// 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.
ID string `mapstructure:"id,omitempty"`
// ID or URL of the remote cloud image as given by a build.
ImageID string `mapstructure:"image_id,omitempty"`
// 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,omitempty"`
}
type DatasourceOutput struct {
// 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.
Id string `mapstructure:"Id"`
// The version number assigned to an iteration. This number is an integer,
// and is created by the HCP Packer Registry once an iteration is
// marked "complete". If a new iteration is marked "complete", the version
// that HCP Packer assigns to it will always be the highest previous
// iteration version plus one.
IncrementalVersion int32 `mapstructure:"incremental_version"`
// The date the iteration was created.
CreatedAt string `mapstructure:"created_at"`
// A list of builds that are stored in the iteration. These builds can be
// parsed using HCL to find individual image ids for specific providers.
Builds []ParBuild `mapstructure:"builds"`
}
func (d *DeactivatedDatasource) OutputSpec() hcldec.ObjectSpec {
return (&DatasourceOutput{}).FlatMapstructure().HCL2Spec()
}
func (d *DeactivatedDatasource) Execute() (cty.Value, error) {
ctx := context.TODO()
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, channel=%s]",
d.config.Bucket, cli.ProjectID, cli.OrganizationID, d.config.Channel)
iteration, err := cli.GetIterationFromChannel(ctx, d.config.Bucket, d.config.Channel)
if err != nil {
return cty.NullVal(cty.EmptyObject), fmt.Errorf("error retrieving "+
"image iteration from HCP Packer registry: %s", err.Error())
}
output := DatasourceOutput{
IncrementalVersion: iteration.IncrementalVersion,
CreatedAt: iteration.CreatedAt.String(),
Builds: convertPackerBuildList(iteration.Builds),
}
return hcl2helper.HCL2ValueFromConfig(output, d.OutputSpec()), nil
}
func convertPackerBuildList(builds []*models.HashicorpCloudPackerBuild) (flattened []ParBuild) {
for _, build := range builds {
out := ParBuild{
CloudProvider: build.CloudProvider,
ComponentType: build.ComponentType,
CreatedAt: build.CreatedAt.String(),
ID: build.ID,
Images: convertPackerBuildImagesList(build.Images),
Labels: build.Labels,
PackerRunUUID: build.PackerRunUUID,
Status: string(build.Status),
UpdatedAt: build.UpdatedAt.String(),
}
flattened = append(flattened, out)
}
return
}
func convertPackerBuildImagesList(images []*models.HashicorpCloudPackerImage) (flattened []ParImage) {
for _, image := range images {
out := ParImage{
CreatedAt: image.CreatedAt.String(),
ID: image.ID,
ImageID: image.ImageID,
Region: image.Region,
}
flattened = append(flattened, out)
}
return
}