Skip to content

Commit 361e584

Browse files
authored
mz440: cleanup kaniko workspace on failure too (#453)
* mz440: cleanup kaniko dir * mz440: cleanup on failure too * ai review * address review items
1 parent b719f0b commit 361e584

File tree

3 files changed

+98
-17
lines changed

3 files changed

+98
-17
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -967,7 +967,7 @@ ie. in order to support custom built kaniko images.
967967

968968
#### Flag `--cleanup`
969969

970-
Set this flag to clean the filesystem at the end of the build.
970+
Set this flag to clean the filesystem and kaniko's working directory at the end of the build.
971971

972972
#### Flag `--compression`
973973

pkg/config/init.go

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,11 @@ limitations under the License.
1717
package config
1818

1919
import (
20+
"errors"
2021
"fmt"
2122
"os"
2223
"path/filepath"
24+
"strings"
2325

2426
"github.com/osscontainertools/kaniko/pkg/constants"
2527
"github.com/sirupsen/logrus"
@@ -94,3 +96,68 @@ func init() {
9496
RootDir = constants.RootDir
9597
MountInfoPath = constants.MountInfoPath
9698
}
99+
100+
// Same as os.RemoveAll, but asserts that we don't delete / or /kaniko.
101+
// This should be impossible at runtime and would indicate a programming mistake.
102+
func safeRemove(target string) error {
103+
targetInfo, err := os.Stat(target)
104+
if errors.Is(err, os.ErrNotExist) {
105+
return nil
106+
} else if err != nil {
107+
return fmt.Errorf("failed to stat %q: %w", target, err)
108+
}
109+
rootInfo, err := os.Stat(RootDir)
110+
if err != nil {
111+
return fmt.Errorf("failed to stat %q: %w", RootDir, err)
112+
}
113+
kanikoInfo, err := os.Stat(KanikoDir)
114+
if err != nil {
115+
return fmt.Errorf("failed to stat %q: %w", KanikoDir, err)
116+
}
117+
if os.SameFile(targetInfo, rootInfo) {
118+
logrus.Fatalf("refusing to remove /")
119+
}
120+
if os.SameFile(targetInfo, kanikoInfo) {
121+
logrus.Fatalf("refusing to remove %q", KanikoDir)
122+
}
123+
if !strings.HasPrefix(target, KanikoDir+"/") {
124+
logrus.Fatalf("refusing to remove %q outside %q", target, KanikoDir)
125+
}
126+
return os.RemoveAll(target)
127+
}
128+
129+
func Cleanup() error {
130+
err := safeRemove(DockerfilePath)
131+
if err != nil {
132+
return err
133+
}
134+
err = safeRemove(KanikoIntermediateStagesDir)
135+
if err != nil {
136+
return err
137+
}
138+
err = safeRemove(BuildContextDir)
139+
if err != nil {
140+
return err
141+
}
142+
if EnvBoolDefault("FF_KANIKO_NEW_CACHE_LAYOUT", true) {
143+
err = safeRemove(KanikoInterStageDepsDir)
144+
if err != nil {
145+
return err
146+
}
147+
err = safeRemove(KanikoLayersDir)
148+
if err != nil {
149+
return err
150+
}
151+
}
152+
err = safeRemove(KanikoSecretsDir)
153+
if err != nil {
154+
return err
155+
}
156+
_, err = os.Stat(KanikoSwapDir)
157+
if err == nil {
158+
return fmt.Errorf("expected directory %q to not exist, but it does", KanikoSwapDir)
159+
} else if !errors.Is(err, os.ErrNotExist) {
160+
return fmt.Errorf("failed to stat %q: %w", KanikoSwapDir, err)
161+
}
162+
return nil
163+
}

pkg/executor/build.go

Lines changed: 30 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -724,7 +724,7 @@ func CalculateDependencies(stages []config.KanikoStage, opts *config.KanikoOptio
724724
}
725725

726726
// DoBuild executes building the Dockerfile
727-
func DoBuild(opts *config.KanikoOptions) (v1.Image, error) {
727+
func DoBuild(opts *config.KanikoOptions) (image v1.Image, retErr error) {
728728
t := timing.Start("Total Build Time")
729729
digestToCacheKey := make(map[string]string)
730730
stageIdxToDigest := make(map[int]string)
@@ -792,6 +792,29 @@ func DoBuild(opts *config.KanikoOptions) (v1.Image, error) {
792792
}
793793
}
794794

795+
if opts.Cleanup {
796+
defer assignIfNil(&retErr, func() error {
797+
if err = util.DeleteFilesystem(); err != nil {
798+
return err
799+
}
800+
err = config.Cleanup()
801+
if err != nil {
802+
return err
803+
}
804+
if opts.PreserveContext {
805+
if tarball == "" {
806+
return fmt.Errorf("context snapshot is missing")
807+
}
808+
_, err := util.UnpackLocalTarArchive(tarball, config.RootDir)
809+
if err != nil {
810+
return fmt.Errorf("failed to unpack context snapshot: %w", err)
811+
}
812+
logrus.Info("Context restored")
813+
}
814+
return nil
815+
})
816+
}
817+
795818
for _, stage := range kanikoStages {
796819
sb, err := newStageBuilder(
797820
args, opts, stage,
@@ -859,21 +882,6 @@ func DoBuild(opts *config.KanikoOptions) (v1.Image, error) {
859882
if len(opts.Annotations) > 0 {
860883
sourceImage = mutate.Annotations(sourceImage, opts.Annotations).(v1.Image)
861884
}
862-
if opts.Cleanup {
863-
if err = util.DeleteFilesystem(); err != nil {
864-
return nil, err
865-
}
866-
if opts.PreserveContext {
867-
if tarball == "" {
868-
return nil, fmt.Errorf("context snapshot is missing")
869-
}
870-
_, err := util.UnpackLocalTarArchive(tarball, config.RootDir)
871-
if err != nil {
872-
return nil, fmt.Errorf("failed to unpack context snapshot: %w", err)
873-
}
874-
logrus.Info("Context restored")
875-
}
876-
}
877885
timing.DefaultRun.Stop(t)
878886
return sourceImage, nil
879887
}
@@ -919,6 +927,12 @@ func DoBuild(opts *config.KanikoOptions) (v1.Image, error) {
919927
return nil, err
920928
}
921929

930+
func assignIfNil(dst *error, fn func() error) {
931+
if err := fn(); err != nil && *dst == nil {
932+
*dst = err
933+
}
934+
}
935+
922936
// filesToSave returns all the files matching the given pattern in deps.
923937
// If a file is a symlink, it also returns the target file.
924938
func filesToSave(deps []string) ([]string, error) {

0 commit comments

Comments
 (0)