Skip to content

Commit

Permalink
Export cache image and app image in parallel
Browse files Browse the repository at this point in the history
Signed-off-by: Woa <[email protected]>
  • Loading branch information
ESWZY committed Aug 18, 2023
1 parent f8b3419 commit 78fb788
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 28 deletions.
3 changes: 3 additions & 0 deletions acceptance/exporter_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -314,8 +314,11 @@ func testExporterFunc(platformAPI string) func(t *testing.T, when spec.G, it spe
)
h.AssertStringContains(t, output, "Saving "+exportedImageName)

// To detect whether the export of cacheImage and exportedImage is successful
h.Run(t, exec.Command("docker", "pull", exportedImageName))
assertImageOSAndArchAndCreatedAt(t, exportedImageName, exportTest, imgutil.NormalizedDateTime)

h.Run(t, exec.Command("docker", "pull", cacheImageName))
})

it("is created with empty layer", func() {
Expand Down
57 changes: 37 additions & 20 deletions cmd/lifecycle/exporter.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"os"
"path/filepath"
"strconv"
"sync"
"time"

"github.com/BurntSushi/toml"
Expand Down Expand Up @@ -205,31 +206,47 @@ func (e *exportCmd) export(group buildpack.Group, cacheStore lifecycle.Cache, an
return err
}

report, err := exporter.Export(lifecycle.ExportOptions{
AdditionalNames: e.AdditionalTags,
AppDir: e.AppDir,
DefaultProcessType: e.DefaultProcessType,
ExtendedDir: e.ExtendedDir,
LauncherConfig: launcherConfig(e.LauncherPath, e.LauncherSBOMDir),
LayersDir: e.LayersDir,
OrigMetadata: analyzedMD.LayersMetadata,
Project: projectMD,
RunImageRef: runImageID,
RunImageForExport: runImageForExport,
WorkingImage: appImage,
})
if err != nil {
return cmd.FailErrCode(err, e.CodeFor(platform.ExportError), "export")
var exportWaitGroup sync.WaitGroup
var report files.Report
var appErr error
appErr = nil

exportWaitGroup.Add(1)
go func() {
defer exportWaitGroup.Done()
report, appErr = exporter.Export(lifecycle.ExportOptions{
AdditionalNames: e.AdditionalTags,
AppDir: e.AppDir,
DefaultProcessType: e.DefaultProcessType,
ExtendedDir: e.ExtendedDir,
LauncherConfig: launcherConfig(e.LauncherPath, e.LauncherSBOMDir),
LayersDir: e.LayersDir,
OrigMetadata: analyzedMD.LayersMetadata,
Project: projectMD,
RunImageRef: runImageID,
RunImageForExport: runImageForExport,
WorkingImage: appImage,
})
}()

exportWaitGroup.Add(1)
go func() {
defer exportWaitGroup.Done()
if cacheStore != nil {
if cacheErr := exporter.Cache(e.LayersDir, cacheStore); cacheErr != nil {
cmd.DefaultLogger.Warnf("Failed to export cache: %v\n", cacheErr)
}
}
}()

exportWaitGroup.Wait()
if appErr != nil {
return cmd.FailErrCode(appErr, e.CodeFor(platform.ExportError), "export")
}
if err = encoding.WriteTOML(e.ReportPath, &report); err != nil {
return cmd.FailErrCode(err, e.CodeFor(platform.ExportError), "write export report")
}

if cacheStore != nil {
if cacheErr := exporter.Cache(e.LayersDir, cacheStore); cacheErr != nil {
cmd.DefaultLogger.Warnf("Failed to export cache: %v\n", cacheErr)
}
}
return nil
}

Expand Down
16 changes: 8 additions & 8 deletions layers/factory.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"os"
"path/filepath"
"strings"
"sync"

v1 "github.com/google/go-containerregistry/pkg/v1"

Expand All @@ -27,7 +28,8 @@ type Factory struct {
UID, GID int // UID and GID are used to normalize layer entries
Logger log.Logger

tarHashes map[string]string // tarHases Stores hashes of layer tarballs for reuse between the export and cache steps.
// tarHashes stores hashes of layer tarballs for reuse between the export and cache steps.
tarHashes sync.Map
}

type Layer struct {
Expand All @@ -39,15 +41,13 @@ type Layer struct {

func (f *Factory) writeLayer(id, createdBy string, addEntries func(tw *archive.NormalizingTarWriter) error) (layer Layer, err error) {
tarPath := filepath.Join(f.ArtifactsDir, escape(id)+".tar")
if f.tarHashes == nil {
f.tarHashes = make(map[string]string)
}
if sha, ok := f.tarHashes[tarPath]; ok {
f.Logger.Debugf("Reusing tarball for layer %q with SHA: %s\n", id, sha)
if sha, ok := f.tarHashes.Load(tarPath); ok {
shaString := sha.(string)
f.Logger.Debugf("Reusing tarball for layer %q with SHA: %s\n", id, shaString)
return Layer{
ID: id,
TarPath: tarPath,
Digest: sha,
Digest: shaString,
History: v1.History{CreatedBy: createdBy},
}, nil
}
Expand All @@ -69,7 +69,7 @@ func (f *Factory) writeLayer(id, createdBy string, addEntries func(tw *archive.N
return Layer{}, err
}
digest := lw.Digest()
f.tarHashes[tarPath] = digest
f.tarHashes.Store(tarPath, digest)
return Layer{
ID: id,
Digest: digest,
Expand Down

0 comments on commit 78fb788

Please sign in to comment.