summaryrefslogtreecommitdiff
path: root/vendor/github.com/projectatomic/buildah/util/util.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/projectatomic/buildah/util/util.go')
-rw-r--r--vendor/github.com/projectatomic/buildah/util/util.go221
1 files changed, 221 insertions, 0 deletions
diff --git a/vendor/github.com/projectatomic/buildah/util/util.go b/vendor/github.com/projectatomic/buildah/util/util.go
new file mode 100644
index 000000000..49d6fcc4e
--- /dev/null
+++ b/vendor/github.com/projectatomic/buildah/util/util.go
@@ -0,0 +1,221 @@
+package util
+
+import (
+ "fmt"
+ "io"
+ "net/url"
+ "path"
+ "strings"
+ "time"
+
+ "github.com/containers/image/directory"
+ dockerarchive "github.com/containers/image/docker/archive"
+ "github.com/containers/image/docker/reference"
+ ociarchive "github.com/containers/image/oci/archive"
+ "github.com/containers/image/pkg/sysregistries"
+ is "github.com/containers/image/storage"
+ "github.com/containers/image/tarball"
+ "github.com/containers/image/types"
+ "github.com/containers/storage"
+ "github.com/docker/distribution/registry/api/errcode"
+ "github.com/pkg/errors"
+ "github.com/sirupsen/logrus"
+)
+
+const (
+ minimumTruncatedIDLength = 3
+)
+
+var (
+ // RegistryDefaultPathPrefix contains a per-registry listing of default prefixes
+ // to prepend to image names that only contain a single path component.
+ RegistryDefaultPathPrefix = map[string]string{
+ "index.docker.io": "library",
+ "docker.io": "library",
+ }
+ // Transports contains the possible transports used for images
+ Transports = map[string]string{
+ dockerarchive.Transport.Name(): "",
+ ociarchive.Transport.Name(): "",
+ directory.Transport.Name(): "",
+ tarball.Transport.Name(): "",
+ }
+ // DockerArchive is the transport we prepend to an image name
+ // when saving to docker-archive
+ DockerArchive = dockerarchive.Transport.Name()
+ // OCIArchive is the transport we prepend to an image name
+ // when saving to oci-archive
+ OCIArchive = ociarchive.Transport.Name()
+ // DirTransport is the transport for pushing and pulling
+ // images to and from a directory
+ DirTransport = directory.Transport.Name()
+ // TarballTransport is the transport for importing a tar archive
+ // and creating a filesystem image
+ TarballTransport = tarball.Transport.Name()
+)
+
+// ResolveName checks if name is a valid image name, and if that name doesn't include a domain
+// portion, returns a list of the names which it might correspond to in the registries.
+func ResolveName(name string, firstRegistry string, sc *types.SystemContext, store storage.Store) []string {
+ if name == "" {
+ return nil
+ }
+
+ // Maybe it's a truncated image ID. Don't prepend a registry name, then.
+ if len(name) >= minimumTruncatedIDLength {
+ if img, err := store.Image(name); err == nil && img != nil && strings.HasPrefix(img.ID, name) {
+ // It's a truncated version of the ID of an image that's present in local storage;
+ // we need to expand the ID.
+ return []string{img.ID}
+ }
+ }
+
+ // If the image is from a different transport
+ split := strings.SplitN(name, ":", 2)
+ if len(split) == 2 {
+ if _, ok := Transports[split[0]]; ok {
+ return []string{split[1]}
+ }
+ }
+
+ // If the image name already included a domain component, we're done.
+ named, err := reference.ParseNormalizedNamed(name)
+ if err != nil {
+ return []string{name}
+ }
+ if named.String() == name {
+ // Parsing produced the same result, so there was a domain name in there to begin with.
+ return []string{name}
+ }
+ if reference.Domain(named) != "" && RegistryDefaultPathPrefix[reference.Domain(named)] != "" {
+ // If this domain can cause us to insert something in the middle, check if that happened.
+ repoPath := reference.Path(named)
+ domain := reference.Domain(named)
+ defaultPrefix := RegistryDefaultPathPrefix[reference.Domain(named)] + "/"
+ if strings.HasPrefix(repoPath, defaultPrefix) && path.Join(domain, repoPath[len(defaultPrefix):]) == name {
+ // Yup, parsing just inserted a bit in the middle, so there was a domain name there to begin with.
+ return []string{name}
+ }
+ }
+
+ // Figure out the list of registries.
+ registries, err := sysregistries.GetRegistries(sc)
+ if err != nil {
+ logrus.Debugf("unable to complete image name %q: %v", name, err)
+ return []string{name}
+ }
+ if sc.DockerInsecureSkipTLSVerify {
+ if unverifiedRegistries, err := sysregistries.GetInsecureRegistries(sc); err == nil {
+ registries = append(registries, unverifiedRegistries...)
+ }
+ }
+
+ // Create all of the combinations. Some registries need an additional component added, so
+ // use our lookaside map to keep track of them. If there are no configured registries, at
+ // least return the name as it was passed to us.
+ candidates := []string{}
+ for _, registry := range append([]string{firstRegistry}, registries...) {
+ if registry == "" {
+ continue
+ }
+ middle := ""
+ if prefix, ok := RegistryDefaultPathPrefix[registry]; ok && strings.IndexRune(name, '/') == -1 {
+ middle = prefix
+ }
+ candidate := path.Join(registry, middle, name)
+ candidates = append(candidates, candidate)
+ }
+ if len(candidates) == 0 {
+ candidates = append(candidates, name)
+ }
+ return candidates
+}
+
+// ExpandNames takes unqualified names, parses them as image names, and returns
+// the fully expanded result, including a tag. Names which don't include a registry
+// name will be marked for the most-preferred registry (i.e., the first one in our
+// configuration).
+func ExpandNames(names []string) ([]string, error) {
+ expanded := make([]string, 0, len(names))
+ for _, n := range names {
+ name, err := reference.ParseNormalizedNamed(n)
+ if err != nil {
+ return nil, errors.Wrapf(err, "error parsing name %q", n)
+ }
+ name = reference.TagNameOnly(name)
+ tag := ""
+ digest := ""
+ if tagged, ok := name.(reference.NamedTagged); ok {
+ tag = ":" + tagged.Tag()
+ }
+ if digested, ok := name.(reference.Digested); ok {
+ digest = "@" + digested.Digest().String()
+ }
+ expanded = append(expanded, name.Name()+tag+digest)
+ }
+ return expanded, nil
+}
+
+// FindImage locates the locally-stored image which corresponds to a given name.
+func FindImage(store storage.Store, image string) (*storage.Image, error) {
+ var img *storage.Image
+ ref, err := is.Transport.ParseStoreReference(store, image)
+ if err == nil {
+ img, err = is.Transport.GetStoreImage(store, ref)
+ }
+ if err != nil {
+ img2, err2 := store.Image(image)
+ if err2 != nil {
+ if ref == nil {
+ return nil, errors.Wrapf(err, "error parsing reference to image %q", image)
+ }
+ return nil, errors.Wrapf(err, "unable to locate image %q", image)
+ }
+ img = img2
+ }
+ return img, nil
+}
+
+// AddImageNames adds the specified names to the specified image.
+func AddImageNames(store storage.Store, image *storage.Image, addNames []string) error {
+ names, err := ExpandNames(addNames)
+ if err != nil {
+ return err
+ }
+ err = store.SetNames(image.ID, append(image.Names, names...))
+ if err != nil {
+ return errors.Wrapf(err, "error adding names (%v) to image %q", names, image.ID)
+ }
+ return nil
+}
+
+// GetFailureCause checks the type of the error "err" and returns a new
+// error message that reflects the reason of the failure.
+// In case err type is not a familiar one the error "defaultError" is returned.
+func GetFailureCause(err, defaultError error) error {
+ switch nErr := errors.Cause(err).(type) {
+ case errcode.Errors:
+ return err
+ case errcode.Error, *url.Error:
+ return nErr
+ default:
+ return defaultError
+ }
+}
+
+// GetLocalTime discover the UTC offset and then add that to the
+// passed in time to arrive at the local time.
+func GetLocalTime(localTime time.Time) time.Time {
+ t := time.Now()
+ _, offset := t.Local().Zone()
+ localTime = localTime.Add(time.Second * time.Duration(offset))
+ return localTime
+}
+
+// WriteError writes `lastError` into `w` if not nil and return the next error `err`
+func WriteError(w io.Writer, err error, lastError error) error {
+ if lastError != nil {
+ fmt.Fprintln(w, lastError)
+ }
+ return err
+}