github.com/containerd/Containerd@v1.4.13/snapshots/testsuite/issues.go (about) 1 /* 2 Copyright The containerd Authors. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package testsuite 18 19 import ( 20 "context" 21 "fmt" 22 "strings" 23 "testing" 24 "time" 25 26 "github.com/containerd/containerd/snapshots" 27 "github.com/containerd/continuity/fs/fstest" 28 ) 29 30 // Checks which cover former issues found in older layering models. 31 // 32 // NOTE: In older models, applying with tar was used to create read only layers, 33 // however with the snapshot model read only layers are created just using 34 // mounts and commits. Read write layers are a separate type of snapshot which 35 // is not committed, avoiding any confusion in the snapshotter about whether 36 // a snapshot will be mutated in the future. 37 38 // checkLayerFileUpdate tests the update of a single file in an upper layer 39 // Cause of issue was originally related to tar, snapshot should be able to 40 // avoid such issues by not relying on tar to create layers. 41 // See https://github.com/docker/docker/issues/21555 42 func checkLayerFileUpdate(ctx context.Context, t *testing.T, sn snapshots.Snapshotter, work string) { 43 l1Init := fstest.Apply( 44 fstest.CreateDir("/etc", 0700), 45 fstest.CreateFile("/etc/hosts", []byte("mydomain 10.0.0.1"), 0644), 46 fstest.CreateFile("/etc/profile", []byte("PATH=/usr/bin"), 0644), 47 ) 48 l2Init := fstest.Apply( 49 fstest.CreateFile("/etc/hosts", []byte("mydomain 10.0.0.2"), 0644), 50 fstest.CreateFile("/etc/profile", []byte("PATH=/usr/bin"), 0666), 51 fstest.CreateDir("/root", 0700), 52 fstest.CreateFile("/root/.bashrc", []byte("PATH=/usr/sbin:/usr/bin"), 0644), 53 ) 54 55 var sleepTime time.Duration 56 57 // run 5 times to account for sporadic failure 58 for i := 0; i < 5; i++ { 59 time.Sleep(sleepTime) 60 61 if err := checkSnapshots(ctx, sn, work, l1Init, l2Init); err != nil { 62 t.Fatalf("Check snapshots failed: %+v", err) 63 } 64 65 // Sleep until next second boundary before running again 66 nextTime := time.Now() 67 sleepTime = time.Unix(nextTime.Unix()+1, 0).Sub(nextTime) 68 } 69 } 70 71 // checkRemoveDirectoryInLowerLayer 72 // See https://github.com/docker/docker/issues/25244 73 func checkRemoveDirectoryInLowerLayer(ctx context.Context, t *testing.T, sn snapshots.Snapshotter, work string) { 74 l1Init := fstest.Apply( 75 fstest.CreateDir("/lib", 0700), 76 fstest.CreateFile("/lib/hidden", []byte{}, 0644), 77 ) 78 l2Init := fstest.Apply( 79 fstest.RemoveAll("/lib"), 80 fstest.CreateDir("/lib", 0700), 81 fstest.CreateFile("/lib/not-hidden", []byte{}, 0644), 82 ) 83 l3Init := fstest.Apply( 84 fstest.CreateFile("/lib/newfile", []byte{}, 0644), 85 ) 86 87 if err := checkSnapshots(ctx, sn, work, l1Init, l2Init, l3Init); err != nil { 88 t.Fatalf("Check snapshots failed: %+v", err) 89 } 90 } 91 92 // checkChown 93 // See https://github.com/docker/docker/issues/20240 aufs 94 // See https://github.com/docker/docker/issues/24913 overlay 95 // see https://github.com/docker/docker/issues/28391 overlay2 96 func checkChown(ctx context.Context, t *testing.T, sn snapshots.Snapshotter, work string) { 97 l1Init := fstest.Apply( 98 fstest.CreateDir("/opt", 0700), 99 fstest.CreateDir("/opt/a", 0700), 100 fstest.CreateDir("/opt/a/b", 0700), 101 fstest.CreateFile("/opt/a/b/file.txt", []byte("hello"), 0644), 102 ) 103 l2Init := fstest.Apply( 104 fstest.Chown("/opt", 1, 1), 105 fstest.Chown("/opt/a", 1, 1), 106 fstest.Chown("/opt/a/b", 1, 1), 107 fstest.Chown("/opt/a/b/file.txt", 1, 1), 108 ) 109 110 if err := checkSnapshots(ctx, sn, work, l1Init, l2Init); err != nil { 111 t.Fatalf("Check snapshots failed: %+v", err) 112 } 113 } 114 115 // checkRename 116 // https://github.com/docker/docker/issues/25409 117 func checkRename(ctx context.Context, t *testing.T, sn snapshots.Snapshotter, work string) { 118 t.Skip("rename test still fails on some kernels with overlay") 119 l1Init := fstest.Apply( 120 fstest.CreateDir("/dir1", 0700), 121 fstest.CreateDir("/somefiles", 0700), 122 fstest.CreateFile("/somefiles/f1", []byte("was here first!"), 0644), 123 fstest.CreateFile("/somefiles/f2", []byte("nothing interesting"), 0644), 124 ) 125 l2Init := fstest.Apply( 126 fstest.Rename("/dir1", "/dir2"), 127 fstest.CreateFile("/somefiles/f1-overwrite", []byte("new content 1"), 0644), 128 fstest.Rename("/somefiles/f1-overwrite", "/somefiles/f1"), 129 fstest.Rename("/somefiles/f2", "/somefiles/f3"), 130 ) 131 132 if err := checkSnapshots(ctx, sn, work, l1Init, l2Init); err != nil { 133 t.Fatalf("Check snapshots failed: %+v", err) 134 } 135 } 136 137 // checkDirectoryPermissionOnCommit 138 // https://github.com/docker/docker/issues/27298 139 func checkDirectoryPermissionOnCommit(ctx context.Context, t *testing.T, sn snapshots.Snapshotter, work string) { 140 l1Init := fstest.Apply( 141 fstest.CreateDir("/dir1", 0700), 142 fstest.CreateDir("/dir2", 0700), 143 fstest.CreateDir("/dir3", 0700), 144 fstest.CreateDir("/dir4", 0700), 145 fstest.CreateFile("/dir4/f1", []byte("..."), 0644), 146 fstest.CreateDir("/dir5", 0700), 147 fstest.CreateFile("/dir5/f1", []byte("..."), 0644), 148 fstest.Chown("/dir1", 1, 1), 149 fstest.Chown("/dir2", 1, 1), 150 fstest.Chown("/dir3", 1, 1), 151 fstest.Chown("/dir5", 1, 1), 152 fstest.Chown("/dir5/f1", 1, 1), 153 ) 154 l2Init := fstest.Apply( 155 fstest.Chown("/dir2", 0, 0), 156 fstest.RemoveAll("/dir3"), 157 fstest.Chown("/dir4", 1, 1), 158 fstest.Chown("/dir4/f1", 1, 1), 159 ) 160 l3Init := fstest.Apply( 161 fstest.CreateDir("/dir3", 0700), 162 fstest.Chown("/dir3", 1, 1), 163 fstest.RemoveAll("/dir5"), 164 fstest.CreateDir("/dir5", 0700), 165 fstest.Chown("/dir5", 1, 1), 166 ) 167 168 if err := checkSnapshots(ctx, sn, work, l1Init, l2Init, l3Init); err != nil { 169 t.Fatalf("Check snapshots failed: %+v", err) 170 } 171 } 172 173 // checkStatInWalk ensures that a stat can be called during a walk 174 func checkStatInWalk(ctx context.Context, t *testing.T, sn snapshots.Snapshotter, work string) { 175 prefix := "stats-in-walk-" 176 if err := createNamedSnapshots(ctx, sn, prefix); err != nil { 177 t.Fatal(err) 178 } 179 180 err := sn.Walk(ctx, func(ctx context.Context, si snapshots.Info) error { 181 if !strings.HasPrefix(si.Name, prefix) { 182 // Only stat snapshots from this test 183 return nil 184 } 185 si2, err := sn.Stat(ctx, si.Name) 186 if err != nil { 187 return err 188 } 189 190 return checkInfo(si, si2) 191 }) 192 if err != nil { 193 t.Fatal(err) 194 } 195 } 196 197 func createNamedSnapshots(ctx context.Context, snapshotter snapshots.Snapshotter, ns string) error { 198 c1 := fmt.Sprintf("%sc1", ns) 199 c2 := fmt.Sprintf("%sc2", ns) 200 if _, err := snapshotter.Prepare(ctx, c1+"-a", "", opt); err != nil { 201 return err 202 } 203 if err := snapshotter.Commit(ctx, c1, c1+"-a", opt); err != nil { 204 return err 205 } 206 if _, err := snapshotter.Prepare(ctx, c2+"-a", c1, opt); err != nil { 207 return err 208 } 209 if err := snapshotter.Commit(ctx, c2, c2+"-a", opt); err != nil { 210 return err 211 } 212 if _, err := snapshotter.Prepare(ctx, fmt.Sprintf("%sa1", ns), c2, opt); err != nil { 213 return err 214 } 215 if _, err := snapshotter.View(ctx, fmt.Sprintf("%sv1", ns), c2, opt); err != nil { 216 return err 217 } 218 return nil 219 } 220 221 // More issues to test 222 // 223 // checkRemoveAfterCommit 224 // See https://github.com/docker/docker/issues/24309 225 // 226 // checkUnixDomainSockets 227 // See https://github.com/docker/docker/issues/12080 228 // 229 // checkDirectoryInodeStability 230 // See https://github.com/docker/docker/issues/19647 231 // 232 // checkOpenFileInodeStability 233 // See https://github.com/docker/docker/issues/12327 234 // 235 // checkGetCWD 236 // See https://github.com/docker/docker/issues/19082 237 // 238 // checkChmod 239 // See https://github.com/docker/machine/issues/3327 240 // 241 // checkRemoveInWalk 242 // Allow mutations during walk without deadlocking