@@ -31,9 +31,11 @@ import (
31
31
"os/exec"
32
32
"path"
33
33
"strings"
34
+ "time"
34
35
35
36
"github.com/google/go-containerregistry/pkg/authn"
36
37
"github.com/google/go-containerregistry/pkg/name"
38
+ "github.com/google/go-containerregistry/pkg/v1"
37
39
"github.com/google/go-containerregistry/pkg/v1/empty"
38
40
"github.com/google/go-containerregistry/pkg/v1/mutate"
39
41
"github.com/google/go-containerregistry/pkg/v1/remote"
@@ -54,6 +56,11 @@ const (
54
56
imageLabelSourceImageSize = "source-image-size"
55
57
imageLabelSourceImageVirtualSize = "source-image-virtual-size"
56
58
imageLabelSourceImageFormat = "source-image-format"
59
+ imageLabelEROFSCompatible = "erofs-compatible-layers"
60
+ imageArchitecture = "amd64"
61
+ imageOS = "linux"
62
+ imageAuthor = "DVCR client"
63
+ imageWorkingDir = "/"
57
64
)
58
65
59
66
type ImportRes struct {
@@ -171,16 +178,36 @@ func (p DataProcessor) inspectAndStreamSourceImage(
171
178
) error {
172
179
var tarWriter * tar.Writer
173
180
{
181
+ now := time .Now ()
182
+
174
183
tarWriter = tar .NewWriter (pipeWriter )
184
+ dirHeader := & tar.Header {
185
+ Name : "disk" ,
186
+ Mode : 0o755 ,
187
+ Uid : 107 ,
188
+ Gid : 107 ,
189
+ AccessTime : now ,
190
+ ChangeTime : now ,
191
+ Typeflag : tar .TypeDir ,
192
+ }
193
+ if err := tarWriter .WriteHeader (dirHeader ); err != nil {
194
+ return fmt .Errorf ("error writing tar header [disk]: %w" , err )
195
+ }
196
+
197
+ imagePath := path .Join ("disk" , sourceImageFilename )
175
198
header := & tar.Header {
176
- Name : path .Join ("disk" , sourceImageFilename ),
177
- Size : int64 (sourceImageSize ),
178
- Mode : 0o644 ,
179
- Typeflag : tar .TypeReg ,
199
+ Name : imagePath ,
200
+ Size : int64 (sourceImageSize ),
201
+ Mode : 0o644 ,
202
+ Uid : 107 ,
203
+ Gid : 107 ,
204
+ AccessTime : now ,
205
+ ChangeTime : now ,
206
+ Typeflag : tar .TypeReg ,
180
207
}
181
208
182
209
if err := tarWriter .WriteHeader (header ); err != nil {
183
- return fmt .Errorf ("error writing tar header: %w" , err )
210
+ return fmt .Errorf ("error writing tar header [%s] : %w" , imagePath , err )
184
211
}
185
212
}
186
213
@@ -247,6 +274,12 @@ func (p DataProcessor) inspectAndStreamSourceImage(
247
274
}
248
275
}
249
276
277
+ // Append end-of-file marker for tar archive.
278
+ err = writeTarEOFMarker (pipeWriter )
279
+ if err != nil {
280
+ return fmt .Errorf ("adding tar EOF marker: %w" , err )
281
+ }
282
+
250
283
klog .Infoln ("Source streaming completed" )
251
284
252
285
return nil
@@ -305,7 +338,8 @@ func (p DataProcessor) uploadLayersAndImage(
305
338
306
339
klog .Infof ("Got image info: virtual size: %d, format: %s" , informer .GetVirtualSize (), informer .GetFormat ())
307
340
308
- cnf .Config .Labels = map [string ]string {}
341
+ populateCommonConfigFields (cnf )
342
+
309
343
cnf .Config .Labels [imageLabelSourceImageVirtualSize ] = fmt .Sprintf ("%d" , informer .GetVirtualSize ())
310
344
cnf .Config .Labels [imageLabelSourceImageSize ] = fmt .Sprintf ("%d" , sourceImageSize )
311
345
cnf .Config .Labels [imageLabelSourceImageFormat ] = informer .GetFormat ()
@@ -328,6 +362,29 @@ func (p DataProcessor) uploadLayersAndImage(
328
362
return nil
329
363
}
330
364
365
+ // populateCommonConfigFields adds some required fields according to the document:
366
+ // https://github.com/opencontainers/image-spec/blob/main/config.md
367
+ func populateCommonConfigFields (cnf * v1.ConfigFile ) {
368
+ now := time .Now ().UTC ()
369
+ cnf .Created = v1.Time {Time : now }
370
+ cnf .Architecture = imageArchitecture
371
+ cnf .OS = imageOS
372
+ cnf .Author = imageAuthor
373
+
374
+ // Initialize labels, add label to distinguish from previous images with non-complete tar archives.
375
+ cnf .Config .Labels = make (map [string ]string )
376
+ cnf .Config .Labels [imageLabelEROFSCompatible ] = "true"
377
+
378
+ cnf .Config .WorkingDir = imageWorkingDir
379
+
380
+ cnf .History = append (cnf .History , v1.History {
381
+ Author : imageAuthor ,
382
+ Created : v1.Time {Time : now },
383
+ Comment : "streamed from the datasource" ,
384
+ EmptyLayer : false ,
385
+ })
386
+ }
387
+
331
388
func getImageInfo (ctx context.Context , sourceReader io.ReadCloser ) (ImageInfo , error ) {
332
389
formatSourceReaders , err := importer .NewFormatReaders (sourceReader , 0 )
333
390
if err != nil {
0 commit comments