@@ -3,13 +3,7 @@ package main
33import (
44 "errors"
55 "fmt"
6- "os"
7- "path/filepath"
86
9- "github.com/buildpacks/imgutil"
10- "github.com/buildpacks/imgutil/layout"
11- "github.com/buildpacks/imgutil/layout/sparse"
12- "github.com/buildpacks/imgutil/remote"
137 "github.com/docker/docker/client"
148 "github.com/google/go-containerregistry/pkg/authn"
159
@@ -18,16 +12,12 @@ import (
1812 "github.com/buildpacks/lifecycle/cmd"
1913 "github.com/buildpacks/lifecycle/cmd/lifecycle/cli"
2014 "github.com/buildpacks/lifecycle/image"
21- "github.com/buildpacks/lifecycle/internal/encoding"
22- "github.com/buildpacks/lifecycle/internal/layer"
2315 "github.com/buildpacks/lifecycle/phase"
2416 "github.com/buildpacks/lifecycle/platform"
2517 "github.com/buildpacks/lifecycle/platform/files"
2618 "github.com/buildpacks/lifecycle/priv"
2719)
2820
29- const kanikoDir = "/kaniko"
30-
3121type restoreCmd struct {
3222 * platform.Platform
3323
@@ -95,196 +85,25 @@ func (r *restoreCmd) Privileges() error {
9585}
9686
9787func (r * restoreCmd ) Exec () error {
98- group , err := files .Handler .ReadGroup (r .GroupPath )
99- if err != nil {
100- return err
101- }
102- if err = verifyBuildpackApis (group ); err != nil {
103- return err
104- }
105-
106- var analyzedMD files.Analyzed
107- if analyzedMD , err = files .Handler .ReadAnalyzed (r .AnalyzedPath , cmd .DefaultLogger ); err == nil {
108- if r .supportsBuildImageExtension () && r .BuildImageRef != "" {
109- cmd .DefaultLogger .Debugf ("Pulling builder image metadata for %s..." , r .BuildImageRef )
110- remoteBuildImage , err := r .pullSparse (r .BuildImageRef )
111- if err != nil {
112- return cmd .FailErr (err , fmt .Sprintf ("pull builder image %s" , r .BuildImageRef ))
113- }
114- digestRef , err := remoteBuildImage .Identifier ()
115- if err != nil {
116- return cmd .FailErr (err , "get digest reference for builder image" )
117- }
118- analyzedMD .BuildImage = & files.ImageIdentifier {Reference : digestRef .String ()}
119- cmd .DefaultLogger .Debugf ("Adding build image info to analyzed metadata: " )
120- cmd .DefaultLogger .Debugf (encoding .ToJSONMaybe (analyzedMD .BuildImage ))
121- }
122- var (
123- runImage imgutil.Image
124- )
125- runImageName := analyzedMD .RunImageImage () // FIXME: if we have a digest reference available in `Reference` (e.g., in the non-daemon case) we should use it
126- if r .supportsRunImageExtension () && needsPulling (analyzedMD .RunImage ) {
127- cmd .DefaultLogger .Debugf ("Pulling run image metadata for %s..." , runImageName )
128- runImage , err = r .pullSparse (runImageName )
129- if err != nil {
130- return cmd .FailErr (err , fmt .Sprintf ("pull run image %s" , runImageName ))
131- }
132- // update analyzed metadata, even if we only needed to pull the image metadata, because
133- // the extender needs a digest reference in analyzed.toml,
134- // and daemon images will only have a daemon image ID
135- if err = r .updateAnalyzedMD (& analyzedMD , runImage ); err != nil {
136- return cmd .FailErr (err , "update analyzed metadata" )
137- }
138- } else if r .needsUpdating (analyzedMD .RunImage , group ) {
139- cmd .DefaultLogger .Debugf ("Updating run image info in analyzed metadata..." )
140- h := image .NewHandler (r .docker , r .keychain , r .LayoutDir , r .UseLayout , r .InsecureRegistries )
141- runImage , err = h .InitImage (runImageName )
142- if err != nil || ! runImage .Found () {
143- return cmd .FailErr (err , fmt .Sprintf ("get run image %s" , runImageName ))
144- }
145- if err = r .updateAnalyzedMD (& analyzedMD , runImage ); err != nil {
146- return cmd .FailErr (err , "update analyzed metadata" )
147- }
148- }
149- if err = files .Handler .WriteAnalyzed (r .AnalyzedPath , & analyzedMD , cmd .DefaultLogger ); err != nil {
150- return cmd .FailErr (err , "write analyzed metadata" )
151- }
152- } else {
153- cmd .DefaultLogger .Warnf ("Not using analyzed data, usable file not found: %s" , err )
154- }
155-
156- cacheStore , err := initCache (r .CacheImageRef , r .CacheDir , r .keychain , r .PlatformAPI .LessThan ("0.13" ))
157- if err != nil {
158- return err
159- }
160- return r .restore (analyzedMD .LayersMetadata , group , cacheStore )
161- }
162-
163- func (r * restoreCmd ) updateAnalyzedMD (analyzedMD * files.Analyzed , runImage imgutil.Image ) error {
164- if r .PlatformAPI .LessThan ("0.10" ) {
165- return nil
166- }
167- digestRef , err := runImage .Identifier ()
168- if err != nil {
169- return cmd .FailErr (err , "get digest reference for run image" )
170- }
171- var targetData * files.TargetMetadata
172- if r .PlatformAPI .AtLeast ("0.12" ) {
173- targetData , err = platform .GetTargetMetadata (runImage )
174- if err != nil {
175- return cmd .FailErr (err , "read target data from run image" )
176- }
177- }
178- cmd .DefaultLogger .Debugf ("Run image info in analyzed metadata was: " )
179- cmd .DefaultLogger .Debugf (encoding .ToJSONMaybe (analyzedMD .RunImage ))
180- analyzedMD .RunImage .Reference = digestRef .String ()
181- analyzedMD .RunImage .TargetMetadata = targetData
182- cmd .DefaultLogger .Debugf ("Run image info in analyzed metadata is: " )
183- cmd .DefaultLogger .Debugf (encoding .ToJSONMaybe (analyzedMD .RunImage ))
184- return nil
185- }
186-
187- func needsPulling (runImage * files.RunImage ) bool {
188- if runImage == nil {
189- // sanity check to prevent panic, should be unreachable
190- return false
191- }
192- return runImage .Extend
193- }
194-
195- func (r * restoreCmd ) needsUpdating (runImage * files.RunImage , group buildpack.Group ) bool {
196- if r .PlatformAPI .LessThan ("0.10" ) {
197- return false
198- }
199- if ! group .HasExtensions () {
200- return false
201- }
202- if runImage == nil {
203- // sanity check to prevent panic, should be unreachable
204- return false
205- }
206- if isPopulated (runImage .TargetMetadata ) {
207- return false
208- }
209- return true
210- }
211-
212- func isPopulated (metadata * files.TargetMetadata ) bool {
213- return metadata != nil && metadata .OS != ""
214- }
215-
216- func (r * restoreCmd ) supportsBuildImageExtension () bool {
217- return r .PlatformAPI .AtLeast ("0.10" )
218- }
219-
220- func (r * restoreCmd ) supportsRunImageExtension () bool {
221- return r .PlatformAPI .AtLeast ("0.12" ) && ! r .UseLayout // FIXME: add layout support as part of https://github.com/buildpacks/lifecycle/issues/1102
222- }
223-
224- func (r * restoreCmd ) supportsTargetData () bool {
225- return r .PlatformAPI .AtLeast ("0.12" )
226- }
227-
228- func (r * restoreCmd ) pullSparse (imageRef string ) (imgutil.Image , error ) {
229- baseCacheDir := filepath .Join (kanikoDir , "cache" , "base" )
230- if err := os .MkdirAll (baseCacheDir , 0755 ); err != nil {
231- return nil , fmt .Errorf ("failed to create cache directory: %w" , err )
232- }
233-
234- var opts []imgutil.ImageOption
235- opts = append (opts , append (image .GetInsecureOptions (r .InsecureRegistries ), remote .FromBaseImage (imageRef ))... )
236-
237- // get remote image
238- remoteImage , err := remote .NewImage (imageRef , r .keychain , opts ... )
239- if err != nil {
240- return nil , fmt .Errorf ("failed to initialize remote image: %w" , err )
241- }
242- if ! remoteImage .Found () {
243- return nil , fmt .Errorf ("failed to get remote image" )
244- }
245- // check for usable kaniko dir
246- if _ , err := os .Stat (kanikoDir ); err != nil {
247- if ! os .IsNotExist (err ) {
248- return nil , fmt .Errorf ("failed to read kaniko directory: %w" , err )
249- }
250- return nil , nil
251- }
252- // save to disk
253- h , err := remoteImage .UnderlyingImage ().Digest ()
254- if err != nil {
255- return nil , fmt .Errorf ("failed to get remote image digest: %w" , err )
256- }
257- path := filepath .Join (baseCacheDir , h .String ())
258- cmd .DefaultLogger .Debugf ("Saving image metadata to %s..." , path )
259- sparseImage , err := sparse .NewImage (
260- path ,
261- remoteImage .UnderlyingImage (),
262- layout .WithMediaTypes (imgutil .DefaultTypes ),
88+ factory := phase .NewConnectedFactory (
89+ r .PlatformAPI ,
90+ & cmd.BuildpackAPIVerifier {},
91+ NewCacheHandler (r .keychain ),
92+ files .Handler ,
93+ image .NewHandler (r .docker , r .keychain , r .LayoutDir , r .UseLayout , r .InsecureRegistries ),
94+ image .NewRegistryHandler (r .keychain , r .InsecureRegistries ),
26395 )
96+ restorer , err := factory .NewRestorer (r .Inputs (), cmd .DefaultLogger , buildpack.Group {})
26497 if err != nil {
265- return nil , fmt . Errorf ( "failed to initialize sparse image: %w" , err )
98+ return unwrapErrorFailWithMessage ( err , " initialize restorer" )
26699 }
267- if err = sparseImage . Save (); err != nil {
268- return nil , fmt . Errorf ( "failed to save sparse image: %w" , err )
100+ if err = restorer . RestoreAnalyzed (); err != nil {
101+ return cmd . FailErrCode ( err , r . CodeFor ( platform . RestoreError ), "restore" )
269102 }
270- return remoteImage , nil
271- }
272-
273- func (r * restoreCmd ) restore (layerMetadata files.LayersMetadata , group buildpack.Group , cacheStore phase.Cache ) error {
274- restorer := & phase.Restorer {
275- LayersDir : r .LayersDir ,
276- Buildpacks : group .Group ,
277- Logger : cmd .DefaultLogger ,
278- PlatformAPI : r .PlatformAPI ,
279- LayerMetadataRestorer : layer .NewDefaultMetadataRestorer (r .LayersDir , r .SkipLayers , cmd .DefaultLogger ),
280- LayersMetadata : layerMetadata ,
281- SBOMRestorer : layer .NewSBOMRestorer (layer.SBOMRestorerOpts {
282- LayersDir : r .LayersDir ,
283- Logger : cmd .DefaultLogger ,
284- Nop : r .SkipLayers ,
285- }, r .PlatformAPI ),
103+ if err = files .Handler .WriteAnalyzed (r .AnalyzedPath , & restorer .AnalyzedMD , cmd .DefaultLogger ); err != nil {
104+ return cmd .FailErr (err , "write analyzed metadata" )
286105 }
287- if err : = restorer .Restore ( cacheStore ); err != nil {
106+ if err = restorer .RestoreCache ( ); err != nil {
288107 return cmd .FailErrCode (err , r .CodeFor (platform .RestoreError ), "restore" )
289108 }
290109 return nil
0 commit comments