@@ -3,73 +3,25 @@ package daemon
3
3
import (
4
4
"context"
5
5
"io"
6
- "io/ioutil"
7
6
"os"
8
7
"sync"
9
8
10
9
"github.com/docker/docker/api/types"
11
- "github.com/docker/docker/client"
12
- "github.com/google/go-containerregistry/pkg/name"
13
10
"github.com/google/go-containerregistry/pkg/v1"
14
11
"github.com/google/go-containerregistry/pkg/v1/tarball"
15
12
"golang.org/x/xerrors"
16
13
)
17
14
18
15
var mu sync.Mutex
19
16
20
- // image is a wrapper for github.com/google/go-containerregistry/pkg/v1/daemon.Image
21
- // daemon.Image loads the entire image into the memory at first,
22
- // but it doesn't need to load it if the information is already in the cache,
23
- // To avoid entire loading, this wrapper uses ImageInspectWithRaw and checks image ID and layer IDs.
24
- type image struct {
25
- v1.Image
26
- opener opener
27
- inspect types.ImageInspect
28
- }
29
-
30
17
type opener func () (v1.Image , error )
31
18
32
- // Image implements v1.Image by extending daemon.Image.
33
- // The caller must call cleanup() to remove a temporary file.
34
- func Image (ref name.Reference ) (v1.Image , * types.ImageInspect , func (), error ) {
35
- cleanup := func () {}
19
+ type imageSave func (context.Context , []string ) (io.ReadCloser , error )
36
20
37
- c , err := client .NewClientWithOpts (client .FromEnv , client .WithAPIVersionNegotiation ())
38
- if err != nil {
39
- return nil , nil , cleanup , xerrors .Errorf ("failed to initialize a docker client: %w" , err )
40
- }
41
- defer func () {
42
- if err != nil {
43
- c .Close ()
44
- }
45
- }()
46
-
47
- inspect , _ , err := c .ImageInspectWithRaw (context .Background (), ref .Name ())
48
- if err != nil {
49
- return nil , nil , cleanup , xerrors .Errorf ("unable to inspect the image (%s): %w" , ref .Name (), err )
50
- }
51
-
52
- f , err := ioutil .TempFile ("" , "fanal-*" )
53
- if err != nil {
54
- return nil , nil , cleanup , xerrors .Errorf ("failed to create a temporary file" )
55
- }
56
-
57
- cleanup = func () {
58
- c .Close ()
59
- f .Close ()
60
- _ = os .Remove (f .Name ())
61
- }
62
-
63
- return & image {
64
- opener : imageOpener (c , ref , f ),
65
- inspect : inspect ,
66
- }, & inspect , cleanup , nil
67
- }
68
-
69
- func imageOpener (c * client.Client , ref name.Reference , f * os.File ) opener {
21
+ func imageOpener (ref string , f * os.File , imageSave imageSave ) opener {
70
22
return func () (v1.Image , error ) {
71
23
// Store the tarball in local filesystem and return a new reader into the bytes each time we need to access something.
72
- rc , err := c . ImageSave (context .Background (), []string {ref . Name () })
24
+ rc , err := imageSave (context .Background (), []string {ref })
73
25
if err != nil {
74
26
return nil , xerrors .Errorf ("unable to export the image: %w" , err )
75
27
}
@@ -89,6 +41,16 @@ func imageOpener(c *client.Client, ref name.Reference, f *os.File) opener {
89
41
}
90
42
}
91
43
44
+ // image is a wrapper for github.com/google/go-containerregistry/pkg/v1/daemon.Image
45
+ // daemon.Image loads the entire image into the memory at first,
46
+ // but it doesn't need to load it if the information is already in the cache,
47
+ // To avoid entire loading, this wrapper uses ImageInspectWithRaw and checks image ID and layer IDs.
48
+ type image struct {
49
+ v1.Image
50
+ opener opener
51
+ inspect types.ImageInspect
52
+ }
53
+
92
54
// populateImage initializes an "image" struct.
93
55
// This method is called by some goroutines at the same time.
94
56
// To prevent multiple heavy initializations, the lock is necessary.
@@ -114,6 +76,13 @@ func (img *image) ConfigName() (v1.Hash, error) {
114
76
}
115
77
116
78
func (img * image ) ConfigFile () (* v1.ConfigFile , error ) {
79
+ if len (img .inspect .RootFS .Layers ) == 0 {
80
+ // Podman doesn't return RootFS...
81
+ if err := img .populateImage (); err != nil {
82
+ return nil , xerrors .Errorf ("unable to populate: %w" , err )
83
+ }
84
+ return img .Image .ConfigFile ()
85
+ }
117
86
var diffIDs []v1.Hash
118
87
for _ , l := range img .inspect .RootFS .Layers {
119
88
h , err := v1 .NewHash (l )
0 commit comments