Support force-building metadata layers into snapshot (#1731)
* feat: add support for forcing build metadata * Chore: Added snapshot forceBuildMetadata flag tests.
This commit is contained in:
parent
7e3954ac73
commit
b525d1e27b
|
|
@ -216,6 +216,7 @@ func addKanikoOptionsFlags() {
|
||||||
RootCmd.PersistentFlags().Var(&opts.Git, "git", "Branch to clone if build context is a git repository")
|
RootCmd.PersistentFlags().Var(&opts.Git, "git", "Branch to clone if build context is a git repository")
|
||||||
RootCmd.PersistentFlags().BoolVarP(&opts.CacheCopyLayers, "cache-copy-layers", "", false, "Caches copy layers")
|
RootCmd.PersistentFlags().BoolVarP(&opts.CacheCopyLayers, "cache-copy-layers", "", false, "Caches copy layers")
|
||||||
RootCmd.PersistentFlags().VarP(&opts.IgnorePaths, "ignore-path", "", "Ignore these paths when taking a snapshot. Set it repeatedly for multiple paths.")
|
RootCmd.PersistentFlags().VarP(&opts.IgnorePaths, "ignore-path", "", "Ignore these paths when taking a snapshot. Set it repeatedly for multiple paths.")
|
||||||
|
RootCmd.PersistentFlags().BoolVarP(&opts.ForceBuildMetadata, "force-build-metadata", "", false, "Force add metadata layers to build image")
|
||||||
}
|
}
|
||||||
|
|
||||||
// addHiddenFlags marks certain flags as hidden from the executor help text
|
// addHiddenFlags marks certain flags as hidden from the executor help text
|
||||||
|
|
|
||||||
|
|
@ -74,6 +74,7 @@ type KanikoOptions struct {
|
||||||
Git KanikoGitOptions
|
Git KanikoGitOptions
|
||||||
IgnorePaths multiArg
|
IgnorePaths multiArg
|
||||||
ImageFSExtractRetry int
|
ImageFSExtractRetry int
|
||||||
|
ForceBuildMetadata bool
|
||||||
}
|
}
|
||||||
|
|
||||||
type KanikoGitOptions struct {
|
type KanikoGitOptions struct {
|
||||||
|
|
|
||||||
|
|
@ -60,7 +60,7 @@ type cachePusher func(*config.KanikoOptions, string, string, string) error
|
||||||
type snapShotter interface {
|
type snapShotter interface {
|
||||||
Init() error
|
Init() error
|
||||||
TakeSnapshotFS() (string, error)
|
TakeSnapshotFS() (string, error)
|
||||||
TakeSnapshot([]string, bool) (string, error)
|
TakeSnapshot([]string, bool, bool) (string, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
// stageBuilder contains all fields necessary to build one stage of a Dockerfile
|
// stageBuilder contains all fields necessary to build one stage of a Dockerfile
|
||||||
|
|
@ -375,7 +375,8 @@ func (s *stageBuilder) build() error {
|
||||||
files = command.FilesToSnapshot()
|
files = command.FilesToSnapshot()
|
||||||
timing.DefaultRun.Stop(t)
|
timing.DefaultRun.Stop(t)
|
||||||
|
|
||||||
if !s.shouldTakeSnapshot(index, command.MetadataOnly()) {
|
if !s.shouldTakeSnapshot(index, command.MetadataOnly()) && !s.opts.ForceBuildMetadata{
|
||||||
|
logrus.Debugf("build: skipping snapshot for [%v]" , command.String())
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if isCacheCommand {
|
if isCacheCommand {
|
||||||
|
|
@ -429,7 +430,7 @@ func (s *stageBuilder) takeSnapshot(files []string, shdDelete bool) (string, err
|
||||||
} else {
|
} else {
|
||||||
// Volumes are very weird. They get snapshotted in the next command.
|
// Volumes are very weird. They get snapshotted in the next command.
|
||||||
files = append(files, util.Volumes()...)
|
files = append(files, util.Volumes()...)
|
||||||
snapshot, err = s.snapshotter.TakeSnapshot(files, shdDelete)
|
snapshot, err = s.snapshotter.TakeSnapshot(files, shdDelete, s.opts.ForceBuildMetadata)
|
||||||
}
|
}
|
||||||
timing.DefaultRun.Stop(t)
|
timing.DefaultRun.Stop(t)
|
||||||
return snapshot, err
|
return snapshot, err
|
||||||
|
|
@ -473,7 +474,7 @@ func (s *stageBuilder) saveSnapshotToLayer(tarPath string) (v1.Layer, error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "tar file path does not exist")
|
return nil, errors.Wrap(err, "tar file path does not exist")
|
||||||
}
|
}
|
||||||
if fi.Size() <= emptyTarSize {
|
if fi.Size() <= emptyTarSize && !s.opts.ForceBuildMetadata{
|
||||||
logrus.Info("No files were changed, appending empty layer to config. No layer added to image.")
|
logrus.Info("No files were changed, appending empty layer to config. No layer added to image.")
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -35,6 +35,9 @@ import (
|
||||||
// For testing
|
// For testing
|
||||||
var snapshotPathPrefix = ""
|
var snapshotPathPrefix = ""
|
||||||
|
|
||||||
|
// for user layer flag
|
||||||
|
var addUserLayer bool = true
|
||||||
|
|
||||||
// Snapshotter holds the root directory from which to take snapshots, and a list of snapshots taken
|
// Snapshotter holds the root directory from which to take snapshots, and a list of snapshots taken
|
||||||
type Snapshotter struct {
|
type Snapshotter struct {
|
||||||
l *LayeredMap
|
l *LayeredMap
|
||||||
|
|
@ -60,7 +63,7 @@ func (s *Snapshotter) Key() (string, error) {
|
||||||
|
|
||||||
// TakeSnapshot takes a snapshot of the specified files, avoiding directories in the ignorelist, and creates
|
// TakeSnapshot takes a snapshot of the specified files, avoiding directories in the ignorelist, and creates
|
||||||
// a tarball of the changed files. Return contents of the tarball, and whether or not any files were changed
|
// a tarball of the changed files. Return contents of the tarball, and whether or not any files were changed
|
||||||
func (s *Snapshotter) TakeSnapshot(files []string, shdCheckDelete bool) (string, error) {
|
func (s *Snapshotter) TakeSnapshot(files []string, shdCheckDelete bool, forceBuildMetadata bool) (string, error) {
|
||||||
f, err := ioutil.TempFile(config.KanikoDir, "")
|
f, err := ioutil.TempFile(config.KanikoDir, "")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
|
|
@ -68,7 +71,7 @@ func (s *Snapshotter) TakeSnapshot(files []string, shdCheckDelete bool) (string,
|
||||||
defer f.Close()
|
defer f.Close()
|
||||||
|
|
||||||
s.l.Snapshot()
|
s.l.Snapshot()
|
||||||
if len(files) == 0 {
|
if len(files) == 0 && !forceBuildMetadata {
|
||||||
logrus.Info("No files changed in this command, skipping snapshotting.")
|
logrus.Info("No files changed in this command, skipping snapshotting.")
|
||||||
return "", nil
|
return "", nil
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -214,7 +214,7 @@ func TestSnapshotFiles(t *testing.T) {
|
||||||
filesToSnapshot := []string{
|
filesToSnapshot := []string{
|
||||||
filepath.Join(testDir, "foo"),
|
filepath.Join(testDir, "foo"),
|
||||||
}
|
}
|
||||||
tarPath, err := snapshotter.TakeSnapshot(filesToSnapshot, false)
|
tarPath, err := snapshotter.TakeSnapshot(filesToSnapshot, false, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
@ -361,7 +361,7 @@ func TestSnasphotPreservesFileOrder(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Take a snapshot
|
// Take a snapshot
|
||||||
tarPath, err := snapshotter.TakeSnapshot(filesToSnapshot, false)
|
tarPath, err := snapshotter.TakeSnapshot(filesToSnapshot, false, false)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Error taking snapshot of fs: %s", err)
|
t.Fatalf("Error taking snapshot of fs: %s", err)
|
||||||
|
|
@ -391,6 +391,46 @@ func TestSnasphotPreservesFileOrder(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestSnapshotWithForceBuildMetadataSet(t *testing.T) {
|
||||||
|
_, snapshotter, cleanup, err := setUpTest()
|
||||||
|
defer cleanup()
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
filesToSnapshot := []string{}
|
||||||
|
|
||||||
|
// snapshot should be taken regardless, if forceBuildMetadata flag is set
|
||||||
|
filename, err := snapshotter.TakeSnapshot(filesToSnapshot, false, true)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Error taking snapshot of fs: %s", err)
|
||||||
|
}
|
||||||
|
if filename == "" {
|
||||||
|
t.Fatalf("Filename returned from snapshot is empty.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSnapshotWithForceBuildMetadataIsNotSet(t *testing.T) {
|
||||||
|
_, snapshotter, cleanup, err := setUpTest()
|
||||||
|
defer cleanup()
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
filesToSnapshot := []string{}
|
||||||
|
|
||||||
|
// snapshot should not be taken
|
||||||
|
filename, err := snapshotter.TakeSnapshot(filesToSnapshot, false, false)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Error taking snapshot of fs: %s", err)
|
||||||
|
}
|
||||||
|
if filename != "" {
|
||||||
|
t.Fatalf("Filename returned is expected to be empty.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestSnasphotPreservesWhiteoutOrder(t *testing.T) {
|
func TestSnasphotPreservesWhiteoutOrder(t *testing.T) {
|
||||||
newFiles := map[string]string{
|
newFiles := map[string]string{
|
||||||
"foo": "newbaz1",
|
"foo": "newbaz1",
|
||||||
|
|
@ -430,7 +470,7 @@ func TestSnasphotPreservesWhiteoutOrder(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Take a snapshot
|
// Take a snapshot
|
||||||
_, err = snapshotter.TakeSnapshot(filesToSnapshot, false)
|
_, err = snapshotter.TakeSnapshot(filesToSnapshot, false, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Error taking snapshot of fs: %s", err)
|
t.Fatalf("Error taking snapshot of fs: %s", err)
|
||||||
}
|
}
|
||||||
|
|
@ -444,7 +484,7 @@ func TestSnasphotPreservesWhiteoutOrder(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Take a snapshot again
|
// Take a snapshot again
|
||||||
tarPath, err := snapshotter.TakeSnapshot(filesToSnapshot, true)
|
tarPath, err := snapshotter.TakeSnapshot(filesToSnapshot, true, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Error taking snapshot of fs: %s", err)
|
t.Fatalf("Error taking snapshot of fs: %s", err)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue