github.com/latiif/helm@v2.15.0+incompatible/pkg/storage/storage_test.go (about) 1 /* 2 Copyright The Helm 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 storage // import "k8s.io/helm/pkg/storage" 18 19 import ( 20 "fmt" 21 "reflect" 22 "testing" 23 24 rspb "k8s.io/helm/pkg/proto/hapi/release" 25 "k8s.io/helm/pkg/storage/driver" 26 ) 27 28 func TestStorageCreate(t *testing.T) { 29 // initialize storage 30 storage := Init(driver.NewMemory()) 31 32 // create fake release 33 rls := ReleaseTestData{ 34 Name: "angry-beaver", 35 Version: 1, 36 }.ToRelease() 37 38 assertErrNil(t.Fatal, storage.Create(rls), "StoreRelease") 39 40 // fetch the release 41 res, err := storage.Get(rls.Name, rls.Version) 42 assertErrNil(t.Fatal, err, "QueryRelease") 43 44 // verify the fetched and created release are the same 45 if !reflect.DeepEqual(rls, res) { 46 t.Fatalf("Expected %q, got %q", rls, res) 47 } 48 } 49 50 func TestStorageUpdate(t *testing.T) { 51 // initialize storage 52 storage := Init(driver.NewMemory()) 53 54 // create fake release 55 rls := ReleaseTestData{ 56 Name: "angry-beaver", 57 Version: 1, 58 Status: rspb.Status_DEPLOYED, 59 }.ToRelease() 60 61 assertErrNil(t.Fatal, storage.Create(rls), "StoreRelease") 62 63 // modify the release 64 rls.Info.Status.Code = rspb.Status_DELETED 65 assertErrNil(t.Fatal, storage.Update(rls), "UpdateRelease") 66 67 // retrieve the updated release 68 res, err := storage.Get(rls.Name, rls.Version) 69 assertErrNil(t.Fatal, err, "QueryRelease") 70 71 // verify updated and fetched releases are the same. 72 if !reflect.DeepEqual(rls, res) { 73 t.Fatalf("Expected %q, got %q", rls, res) 74 } 75 } 76 77 func TestStorageDelete(t *testing.T) { 78 // initialize storage 79 storage := Init(driver.NewMemory()) 80 81 // create fake release 82 rls := ReleaseTestData{ 83 Name: "angry-beaver", 84 Version: 1, 85 }.ToRelease() 86 rls2 := ReleaseTestData{ 87 Name: "angry-beaver", 88 Version: 2, 89 }.ToRelease() 90 91 assertErrNil(t.Fatal, storage.Create(rls), "StoreRelease") 92 assertErrNil(t.Fatal, storage.Create(rls2), "StoreRelease") 93 94 // delete the release 95 res, err := storage.Delete(rls.Name, rls.Version) 96 assertErrNil(t.Fatal, err, "DeleteRelease") 97 98 // verify updated and fetched releases are the same. 99 if !reflect.DeepEqual(rls, res) { 100 t.Fatalf("Expected %q, got %q", rls, res) 101 } 102 103 hist, err := storage.History(rls.Name) 104 if err != nil { 105 t.Errorf("unexpected error: %s", err) 106 } 107 108 // We have now deleted one of the two records. 109 if len(hist) != 1 { 110 t.Errorf("expected 1 record for deleted release version, got %d", len(hist)) 111 } 112 113 if hist[0].Version != 2 { 114 t.Errorf("Expected version to be 2, got %d", hist[0].Version) 115 } 116 } 117 118 func TestStorageList(t *testing.T) { 119 // initialize storage 120 storage := Init(driver.NewMemory()) 121 122 // setup storage with test releases 123 setup := func() { 124 // release records 125 rls0 := ReleaseTestData{Name: "happy-catdog", Status: rspb.Status_SUPERSEDED}.ToRelease() 126 rls1 := ReleaseTestData{Name: "livid-human", Status: rspb.Status_SUPERSEDED}.ToRelease() 127 rls2 := ReleaseTestData{Name: "relaxed-cat", Status: rspb.Status_SUPERSEDED}.ToRelease() 128 rls3 := ReleaseTestData{Name: "hungry-hippo", Status: rspb.Status_DEPLOYED}.ToRelease() 129 rls4 := ReleaseTestData{Name: "angry-beaver", Status: rspb.Status_DEPLOYED}.ToRelease() 130 rls5 := ReleaseTestData{Name: "opulent-frog", Status: rspb.Status_DELETED}.ToRelease() 131 rls6 := ReleaseTestData{Name: "happy-liger", Status: rspb.Status_DELETED}.ToRelease() 132 133 // create the release records in the storage 134 assertErrNil(t.Fatal, storage.Create(rls0), "Storing release 'rls0'") 135 assertErrNil(t.Fatal, storage.Create(rls1), "Storing release 'rls1'") 136 assertErrNil(t.Fatal, storage.Create(rls2), "Storing release 'rls2'") 137 assertErrNil(t.Fatal, storage.Create(rls3), "Storing release 'rls3'") 138 assertErrNil(t.Fatal, storage.Create(rls4), "Storing release 'rls4'") 139 assertErrNil(t.Fatal, storage.Create(rls5), "Storing release 'rls5'") 140 assertErrNil(t.Fatal, storage.Create(rls6), "Storing release 'rls6'") 141 } 142 143 var listTests = []struct { 144 Description string 145 NumExpected int 146 ListFunc func() ([]*rspb.Release, error) 147 }{ 148 {"ListDeleted", 2, storage.ListDeleted}, 149 {"ListDeployed", 2, storage.ListDeployed}, 150 {"ListReleases", 7, storage.ListReleases}, 151 } 152 153 setup() 154 155 for _, tt := range listTests { 156 list, err := tt.ListFunc() 157 assertErrNil(t.Fatal, err, tt.Description) 158 // verify the count of releases returned 159 if len(list) != tt.NumExpected { 160 t.Errorf("ListReleases(%s): expected %d, actual %d", 161 tt.Description, 162 tt.NumExpected, 163 len(list)) 164 } 165 } 166 } 167 168 func TestStorageDeployed(t *testing.T) { 169 storage := Init(driver.NewMemory()) 170 171 const name = "angry-bird" 172 const vers = int32(4) 173 174 // setup storage with test releases 175 setup := func() { 176 // release records 177 rls0 := ReleaseTestData{Name: name, Version: 1, Status: rspb.Status_SUPERSEDED}.ToRelease() 178 rls1 := ReleaseTestData{Name: name, Version: 2, Status: rspb.Status_SUPERSEDED}.ToRelease() 179 rls2 := ReleaseTestData{Name: name, Version: 3, Status: rspb.Status_SUPERSEDED}.ToRelease() 180 rls3 := ReleaseTestData{Name: name, Version: 4, Status: rspb.Status_DEPLOYED}.ToRelease() 181 182 // create the release records in the storage 183 assertErrNil(t.Fatal, storage.Create(rls0), "Storing release 'angry-bird' (v1)") 184 assertErrNil(t.Fatal, storage.Create(rls1), "Storing release 'angry-bird' (v2)") 185 assertErrNil(t.Fatal, storage.Create(rls2), "Storing release 'angry-bird' (v3)") 186 assertErrNil(t.Fatal, storage.Create(rls3), "Storing release 'angry-bird' (v4)") 187 } 188 189 setup() 190 191 rls, err := storage.Last(name) 192 if err != nil { 193 t.Fatalf("Failed to query for deployed release: %s\n", err) 194 } 195 196 switch { 197 case rls == nil: 198 t.Fatalf("Release is nil") 199 case rls.Name != name: 200 t.Fatalf("Expected release name %q, actual %q\n", name, rls.Name) 201 case rls.Version != vers: 202 t.Fatalf("Expected release version %d, actual %d\n", vers, rls.Version) 203 case rls.Info.Status.Code != rspb.Status_DEPLOYED: 204 t.Fatalf("Expected release status 'DEPLOYED', actual %s\n", rls.Info.Status.Code) 205 } 206 } 207 208 func TestStorageHistory(t *testing.T) { 209 storage := Init(driver.NewMemory()) 210 211 const name = "angry-bird" 212 213 // setup storage with test releases 214 setup := func() { 215 // release records 216 rls0 := ReleaseTestData{Name: name, Version: 1, Status: rspb.Status_SUPERSEDED}.ToRelease() 217 rls1 := ReleaseTestData{Name: name, Version: 2, Status: rspb.Status_SUPERSEDED}.ToRelease() 218 rls2 := ReleaseTestData{Name: name, Version: 3, Status: rspb.Status_SUPERSEDED}.ToRelease() 219 rls3 := ReleaseTestData{Name: name, Version: 4, Status: rspb.Status_DEPLOYED}.ToRelease() 220 221 // create the release records in the storage 222 assertErrNil(t.Fatal, storage.Create(rls0), "Storing release 'angry-bird' (v1)") 223 assertErrNil(t.Fatal, storage.Create(rls1), "Storing release 'angry-bird' (v2)") 224 assertErrNil(t.Fatal, storage.Create(rls2), "Storing release 'angry-bird' (v3)") 225 assertErrNil(t.Fatal, storage.Create(rls3), "Storing release 'angry-bird' (v4)") 226 } 227 228 setup() 229 230 h, err := storage.History(name) 231 if err != nil { 232 t.Fatalf("Failed to query for release history (%q): %s\n", name, err) 233 } 234 if len(h) != 4 { 235 t.Fatalf("Release history (%q) is empty\n", name) 236 } 237 } 238 239 func TestStorageRemoveLeastRecent(t *testing.T) { 240 storage := Init(driver.NewMemory()) 241 storage.Log = t.Logf 242 243 // Make sure that specifying this at the outset doesn't cause any bugs. 244 storage.MaxHistory = 10 245 246 const name = "angry-bird" 247 248 // setup storage with test releases 249 setup := func() { 250 // release records 251 rls0 := ReleaseTestData{Name: name, Version: 1, Status: rspb.Status_SUPERSEDED}.ToRelease() 252 rls1 := ReleaseTestData{Name: name, Version: 2, Status: rspb.Status_SUPERSEDED}.ToRelease() 253 rls2 := ReleaseTestData{Name: name, Version: 3, Status: rspb.Status_SUPERSEDED}.ToRelease() 254 rls3 := ReleaseTestData{Name: name, Version: 4, Status: rspb.Status_DEPLOYED}.ToRelease() 255 256 // create the release records in the storage 257 assertErrNil(t.Fatal, storage.Create(rls0), "Storing release 'angry-bird' (v1)") 258 assertErrNil(t.Fatal, storage.Create(rls1), "Storing release 'angry-bird' (v2)") 259 assertErrNil(t.Fatal, storage.Create(rls2), "Storing release 'angry-bird' (v3)") 260 assertErrNil(t.Fatal, storage.Create(rls3), "Storing release 'angry-bird' (v4)") 261 } 262 setup() 263 264 // Because we have not set a limit, we expect 4. 265 expect := 4 266 if hist, err := storage.History(name); err != nil { 267 t.Fatal(err) 268 } else if len(hist) != expect { 269 t.Fatalf("expected %d items in history, got %d", expect, len(hist)) 270 } 271 272 storage.MaxHistory = 3 273 rls5 := ReleaseTestData{Name: name, Version: 5, Status: rspb.Status_DEPLOYED}.ToRelease() 274 assertErrNil(t.Fatal, storage.Create(rls5), "Storing release 'angry-bird' (v5)") 275 276 // On inserting the 5th record, we expect two records to be pruned from history. 277 hist, err := storage.History(name) 278 if err != nil { 279 t.Fatal(err) 280 } else if len(hist) != storage.MaxHistory { 281 for _, item := range hist { 282 t.Logf("%s %v", item.Name, item.Version) 283 } 284 t.Fatalf("expected %d items in history, got %d", storage.MaxHistory, len(hist)) 285 } 286 287 // We expect the existing records to be 3, 4, and 5. 288 for i, item := range hist { 289 v := int(item.Version) 290 if expect := i + 3; v != expect { 291 t.Errorf("Expected release %d, got %d", expect, v) 292 } 293 } 294 } 295 296 func TestStorageDontDeleteDeployed(t *testing.T) { 297 storage := Init(driver.NewMemory()) 298 storage.Log = t.Logf 299 storage.MaxHistory = 3 300 301 const name = "angry-bird" 302 303 // setup storage with test releases 304 setup := func() { 305 // release records 306 rls0 := ReleaseTestData{Name: name, Version: 1, Status: rspb.Status_SUPERSEDED}.ToRelease() 307 rls1 := ReleaseTestData{Name: name, Version: 2, Status: rspb.Status_DEPLOYED}.ToRelease() 308 rls2 := ReleaseTestData{Name: name, Version: 3, Status: rspb.Status_FAILED}.ToRelease() 309 rls3 := ReleaseTestData{Name: name, Version: 4, Status: rspb.Status_FAILED}.ToRelease() 310 311 // create the release records in the storage 312 assertErrNil(t.Fatal, storage.Create(rls0), "Storing release 'angry-bird' (v1)") 313 assertErrNil(t.Fatal, storage.Create(rls1), "Storing release 'angry-bird' (v2)") 314 assertErrNil(t.Fatal, storage.Create(rls2), "Storing release 'angry-bird' (v3)") 315 assertErrNil(t.Fatal, storage.Create(rls3), "Storing release 'angry-bird' (v4)") 316 } 317 setup() 318 319 rls5 := ReleaseTestData{Name: name, Version: 5, Status: rspb.Status_FAILED}.ToRelease() 320 assertErrNil(t.Fatal, storage.Create(rls5), "Storing release 'angry-bird' (v5)") 321 322 // On inserting the 5th record, we expect a total of 3 releases, but we expect version 2 323 // (the only deployed release), to still exist 324 hist, err := storage.History(name) 325 if err != nil { 326 t.Fatal(err) 327 } else if len(hist) != storage.MaxHistory { 328 for _, item := range hist { 329 t.Logf("%s %v", item.Name, item.Version) 330 } 331 t.Fatalf("expected %d items in history, got %d", storage.MaxHistory, len(hist)) 332 } 333 334 expectedVersions := map[int32]bool{ 335 2: true, 336 4: true, 337 5: true, 338 } 339 340 for _, item := range hist { 341 if !expectedVersions[item.GetVersion()] { 342 t.Errorf("Release version %d, found when not expected", item.GetVersion()) 343 } 344 } 345 } 346 347 func TestStorageLast(t *testing.T) { 348 storage := Init(driver.NewMemory()) 349 350 const name = "angry-bird" 351 352 // Set up storage with test releases. 353 setup := func() { 354 // release records 355 rls0 := ReleaseTestData{Name: name, Version: 1, Status: rspb.Status_SUPERSEDED}.ToRelease() 356 rls1 := ReleaseTestData{Name: name, Version: 2, Status: rspb.Status_SUPERSEDED}.ToRelease() 357 rls2 := ReleaseTestData{Name: name, Version: 3, Status: rspb.Status_SUPERSEDED}.ToRelease() 358 rls3 := ReleaseTestData{Name: name, Version: 4, Status: rspb.Status_FAILED}.ToRelease() 359 360 // create the release records in the storage 361 assertErrNil(t.Fatal, storage.Create(rls0), "Storing release 'angry-bird' (v1)") 362 assertErrNil(t.Fatal, storage.Create(rls1), "Storing release 'angry-bird' (v2)") 363 assertErrNil(t.Fatal, storage.Create(rls2), "Storing release 'angry-bird' (v3)") 364 assertErrNil(t.Fatal, storage.Create(rls3), "Storing release 'angry-bird' (v4)") 365 } 366 367 setup() 368 369 h, err := storage.Last(name) 370 if err != nil { 371 t.Fatalf("Failed to query for release history (%q): %s\n", name, err) 372 } 373 374 if h.Version != 4 { 375 t.Errorf("Expected revision 4, got %d", h.Version) 376 } 377 } 378 379 type ReleaseTestData struct { 380 Name string 381 Version int32 382 Manifest string 383 Namespace string 384 Status rspb.Status_Code 385 } 386 387 func (test ReleaseTestData) ToRelease() *rspb.Release { 388 return &rspb.Release{ 389 Name: test.Name, 390 Version: test.Version, 391 Manifest: test.Manifest, 392 Namespace: test.Namespace, 393 Info: &rspb.Info{Status: &rspb.Status{Code: test.Status}}, 394 } 395 } 396 397 func assertErrNil(eh func(args ...interface{}), err error, message string) { 398 if err != nil { 399 eh(fmt.Sprintf("%s: %q", message, err)) 400 } 401 }