@@ -8,12 +8,9 @@ import (
8
8
"os"
9
9
"path"
10
10
"path/filepath"
11
- "runtime"
12
11
"strings"
13
- "sync"
14
12
"time"
15
13
16
- "github.com/klauspost/pgzip"
17
14
"github.com/opencontainers/go-digest"
18
15
ispec "github.com/opencontainers/image-spec/specs-go/v1"
19
16
"github.com/opencontainers/umoci"
@@ -24,14 +21,13 @@ import (
24
21
"github.com/pkg/xattr"
25
22
"stackerbuild.io/stacker/pkg/lib"
26
23
"stackerbuild.io/stacker/pkg/log"
24
+ "stackerbuild.io/stacker/pkg/oci"
27
25
stackeroci "stackerbuild.io/stacker/pkg/oci"
28
26
"stackerbuild.io/stacker/pkg/squashfs"
29
27
"stackerbuild.io/stacker/pkg/storage"
30
28
"stackerbuild.io/stacker/pkg/types"
31
29
)
32
30
33
- var tarEx sync.Mutex
34
-
35
31
// Container image layers are often tar.gz, however there is nothing in the
36
32
// spec or documentation which standardizes compression params which can cause
37
33
// different layer hashes even for the same tar. So picking compression params
@@ -51,56 +47,6 @@ func overlayPath(rootfs string, d digest.Digest, subdirs ...string) string {
51
47
return path .Join (dirs ... )
52
48
}
53
49
54
- func (o * overlay ) Unpack (tag , name string ) error {
55
- cacheDir := path .Join (o .config .StackerDir , "layer-bases" , "oci" )
56
- oci , err := umoci .OpenLayout (cacheDir )
57
- if err != nil {
58
- return err
59
- }
60
- defer oci .Close ()
61
-
62
- manifest , err := stackeroci .LookupManifest (oci , tag )
63
- if err != nil {
64
- return err
65
- }
66
-
67
- pool := NewThreadPool (runtime .NumCPU ())
68
-
69
- seen := map [digest.Digest ]bool {}
70
- for _ , curLayer := range manifest .Layers {
71
- // avoid calling unpackOne twice for the same digest
72
- if seen [curLayer .Digest ] {
73
- continue
74
- }
75
- seen [curLayer .Digest ] = true
76
-
77
- // copy layer to avoid race on pool access.
78
- l := curLayer
79
- pool .Add (func (ctx context.Context ) error {
80
- return unpackOne (l , cacheDir , overlayPath (o .config .RootFSDir , l .Digest , "overlay" ))
81
- })
82
- }
83
-
84
- pool .DoneAddingJobs ()
85
-
86
- err = pool .Run ()
87
- if err != nil {
88
- return err
89
- }
90
-
91
- err = o .Create (name )
92
- if err != nil {
93
- return err
94
- }
95
-
96
- ovl , err := newOverlayMetadataFromOCI (oci , tag )
97
- if err != nil {
98
- return err
99
- }
100
-
101
- return ovl .write (o .config , name )
102
- }
103
-
104
50
func ConvertAndOutput (config types.StackerConfig , tag , name string , layerType types.LayerType ) error {
105
51
cacheDir := path .Join (config .StackerDir , "layer-bases" , "oci" )
106
52
cacheOCI , err := umoci .OpenLayout (cacheDir )
@@ -681,57 +627,32 @@ func repackOverlay(config types.StackerConfig, name string, layerTypes []types.L
681
627
return ovl .write (config , name )
682
628
}
683
629
684
- // unpackOne - unpack a single layer (Descriptor) found in ociDir to extractDir
685
- //
686
- // The result of calling unpackOne is either error or the contents available
687
- // at the provided extractDir. The extractDir should be either empty or
688
- // fully populated with this layer.
689
- func unpackOne (l ispec.Descriptor , ociDir string , extractDir string ) error {
690
- // population of a dir is not atomic, at least for tar extraction.
691
- // As a result, we could hasDirEntries(extractDir) at the same time that
692
- // something is un-populating that dir due to a failed extraction (like
693
- // os.RemoveAll below).
694
- // There needs to be a lock on the extract dir (scoped to the overlay storage backend).
695
- // A sync.RWMutex would work well here since it is safe to check as long
696
- // as no one is populating or unpopulating.
697
- if hasDirEntries (extractDir ) {
698
- // the directory was already populated.
699
- return nil
700
- }
630
+ func (o * overlay ) Unpack (tag , name string ) error {
631
+ cacheDir := path .Join (o .config .StackerDir , "layer-bases" , "oci" )
701
632
702
- if squashfs .IsSquashfsMediaType (l .MediaType ) {
703
- return squashfs .ExtractSingleSquash (
704
- path .Join (ociDir , "blobs" , "sha256" , l .Digest .Encoded ()), extractDir )
633
+ pathfunc := func (digest digest.Digest ) string {
634
+ return overlayPath (o .config .RootFSDir , digest , "overlay" )
705
635
}
706
- switch l .MediaType {
707
- case ispec .MediaTypeImageLayer , ispec .MediaTypeImageLayerGzip :
708
- tarEx .Lock ()
709
- defer tarEx .Unlock ()
710
636
711
- oci , err := umoci .OpenLayout (ociDir )
712
- if err != nil {
713
- return err
714
- }
715
- defer oci .Close ()
637
+ _ , err := oci .Unpack (cacheDir , tag , pathfunc )
638
+ if err != nil {
639
+ return err
640
+ }
716
641
717
- compressed , err := oci .GetBlob (context .Background (), l .Digest )
718
- if err != nil {
719
- return err
720
- }
721
- defer compressed .Close ()
642
+ err = o .Create (name )
643
+ if err != nil {
644
+ return err
645
+ }
722
646
723
- uncompressed , err := pgzip . NewReader ( compressed )
724
- if err != nil {
725
- return err
726
- }
647
+ oci , err := umoci . OpenLayout ( cacheDir )
648
+ if err != nil {
649
+ return err
650
+ }
727
651
728
- err = layer .UnpackLayer (extractDir , uncompressed , nil )
729
- if err != nil {
730
- if rmErr := os .RemoveAll (extractDir ); rmErr != nil {
731
- log .Errorf ("Failed to remove dir '%s' after failed extraction: %v" , extractDir , rmErr )
732
- }
733
- }
652
+ ovl , err := newOverlayMetadataFromOCI (oci , tag )
653
+ if err != nil {
734
654
return err
735
655
}
736
- return errors .Errorf ("unknown media type %s" , l .MediaType )
656
+
657
+ return ovl .write (o .config , name )
737
658
}
0 commit comments