github.com/containerd/containerd@v22.0.0-20200918172823-438c87b8e050+incompatible/archive/tar_linux_test.go (about) 1 // +build linux 2 3 /* 4 Copyright The containerd Authors. 5 6 Licensed under the Apache License, Version 2.0 (the "License"); 7 you may not use this file except in compliance with the License. 8 You may obtain a copy of the License at 9 10 http://www.apache.org/licenses/LICENSE-2.0 11 12 Unless required by applicable law or agreed to in writing, software 13 distributed under the License is distributed on an "AS IS" BASIS, 14 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 See the License for the specific language governing permissions and 16 limitations under the License. 17 */ 18 19 package archive 20 21 import ( 22 "bytes" 23 "context" 24 "fmt" 25 "io" 26 "io/ioutil" 27 "os" 28 "strings" 29 "testing" 30 31 "github.com/containerd/containerd/log/logtest" 32 "github.com/containerd/containerd/mount" 33 "github.com/containerd/containerd/pkg/testutil" 34 "github.com/containerd/containerd/snapshots/overlay" 35 "github.com/containerd/continuity/fs" 36 "github.com/containerd/continuity/fs/fstest" 37 "github.com/pkg/errors" 38 ) 39 40 func TestOverlayApply(t *testing.T) { 41 testutil.RequiresRoot(t) 42 43 base, err := ioutil.TempDir("", "test-ovl-diff-apply-") 44 if err != nil { 45 t.Fatalf("unable to create temp dir: %+v", err) 46 } 47 defer os.RemoveAll(base) 48 49 if err := overlay.Supported(base); err != nil { 50 t.Skipf("skipping because overlay is not supported %v", err) 51 } 52 fstest.FSSuite(t, overlayDiffApplier{ 53 tmp: base, 54 diff: WriteDiff, 55 t: t, 56 }) 57 } 58 59 func TestOverlayApplyNoParents(t *testing.T) { 60 testutil.RequiresRoot(t) 61 62 base, err := ioutil.TempDir("", "test-ovl-diff-apply-") 63 if err != nil { 64 t.Fatalf("unable to create temp dir: %+v", err) 65 } 66 defer os.RemoveAll(base) 67 68 if err := overlay.Supported(base); err != nil { 69 t.Skipf("skipping because overlay is not supported %v", err) 70 } 71 fstest.FSSuite(t, overlayDiffApplier{ 72 tmp: base, 73 diff: func(ctx context.Context, w io.Writer, a, b string) error { 74 cw := newChangeWriter(w, b) 75 cw.addedDirs = nil 76 err := fs.Changes(ctx, a, b, cw.HandleChange) 77 if err != nil { 78 return errors.Wrap(err, "failed to create diff tar stream") 79 } 80 return cw.Close() 81 }, 82 t: t, 83 }) 84 } 85 86 type overlayDiffApplier struct { 87 tmp string 88 diff func(context.Context, io.Writer, string, string) error 89 t *testing.T 90 } 91 92 type overlayContext struct { 93 merged string 94 lowers []string 95 mounted bool 96 } 97 98 type contextKey struct{} 99 100 func (d overlayDiffApplier) TestContext(ctx context.Context) (context.Context, func(), error) { 101 merged, err := ioutil.TempDir(d.tmp, "merged") 102 if err != nil { 103 return ctx, nil, errors.Wrap(err, "failed to make merged dir") 104 } 105 106 oc := &overlayContext{ 107 merged: merged, 108 } 109 110 ctx = logtest.WithT(ctx, d.t) 111 112 return context.WithValue(ctx, contextKey{}, oc), func() { 113 if oc.mounted { 114 mount.Unmount(oc.merged, 0) 115 } 116 }, nil 117 } 118 119 func (d overlayDiffApplier) Apply(ctx context.Context, a fstest.Applier) (string, func(), error) { 120 oc := ctx.Value(contextKey{}).(*overlayContext) 121 122 applyCopy, err := ioutil.TempDir(d.tmp, "apply-copy-") 123 if err != nil { 124 return "", nil, errors.Wrap(err, "failed to create temp dir") 125 } 126 defer os.RemoveAll(applyCopy) 127 128 base := oc.merged 129 if len(oc.lowers) == 1 { 130 base = oc.lowers[0] 131 } 132 133 if err = fs.CopyDir(applyCopy, base); err != nil { 134 return "", nil, errors.Wrap(err, "failed to copy base") 135 } 136 137 if err := a.Apply(applyCopy); err != nil { 138 return "", nil, errors.Wrap(err, "failed to apply changes to copy of base") 139 } 140 141 buf := bytes.NewBuffer(nil) 142 143 if err := d.diff(ctx, buf, base, applyCopy); err != nil { 144 return "", nil, errors.Wrap(err, "failed to create diff") 145 } 146 147 if oc.mounted { 148 if err := mount.Unmount(oc.merged, 0); err != nil { 149 return "", nil, errors.Wrap(err, "failed to unmount") 150 } 151 oc.mounted = false 152 } 153 154 next, err := ioutil.TempDir(d.tmp, "lower-") 155 if err != nil { 156 return "", nil, errors.Wrap(err, "failed to create temp dir") 157 } 158 159 if _, err = Apply(ctx, next, buf, WithConvertWhiteout(OverlayConvertWhiteout), WithParents(oc.lowers)); err != nil { 160 return "", nil, errors.Wrap(err, "failed to apply tar stream") 161 } 162 163 oc.lowers = append([]string{next}, oc.lowers...) 164 165 if len(oc.lowers) == 1 { 166 return oc.lowers[0], nil, nil 167 } 168 169 m := mount.Mount{ 170 Type: "overlay", 171 Source: "overlay", 172 Options: []string{ 173 fmt.Sprintf("lowerdir=%s", strings.Join(oc.lowers, ":")), 174 }, 175 } 176 177 if err := m.Mount(oc.merged); err != nil { 178 return "", nil, errors.Wrapf(err, "failed to mount: %v", m) 179 } 180 oc.mounted = true 181 182 return oc.merged, nil, nil 183 }