Add the ability to skip unpacking the initial file system (#2234)

- Adds a new option, InitialFSUnpacked
- When opts.InitialFSUnpacked is true, the first stage builder will
  skip unpacking the file system; later stages are unaffected

Signed-off-by: Natalie Arellano <narellano@vmware.com>

Signed-off-by: Natalie Arellano <narellano@vmware.com>
This commit is contained in:
Natalie Arellano 2022-09-06 10:21:12 -04:00 committed by GitHub
parent a9d500c554
commit 76c0a8c1ec
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 36 additions and 13 deletions

View File

@ -82,6 +82,7 @@ type KanikoOptions struct {
CacheCopyLayers bool
CacheRunLayers bool
ForceBuildMetadata bool
InitialFSUnpacked bool
}
type KanikoGitOptions struct {

View File

@ -55,6 +55,7 @@ const emptyTarSize = 1024
// for testing
var (
initializeConfig = initConfig
getFSFromImage = util.GetFSFromImage
)
type cachePusher func(*config.KanikoOptions, string, string, string) error
@ -322,12 +323,15 @@ func (s *stageBuilder) build() error {
if len(s.crossStageDeps[s.stage.Index]) > 0 {
shouldUnpack = true
}
if s.stage.Index == 0 && s.opts.InitialFSUnpacked {
shouldUnpack = false
}
if shouldUnpack {
t := timing.Start("FS Unpacking")
retryFunc := func() error {
_, err := util.GetFSFromImage(config.RootDir, s.image, util.ExtractFile)
_, err := getFSFromImage(config.RootDir, s.image, util.ExtractFile)
return err
}
@ -622,7 +626,6 @@ func DoBuild(opts *config.KanikoOptions) (v1.Image, error) {
var args *dockerfile.BuildArgs
for index, stage := range kanikoStages {
sb, err := newStageBuilder(
args, opts, stage,
crossStageDependencies,

View File

@ -727,17 +727,20 @@ func Test_stageBuilder_populateCompositeKey(t *testing.T) {
func Test_stageBuilder_build(t *testing.T) {
type testcase struct {
description string
opts *config.KanikoOptions
args map[string]string
layerCache *fakeLayerCache
expectedCacheKeys []string
pushedCacheKeys []string
commands []commands.DockerCommand
fileName string
rootDir string
image v1.Image
config *v1.ConfigFile
description string
opts *config.KanikoOptions
args map[string]string
layerCache *fakeLayerCache
expectedCacheKeys []string
pushedCacheKeys []string
commands []commands.DockerCommand
fileName string
rootDir string
image v1.Image
config *v1.ConfigFile
stage config.KanikoStage
crossStageDeps map[int][]string
mockGetFSFromImage func(root string, img v1.Image, extract util.ExtractFunction) ([]string, error)
}
testCases := []testcase{
@ -1238,6 +1241,15 @@ RUN foobar
rootDir: dir,
}
}(),
{
description: "fs unpacked",
opts: &config.KanikoOptions{InitialFSUnpacked: true},
stage: config.KanikoStage{Index: 0},
crossStageDeps: map[int][]string{0: {"some-dep"}},
mockGetFSFromImage: func(root string, img v1.Image, extract util.ExtractFunction) ([]string, error) {
return nil, fmt.Errorf("getFSFromImage shouldn't be called if fs is already unpacked")
},
},
}
for _, tc := range testCases {
t.Run(tc.description, func(t *testing.T) {
@ -1294,6 +1306,13 @@ RUN foobar
if tc.rootDir != "" {
config.RootDir = tc.rootDir
}
sb.stage = tc.stage
sb.crossStageDeps = tc.crossStageDeps
if tc.mockGetFSFromImage != nil {
original := getFSFromImage
defer func() { getFSFromImage = original }()
getFSFromImage = tc.mockGetFSFromImage
}
err := sb.build()
if err != nil {
t.Errorf("Expected error to be nil but was %v", err)