You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
packer/internal/registry/types.iterations.go

147 lines
4.0 KiB

package registry
import (
"errors"
"fmt"
"os"
"sync"
git "github.com/go-git/go-git/v5"
registryimage "github.com/hashicorp/packer-plugin-sdk/packer/registry/image"
)
type Iteration struct {
ID string
AncestorSlug string
Fingerprint string
RunUUID string
Labels map[string]string
builds sync.Map
expectedBuilds []string
}
type IterationOptions struct {
TemplateBaseDir string
}
// NewIteration returns a pointer to an Iteration that can be used for storing Packer build details needed by PAR.
func NewIteration(opts IterationOptions) (*Iteration, error) {
i := Iteration{
expectedBuilds: make([]string, 0),
}
// By default we try to load a Fingerprint from the environment variable.
// If no variable is defined we should try to load a fingerprint from Git, or other VCS.
i.Fingerprint = os.Getenv("HCP_PACKER_BUILD_FINGERPRINT")
// get a Git SHA
if i.Fingerprint != "" {
return &i, nil
}
fp, err := GetGitFingerprint(opts)
if err != nil {
return nil, err
}
i.Fingerprint = fp
return &i, nil
}
// GetGitFingerprint returns the HEAD commit for some template dir defined in opt.TemplateBaseDir.
// If the base directory is not under version control an error is returned.
func GetGitFingerprint(opts IterationOptions) (string, error) {
r, err := git.PlainOpenWithOptions(opts.TemplateBaseDir, &git.PlainOpenOptions{
DetectDotGit: true,
})
if err != nil {
return "", fmt.Errorf("Packer was unable to load a git sha. "+
"If your Packer template is not in a git repo, please add a unique "+
"template fingerprint using the env var HCP_PACKER_BUILD_FINGERPRINT. "+
"Error: %s", err)
}
// The config can be used to retrieve user identity. for example,
// c.User.Email. Leaving in but commented because I'm not sure we care
// about this identity right now. - Megan
//
// c, err := r.ConfigScoped(config.GlobalScope)
// if err != nil {
// return "", fmt.Errorf("Error setting git scope", err)
// }
ref, err := r.Head()
if err != nil {
return "", fmt.Errorf("Packer encountered an issue reading the git info for the path %q.\n"+
"If your Packer template is not in a git repo, please add a unique "+
"template fingerprint using the env var HCP_PACKER_BUILD_FINGERPRINT. "+
"Error: %s", opts.TemplateBaseDir, err)
}
// log.Printf("Author: %v, Commit: %v\n", c.User.Email, ref.Hash())
return ref.Hash().String(), nil
}
// AddImageToBuild appends one or more images artifacts to the build referred to by buildName.
func (i *Iteration) AddImageToBuild(buildName string, images ...registryimage.Image) error {
existingBuild, ok := i.builds.Load(buildName)
if !ok {
return errors.New("no build found for the name " + buildName)
}
build, ok := existingBuild.(*Build)
if !ok {
return fmt.Errorf("the build for the component %q does not appear to be a valid registry Build", buildName)
}
if build.Images == nil {
build.Images = make(map[string]registryimage.Image)
}
for _, image := range images {
if err := image.Validate(); err != nil {
return fmt.Errorf("failed to add image to build %q: %v", buildName, err)
}
if build.CloudProvider == "" {
build.CloudProvider = image.ProviderName
}
for k, v := range image.Labels {
if _, ok := build.Labels[k]; ok {
continue
}
build.Labels[k] = v
}
build.Images[image.String()] = image
}
i.builds.Store(buildName, build)
return nil
}
// AddLabelsToBuild merges the contents of data to the labels associated with the build referred to by buildName.
func (i *Iteration) AddLabelsToBuild(buildName string, data map[string]string) error {
existingBuild, ok := i.builds.Load(buildName)
if !ok {
return errors.New("no associated build found for the name " + buildName)
}
build, ok := existingBuild.(*Build)
if !ok {
return fmt.Errorf("the build for the component %q does not appear to be a valid registry Build", buildName)
}
for k, v := range data {
if _, ok := build.Labels[k]; ok {
continue
}
build.Labels[k] = v
}
i.builds.Store(buildName, build)
return nil
}