github.com/koderover/helm@v2.17.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 TestStorageDeployedWithCorruption(t *testing.T) { 209 storage := Init(driver.NewMemory()) 210 211 const name = "angry-bird" 212 const vers = int32(4) 213 214 // setup storage with test releases 215 setup := func() { 216 // release records (notice odd order and corruption) 217 rls0 := ReleaseTestData{Name: name, Version: 1, Status: rspb.Status_SUPERSEDED}.ToRelease() 218 rls1 := ReleaseTestData{Name: name, Version: 4, Status: rspb.Status_DEPLOYED}.ToRelease() 219 rls2 := ReleaseTestData{Name: name, Version: 3, Status: rspb.Status_SUPERSEDED}.ToRelease() 220 rls3 := ReleaseTestData{Name: name, Version: 2, Status: rspb.Status_DEPLOYED}.ToRelease() 221 222 // create the release records in the storage 223 assertErrNil(t.Fatal, storage.Create(rls0), "Storing release 'angry-bird' (v1)") 224 assertErrNil(t.Fatal, storage.Create(rls1), "Storing release 'angry-bird' (v2)") 225 assertErrNil(t.Fatal, storage.Create(rls2), "Storing release 'angry-bird' (v3)") 226 assertErrNil(t.Fatal, storage.Create(rls3), "Storing release 'angry-bird' (v4)") 227 } 228 229 setup() 230 231 rls, err := storage.Deployed(name) 232 if err != nil { 233 t.Fatalf("Failed to query for deployed release: %s\n", err) 234 } 235 236 switch { 237 case rls == nil: 238 t.Fatalf("Release is nil") 239 case rls.Name != name: 240 t.Fatalf("Expected release name %q, actual %q\n", name, rls.Name) 241 case rls.Version != vers: 242 t.Fatalf("Expected release version %d, actual %d\n", vers, rls.Version) 243 case rls.Info.Status.Code != rspb.Status_DEPLOYED: 244 t.Fatalf("Expected release status 'DEPLOYED', actual %s\n", rls.Info.Status.Code) 245 } 246 } 247 248 func TestStorageHistory(t *testing.T) { 249 storage := Init(driver.NewMemory()) 250 251 const name = "angry-bird" 252 253 // setup storage with test releases 254 setup := func() { 255 // release records 256 rls0 := ReleaseTestData{Name: name, Version: 1, Status: rspb.Status_SUPERSEDED}.ToRelease() 257 rls1 := ReleaseTestData{Name: name, Version: 2, Status: rspb.Status_SUPERSEDED}.ToRelease() 258 rls2 := ReleaseTestData{Name: name, Version: 3, Status: rspb.Status_SUPERSEDED}.ToRelease() 259 rls3 := ReleaseTestData{Name: name, Version: 4, Status: rspb.Status_DEPLOYED}.ToRelease() 260 261 // create the release records in the storage 262 assertErrNil(t.Fatal, storage.Create(rls0), "Storing release 'angry-bird' (v1)") 263 assertErrNil(t.Fatal, storage.Create(rls1), "Storing release 'angry-bird' (v2)") 264 assertErrNil(t.Fatal, storage.Create(rls2), "Storing release 'angry-bird' (v3)") 265 assertErrNil(t.Fatal, storage.Create(rls3), "Storing release 'angry-bird' (v4)") 266 } 267 268 setup() 269 270 h, err := storage.History(name) 271 if err != nil { 272 t.Fatalf("Failed to query for release history (%q): %s\n", name, err) 273 } 274 if len(h) != 4 { 275 t.Fatalf("Release history (%q) is empty\n", name) 276 } 277 } 278 279 func TestStorageRemoveLeastRecent(t *testing.T) { 280 storage := Init(driver.NewMemory()) 281 storage.Log = t.Logf 282 283 // Make sure that specifying this at the outset doesn't cause any bugs. 284 storage.MaxHistory = 10 285 286 const name = "angry-bird" 287 288 // setup storage with test releases 289 setup := func() { 290 // release records 291 rls0 := ReleaseTestData{Name: name, Version: 1, Status: rspb.Status_SUPERSEDED}.ToRelease() 292 rls1 := ReleaseTestData{Name: name, Version: 2, Status: rspb.Status_SUPERSEDED}.ToRelease() 293 rls2 := ReleaseTestData{Name: name, Version: 3, Status: rspb.Status_SUPERSEDED}.ToRelease() 294 rls3 := ReleaseTestData{Name: name, Version: 4, Status: rspb.Status_DEPLOYED}.ToRelease() 295 296 // create the release records in the storage 297 assertErrNil(t.Fatal, storage.Create(rls0), "Storing release 'angry-bird' (v1)") 298 assertErrNil(t.Fatal, storage.Create(rls1), "Storing release 'angry-bird' (v2)") 299 assertErrNil(t.Fatal, storage.Create(rls2), "Storing release 'angry-bird' (v3)") 300 assertErrNil(t.Fatal, storage.Create(rls3), "Storing release 'angry-bird' (v4)") 301 } 302 setup() 303 304 // Because we have not set a limit, we expect 4. 305 expect := 4 306 if hist, err := storage.History(name); err != nil { 307 t.Fatal(err) 308 } else if len(hist) != expect { 309 t.Fatalf("expected %d items in history, got %d", expect, len(hist)) 310 } 311 312 storage.MaxHistory = 3 313 rls5 := ReleaseTestData{Name: name, Version: 5, Status: rspb.Status_DEPLOYED}.ToRelease() 314 assertErrNil(t.Fatal, storage.Create(rls5), "Storing release 'angry-bird' (v5)") 315 316 // On inserting the 5th record, we expect two records to be pruned from history. 317 hist, err := storage.History(name) 318 if err != nil { 319 t.Fatal(err) 320 } else if len(hist) != storage.MaxHistory { 321 for _, item := range hist { 322 t.Logf("%s %v", item.Name, item.Version) 323 } 324 t.Fatalf("expected %d items in history, got %d", storage.MaxHistory, len(hist)) 325 } 326 327 // We expect the existing records to be 3, 4, and 5. 328 for i, item := range hist { 329 v := int(item.Version) 330 if expect := i + 3; v != expect { 331 t.Errorf("Expected release %d, got %d", expect, v) 332 } 333 } 334 } 335 336 func TestStorageDontDeleteDeployed(t *testing.T) { 337 storage := Init(driver.NewMemory()) 338 storage.Log = t.Logf 339 storage.MaxHistory = 3 340 341 const name = "angry-bird" 342 343 // setup storage with test releases 344 setup := func() { 345 // release records 346 rls0 := ReleaseTestData{Name: name, Version: 1, Status: rspb.Status_SUPERSEDED}.ToRelease() 347 rls1 := ReleaseTestData{Name: name, Version: 2, Status: rspb.Status_DEPLOYED}.ToRelease() 348 rls2 := ReleaseTestData{Name: name, Version: 3, Status: rspb.Status_FAILED}.ToRelease() 349 rls3 := ReleaseTestData{Name: name, Version: 4, Status: rspb.Status_FAILED}.ToRelease() 350 351 // create the release records in the storage 352 assertErrNil(t.Fatal, storage.Create(rls0), "Storing release 'angry-bird' (v1)") 353 assertErrNil(t.Fatal, storage.Create(rls1), "Storing release 'angry-bird' (v2)") 354 assertErrNil(t.Fatal, storage.Create(rls2), "Storing release 'angry-bird' (v3)") 355 assertErrNil(t.Fatal, storage.Create(rls3), "Storing release 'angry-bird' (v4)") 356 } 357 setup() 358 359 rls5 := ReleaseTestData{Name: name, Version: 5, Status: rspb.Status_FAILED}.ToRelease() 360 assertErrNil(t.Fatal, storage.Create(rls5), "Storing release 'angry-bird' (v5)") 361 362 // On inserting the 5th record, we expect a total of 3 releases, but we expect version 2 363 // (the only deployed release), to still exist 364 hist, err := storage.History(name) 365 if err != nil { 366 t.Fatal(err) 367 } else if len(hist) != storage.MaxHistory { 368 for _, item := range hist { 369 t.Logf("%s %v", item.Name, item.Version) 370 } 371 t.Fatalf("expected %d items in history, got %d", storage.MaxHistory, len(hist)) 372 } 373 374 expectedVersions := map[int32]bool{ 375 2: true, 376 4: true, 377 5: true, 378 } 379 380 for _, item := range hist { 381 if !expectedVersions[item.GetVersion()] { 382 t.Errorf("Release version %d, found when not expected", item.GetVersion()) 383 } 384 } 385 } 386 387 func TestStorageLast(t *testing.T) { 388 storage := Init(driver.NewMemory()) 389 390 const name = "angry-bird" 391 392 // Set up storage with test releases. 393 setup := func() { 394 // release records 395 rls0 := ReleaseTestData{Name: name, Version: 1, Status: rspb.Status_SUPERSEDED}.ToRelease() 396 rls1 := ReleaseTestData{Name: name, Version: 2, Status: rspb.Status_SUPERSEDED}.ToRelease() 397 rls2 := ReleaseTestData{Name: name, Version: 3, Status: rspb.Status_SUPERSEDED}.ToRelease() 398 rls3 := ReleaseTestData{Name: name, Version: 4, Status: rspb.Status_FAILED}.ToRelease() 399 400 // create the release records in the storage 401 assertErrNil(t.Fatal, storage.Create(rls0), "Storing release 'angry-bird' (v1)") 402 assertErrNil(t.Fatal, storage.Create(rls1), "Storing release 'angry-bird' (v2)") 403 assertErrNil(t.Fatal, storage.Create(rls2), "Storing release 'angry-bird' (v3)") 404 assertErrNil(t.Fatal, storage.Create(rls3), "Storing release 'angry-bird' (v4)") 405 } 406 407 setup() 408 409 h, err := storage.Last(name) 410 if err != nil { 411 t.Fatalf("Failed to query for release history (%q): %s\n", name, err) 412 } 413 414 if h.Version != 4 { 415 t.Errorf("Expected revision 4, got %d", h.Version) 416 } 417 } 418 419 type ReleaseTestData struct { 420 Name string 421 Version int32 422 Manifest string 423 Namespace string 424 Status rspb.Status_Code 425 } 426 427 func (test ReleaseTestData) ToRelease() *rspb.Release { 428 return &rspb.Release{ 429 Name: test.Name, 430 Version: test.Version, 431 Manifest: test.Manifest, 432 Namespace: test.Namespace, 433 Info: &rspb.Info{Status: &rspb.Status{Code: test.Status}}, 434 } 435 } 436 437 func assertErrNil(eh func(args ...interface{}), err error, message string) { 438 if err != nil { 439 eh(fmt.Sprintf("%s: %q", message, err)) 440 } 441 }