github.com/kaisenlinux/docker.io@v0.0.0-20230510090727-ea55db55fac7/swarmkit/manager/state/raft/storage/snapwrap_test.go (about) 1 package storage 2 3 import ( 4 "fmt" 5 "io/ioutil" 6 "os" 7 "path/filepath" 8 "testing" 9 10 "github.com/coreos/etcd/raft/raftpb" 11 "github.com/docker/swarmkit/api" 12 "github.com/docker/swarmkit/manager/encryption" 13 "github.com/stretchr/testify/require" 14 ) 15 16 var _ SnapFactory = snapCryptor{} 17 18 var fakeSnapshotData = raftpb.Snapshot{ 19 Data: []byte("snapshotdata"), 20 Metadata: raftpb.SnapshotMetadata{ 21 ConfState: raftpb.ConfState{Nodes: []uint64{3}}, 22 Index: 6, 23 Term: 2, 24 }, 25 } 26 27 func getSnapshotFile(t *testing.T, tempdir string) string { 28 var filepaths []string 29 err := filepath.Walk(tempdir, func(path string, fi os.FileInfo, err error) error { 30 require.NoError(t, err) 31 if !fi.IsDir() { 32 filepaths = append(filepaths, path) 33 } 34 return nil 35 }) 36 require.NoError(t, err) 37 require.Len(t, filepaths, 1) 38 return filepaths[0] 39 } 40 41 // Snapshotter can read snapshots that are wrapped, but not encrypted 42 func TestSnapshotterLoadNotEncryptedSnapshot(t *testing.T) { 43 tempdir, err := ioutil.TempDir("", "snapwrap") 44 require.NoError(t, err) 45 defer os.RemoveAll(tempdir) 46 47 ogSnap := OriginalSnap.New(tempdir) 48 r := api.MaybeEncryptedRecord{ 49 Data: fakeSnapshotData.Data, 50 } 51 data, err := r.Marshal() 52 require.NoError(t, err) 53 54 emptyEncryptionFakeData := fakeSnapshotData 55 emptyEncryptionFakeData.Data = data 56 57 require.NoError(t, ogSnap.SaveSnap(emptyEncryptionFakeData)) 58 59 c := NewSnapFactory(encryption.NoopCrypter, encryption.NoopCrypter) 60 wrapped := c.New(tempdir) 61 62 readSnap, err := wrapped.Load() 63 require.NoError(t, err) 64 require.Equal(t, fakeSnapshotData, *readSnap) 65 } 66 67 // If there is no decrypter for a snapshot, decrypting fails 68 func TestSnapshotterLoadNoDecrypter(t *testing.T) { 69 tempdir, err := ioutil.TempDir("", "snapwrap") 70 require.NoError(t, err) 71 defer os.RemoveAll(tempdir) 72 73 ogSnap := OriginalSnap.New(tempdir) 74 r := api.MaybeEncryptedRecord{ 75 Data: fakeSnapshotData.Data, 76 Algorithm: meowCrypter{}.Algorithm(), 77 } 78 data, err := r.Marshal() 79 require.NoError(t, err) 80 81 emptyEncryptionFakeData := fakeSnapshotData 82 emptyEncryptionFakeData.Data = data 83 84 require.NoError(t, ogSnap.SaveSnap(emptyEncryptionFakeData)) 85 86 c := NewSnapFactory(encryption.NoopCrypter, encryption.NoopCrypter) 87 wrapped := c.New(tempdir) 88 89 _, err = wrapped.Load() 90 require.Error(t, err) 91 } 92 93 // If decrypting a snapshot fails, the error is propagated 94 func TestSnapshotterLoadDecryptingFail(t *testing.T) { 95 tempdir, err := ioutil.TempDir("", "snapwrap") 96 require.NoError(t, err) 97 defer os.RemoveAll(tempdir) 98 99 crypter := &meowCrypter{} 100 101 ogSnap := OriginalSnap.New(tempdir) 102 r := api.MaybeEncryptedRecord{ 103 Data: fakeSnapshotData.Data, 104 Algorithm: crypter.Algorithm(), 105 } 106 data, err := r.Marshal() 107 require.NoError(t, err) 108 109 emptyEncryptionFakeData := fakeSnapshotData 110 emptyEncryptionFakeData.Data = data 111 112 require.NoError(t, ogSnap.SaveSnap(emptyEncryptionFakeData)) 113 114 c := NewSnapFactory(encryption.NoopCrypter, crypter) 115 wrapped := c.New(tempdir) 116 117 _, err = wrapped.Load() 118 require.Error(t, err) 119 require.Contains(t, err.Error(), "not meowcoded") 120 } 121 122 // The snapshot data (but not metadata or anything else) is encryptd before being 123 // passed to the wrapped Snapshotter. 124 func TestSnapshotterSavesSnapshotWithEncryption(t *testing.T) { 125 tempdir, err := ioutil.TempDir("", "snapwrap") 126 require.NoError(t, err) 127 defer os.RemoveAll(tempdir) 128 129 c := NewSnapFactory(meowCrypter{}, encryption.NoopCrypter) 130 wrapped := c.New(tempdir) 131 require.NoError(t, wrapped.SaveSnap(fakeSnapshotData)) 132 133 ogSnap := OriginalSnap.New(tempdir) 134 readSnap, err := ogSnap.Load() 135 require.NoError(t, err) 136 137 r := api.MaybeEncryptedRecord{} 138 require.NoError(t, r.Unmarshal(readSnap.Data)) 139 require.NotEqual(t, fakeSnapshotData.Data, r.Data) 140 require.Equal(t, fakeSnapshotData.Metadata, readSnap.Metadata) 141 } 142 143 // If an encrypter is passed to Snapshotter, but encrypting the data fails, the 144 // error is propagated up 145 func TestSnapshotterSavesSnapshotEncryptionFails(t *testing.T) { 146 tempdir, err := ioutil.TempDir("", "snapwrap") 147 require.NoError(t, err) 148 defer os.RemoveAll(tempdir) 149 150 c := NewSnapFactory(&meowCrypter{encryptFailures: map[string]struct{}{ 151 "snapshotdata": {}, 152 }}, encryption.NoopCrypter) 153 wrapped := c.New(tempdir) 154 err = wrapped.SaveSnap(fakeSnapshotData) 155 require.Error(t, err) 156 require.Contains(t, err.Error(), "refusing to encrypt") 157 158 // nothing there to read 159 ogSnap := OriginalSnap.New(tempdir) 160 _, err = ogSnap.Load() 161 require.Error(t, err) 162 } 163 164 // Snapshotter can read what it wrote so long as it has the same decrypter 165 func TestSaveAndLoad(t *testing.T) { 166 crypter := &meowCrypter{} 167 tempdir, err := ioutil.TempDir("", "waltests") 168 require.NoError(t, err) 169 defer os.RemoveAll(tempdir) 170 171 c := NewSnapFactory(crypter, crypter) 172 wrapped := c.New(tempdir) 173 require.NoError(t, wrapped.SaveSnap(fakeSnapshotData)) 174 readSnap, err := wrapped.Load() 175 require.NoError(t, err) 176 require.Equal(t, fakeSnapshotData, *readSnap) 177 } 178 179 func TestMigrateSnapshot(t *testing.T) { 180 crypter := &meowCrypter{} 181 c := NewSnapFactory(crypter, crypter) 182 var ( 183 err error 184 dirs = make([]string, 3) 185 ) 186 187 tempDir, err := ioutil.TempDir("", "test-migrate") 188 require.NoError(t, err) 189 defer os.RemoveAll(tempDir) 190 191 for i := range dirs { 192 dirs[i] = filepath.Join(tempDir, fmt.Sprintf("snapDir%d", i)) 193 } 194 require.NoError(t, os.Mkdir(dirs[0], 0755)) 195 require.NoError(t, OriginalSnap.New(dirs[0]).SaveSnap(fakeSnapshotData)) 196 197 // original to new 198 oldDir := dirs[0] 199 newDir := dirs[1] 200 201 err = MigrateSnapshot(oldDir, newDir, OriginalSnap, c) 202 require.NoError(t, err) 203 204 readSnap, err := c.New(newDir).Load() 205 require.NoError(t, err) 206 require.Equal(t, fakeSnapshotData, *readSnap) 207 208 // new to original 209 oldDir = dirs[1] 210 newDir = dirs[2] 211 212 err = MigrateSnapshot(oldDir, newDir, c, OriginalSnap) 213 require.NoError(t, err) 214 215 readSnap, err = OriginalSnap.New(newDir).Load() 216 require.NoError(t, err) 217 require.Equal(t, fakeSnapshotData, *readSnap) 218 219 // We can migrate from empty directory without error 220 for _, dir := range dirs { 221 require.NoError(t, os.RemoveAll(dir)) 222 } 223 require.NoError(t, os.Mkdir(dirs[0], 0755)) 224 oldDir = dirs[0] 225 newDir = dirs[1] 226 227 err = MigrateSnapshot(oldDir, newDir, OriginalSnap, c) 228 require.NoError(t, err) 229 230 subdirs, err := ioutil.ReadDir(tempDir) 231 require.NoError(t, err) 232 require.Len(t, subdirs, 1) 233 }