constellation/internal/containerimage/containerimage.go

113 lines
2.5 KiB
Go
Raw Normal View History

2023-04-03 12:09:03 -04:00
/*
Copyright (c) Edgeless Systems GmbH
SPDX-License-Identifier: AGPL-3.0-only
*/
/*
This package provides container image names, registry info and digests.
It should only be used by the CLI and never be imported by any package that
ends up in a container image to avoid circular dependencies.
*/
package containerimage
import (
"errors"
"path"
"regexp"
)
// Image is a container image reference.
// It has the following format:
// <registry>/<prefix>/<name>:<tag>@<digest>
// where <registry> is the registry where the image is located,
// <prefix> is the (optional) prefix of the image name,
// <name> is the name of the image,
// <tag> is the (optional) tag of the image,
// <digest> is the digest of the image.
type Image struct {
// Registry is the registry where the image is located.
Registry string
// Prefix is the prefix of the image name.
Prefix string
// Name is the name of the image.
Name string
// Tag is the tag of the image.
Tag string
// Digest is the digest of the image.
Digest string
}
// Validate validates the image.
func (i Image) Validate() error {
if i.Registry == "" {
return errors.New("image registry is empty")
}
if i.Name == "" {
return errors.New("image name is empty")
}
if i.Digest == "" {
return errors.New("image digest is empty")
}
if matched := digestRegexp.MatchString(i.Digest); !matched {
return errors.New("image digest is not valid")
}
return nil
}
// String returns the image as a string.
// The format is <registry>/<prefix>/<name>:<tag>@<digest>
// or a shorter version if prefix or tag are empty.
func (i Image) String() string {
var base string
if i.Prefix == "" {
base = path.Join(i.Registry, i.Name)
} else {
base = path.Join(i.Registry, i.Prefix, i.Name)
}
var tag string
if i.Tag != "" {
tag = ":" + i.Tag
}
return base + tag + "@" + i.Digest
}
// Builder is a builder for container images.
type Builder struct {
Default Image
Registry string
Prefix string
}
// NewBuilder creates a new builder for container images.
func NewBuilder(def Image, registry, prefix string) *Builder {
return &Builder{
Default: def,
Registry: registry,
Prefix: prefix,
}
}
// Build builds a container image.
func (b *Builder) Build() Image {
img := Image{}
if b.Registry == "" {
img.Registry = b.Default.Registry
} else {
img.Registry = b.Registry
}
if b.Prefix == "" {
img.Prefix = b.Default.Prefix
} else {
img.Prefix = b.Prefix
}
img.Name = b.Default.Name
img.Tag = b.Default.Tag
img.Digest = b.Default.Digest
return img
}
var digestRegexp = regexp.MustCompile(`^sha256:[a-f0-9]{64}$`)