/
load.go
133 lines (115 loc) · 4.11 KB
/
load.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
package libimage
import (
"context"
"fmt"
"os"
"time"
dirTransport "github.com/containers/image/v5/directory"
dockerArchiveTransport "github.com/containers/image/v5/docker/archive"
ociArchiveTransport "github.com/containers/image/v5/oci/archive"
ociTransport "github.com/containers/image/v5/oci/layout"
"github.com/containers/image/v5/types"
"github.com/sirupsen/logrus"
)
type LoadOptions struct {
CopyOptions
}
// Load loads one or more images (depending on the transport) from the
// specified path. The path may point to an image the following transports:
// oci, oci-archive, dir, docker-archive.
func (r *Runtime) Load(ctx context.Context, path string, options *LoadOptions) ([]string, error) {
logrus.Debugf("Loading image from %q", path)
if r.eventChannel != nil {
defer r.writeEvent(&Event{ID: "", Name: path, Time: time.Now(), Type: EventTypeImageLoad})
}
if options == nil {
options = &LoadOptions{}
}
var loadErrors []error
for _, f := range []func() ([]string, string, error){
// OCI
func() ([]string, string, error) {
logrus.Debugf("-> Attempting to load %q as an OCI directory", path)
ref, err := ociTransport.NewReference(path, "")
if err != nil {
return nil, ociTransport.Transport.Name(), err
}
images, err := r.copyFromDefault(ctx, ref, &options.CopyOptions)
return images, ociTransport.Transport.Name(), err
},
// OCI-ARCHIVE
func() ([]string, string, error) {
logrus.Debugf("-> Attempting to load %q as an OCI archive", path)
ref, err := ociArchiveTransport.NewReference(path, "")
if err != nil {
return nil, ociArchiveTransport.Transport.Name(), err
}
images, err := r.copyFromDefault(ctx, ref, &options.CopyOptions)
return images, ociArchiveTransport.Transport.Name(), err
},
// DIR
func() ([]string, string, error) {
logrus.Debugf("-> Attempting to load %q as a Docker dir", path)
ref, err := dirTransport.NewReference(path)
if err != nil {
return nil, dirTransport.Transport.Name(), err
}
images, err := r.copyFromDefault(ctx, ref, &options.CopyOptions)
return images, dirTransport.Transport.Name(), err
},
// DOCKER-ARCHIVE
func() ([]string, string, error) {
logrus.Debugf("-> Attempting to load %q as a Docker archive", path)
ref, err := dockerArchiveTransport.ParseReference(path)
if err != nil {
return nil, dockerArchiveTransport.Transport.Name(), err
}
images, err := r.loadMultiImageDockerArchive(ctx, ref, &options.CopyOptions)
return images, dockerArchiveTransport.Transport.Name(), err
},
} {
loadedImages, transportName, err := f()
if err == nil {
return loadedImages, nil
}
logrus.Debugf("Error loading %s (%s): %v", path, transportName, err)
loadErrors = append(loadErrors, fmt.Errorf("%s: %v", transportName, err))
}
// Give a decent error message if nothing above worked.
loadError := fmt.Errorf("payload does not match any of the supported image formats:")
for _, err := range loadErrors {
loadError = fmt.Errorf("%w\n * %v", loadError, err)
}
return nil, loadError
}
// loadMultiImageDockerArchive loads the docker archive specified by ref. In
// case the path@reference notation was used, only the specifiec image will be
// loaded. Otherwise, all images will be loaded.
func (r *Runtime) loadMultiImageDockerArchive(ctx context.Context, ref types.ImageReference, options *CopyOptions) ([]string, error) {
// If we cannot stat the path, it either does not exist OR the correct
// syntax to reference an image within the archive was used, so we
// should.
path := ref.StringWithinTransport()
if _, err := os.Stat(path); err != nil {
return r.copyFromDockerArchive(ctx, ref, options)
}
reader, err := dockerArchiveTransport.NewReader(r.systemContextCopy(), path)
if err != nil {
return nil, err
}
refLists, err := reader.List()
if err != nil {
return nil, err
}
var copiedImages []string
for _, list := range refLists {
for _, listRef := range list {
names, err := r.copyFromDockerArchiveReaderReference(ctx, reader, listRef, options)
if err != nil {
return nil, err
}
copiedImages = append(copiedImages, names...)
}
}
return copiedImages, nil
}