k8s.io/kubernetes@v1.29.3/pkg/registry/core/namespace/storage/storage_test.go (about) 1 /* 2 Copyright 2015 The Kubernetes 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 18 19 import ( 20 "testing" 21 22 apierrors "k8s.io/apimachinery/pkg/api/errors" 23 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 24 "k8s.io/apimachinery/pkg/fields" 25 "k8s.io/apimachinery/pkg/labels" 26 "k8s.io/apimachinery/pkg/runtime" 27 genericapirequest "k8s.io/apiserver/pkg/endpoints/request" 28 "k8s.io/apiserver/pkg/registry/generic" 29 genericregistrytest "k8s.io/apiserver/pkg/registry/generic/testing" 30 "k8s.io/apiserver/pkg/registry/rest" 31 etcd3testing "k8s.io/apiserver/pkg/storage/etcd3/testing" 32 33 api "k8s.io/kubernetes/pkg/apis/core" 34 "k8s.io/kubernetes/pkg/registry/registrytest" 35 ) 36 37 func newStorage(t *testing.T) (*REST, *etcd3testing.EtcdTestServer) { 38 etcdStorage, server := registrytest.NewEtcdStorage(t, "") 39 restOptions := generic.RESTOptions{StorageConfig: etcdStorage, Decorator: generic.UndecoratedStorage, DeleteCollectionWorkers: 1, ResourcePrefix: "namespaces"} 40 namespaceStorage, _, _, err := NewREST(restOptions) 41 if err != nil { 42 t.Fatalf("unexpected error from REST storage: %v", err) 43 } 44 return namespaceStorage, server 45 } 46 47 func validNewNamespace() *api.Namespace { 48 return &api.Namespace{ 49 ObjectMeta: metav1.ObjectMeta{ 50 Name: "foo", 51 }, 52 } 53 } 54 55 func TestCreate(t *testing.T) { 56 storage, server := newStorage(t) 57 defer server.Terminate(t) 58 defer storage.store.DestroyFunc() 59 test := genericregistrytest.New(t, storage.store).ClusterScope() 60 namespace := validNewNamespace() 61 namespace.ObjectMeta = metav1.ObjectMeta{GenerateName: "foo"} 62 test.TestCreate( 63 // valid 64 namespace, 65 // invalid 66 &api.Namespace{ 67 ObjectMeta: metav1.ObjectMeta{Name: "bad value"}, 68 }, 69 ) 70 } 71 72 func TestCreateSetsFields(t *testing.T) { 73 storage, server := newStorage(t) 74 defer server.Terminate(t) 75 defer storage.store.DestroyFunc() 76 namespace := validNewNamespace() 77 ctx := genericapirequest.WithNamespace(genericapirequest.NewContext(), metav1.NamespaceNone) 78 _, err := storage.Create(ctx, namespace, rest.ValidateAllObjectFunc, &metav1.CreateOptions{}) 79 if err != nil { 80 t.Fatalf("unexpected error: %v", err) 81 } 82 83 object, err := storage.Get(ctx, "foo", &metav1.GetOptions{}) 84 if err != nil { 85 t.Errorf("unexpected error: %v", err) 86 } 87 actual := object.(*api.Namespace) 88 if actual.Name != namespace.Name { 89 t.Errorf("unexpected namespace: %#v", actual) 90 } 91 if len(actual.UID) == 0 { 92 t.Errorf("expected namespace UID to be set: %#v", actual) 93 } 94 if actual.Status.Phase != api.NamespaceActive { 95 t.Errorf("expected namespace phase to be set to active, but %v", actual.Status.Phase) 96 } 97 } 98 99 func TestDelete(t *testing.T) { 100 storage, server := newStorage(t) 101 defer server.Terminate(t) 102 defer storage.store.DestroyFunc() 103 test := genericregistrytest.New(t, storage.store).ClusterScope().ReturnDeletedObject() 104 test.TestDelete(validNewNamespace()) 105 } 106 107 func TestGet(t *testing.T) { 108 storage, server := newStorage(t) 109 defer server.Terminate(t) 110 defer storage.store.DestroyFunc() 111 test := genericregistrytest.New(t, storage.store).ClusterScope() 112 113 // note that this ultimately may call validation 114 test.TestGet(validNewNamespace()) 115 } 116 117 func TestList(t *testing.T) { 118 storage, server := newStorage(t) 119 defer server.Terminate(t) 120 defer storage.store.DestroyFunc() 121 test := genericregistrytest.New(t, storage.store).ClusterScope() 122 test.TestList(validNewNamespace()) 123 } 124 125 func TestWatch(t *testing.T) { 126 storage, server := newStorage(t) 127 defer server.Terminate(t) 128 defer storage.store.DestroyFunc() 129 test := genericregistrytest.New(t, storage.store).ClusterScope() 130 test.TestWatch( 131 validNewNamespace(), 132 // matching labels 133 []labels.Set{}, 134 // not matching labels 135 []labels.Set{ 136 {"foo": "bar"}, 137 }, 138 // matching fields 139 []fields.Set{ 140 {"metadata.name": "foo"}, 141 {"name": "foo"}, 142 }, 143 // not matching fields 144 []fields.Set{ 145 {"metadata.name": "bar"}, 146 }, 147 ) 148 } 149 150 func TestDeleteNamespaceWithIncompleteFinalizers(t *testing.T) { 151 storage, server := newStorage(t) 152 defer server.Terminate(t) 153 defer storage.store.DestroyFunc() 154 key := "namespaces/foo" 155 ctx := genericapirequest.WithNamespace(genericapirequest.NewContext(), metav1.NamespaceNone) 156 now := metav1.Now() 157 namespace := &api.Namespace{ 158 ObjectMeta: metav1.ObjectMeta{ 159 Name: "foo", 160 DeletionTimestamp: &now, 161 }, 162 Spec: api.NamespaceSpec{ 163 Finalizers: []api.FinalizerName{api.FinalizerKubernetes}, 164 }, 165 Status: api.NamespaceStatus{Phase: api.NamespaceActive}, 166 } 167 if err := storage.store.Storage.Create(ctx, key, namespace, nil, 0, false); err != nil { 168 t.Fatalf("unexpected error: %v", err) 169 } 170 ctx = genericapirequest.WithNamespace(genericapirequest.NewContext(), namespace.Name) 171 obj, immediate, err := storage.Delete(ctx, "foo", rest.ValidateAllObjectFunc, nil) 172 if err != nil { 173 t.Fatalf("unexpected error") 174 } 175 if immediate { 176 t.Fatalf("unexpected immediate flag") 177 } 178 if ns, ok := obj.(*api.Namespace); !ok || obj == nil || ns == nil || ns.Name != namespace.Name { 179 t.Fatalf("object not returned by delete") 180 } 181 // should still exist 182 if _, err := storage.Get(ctx, "foo", &metav1.GetOptions{}); err != nil { 183 t.Errorf("unexpected error: %v", err) 184 } 185 } 186 187 func TestUpdateDeletingNamespaceWithIncompleteMetadataFinalizers(t *testing.T) { 188 storage, server := newStorage(t) 189 defer server.Terminate(t) 190 defer storage.store.DestroyFunc() 191 key := "namespaces/foo" 192 ctx := genericapirequest.WithNamespace(genericapirequest.NewContext(), metav1.NamespaceNone) 193 now := metav1.Now() 194 namespace := &api.Namespace{ 195 ObjectMeta: metav1.ObjectMeta{ 196 Name: "foo", 197 DeletionTimestamp: &now, 198 Finalizers: []string{"example.com/foo"}, 199 }, 200 Spec: api.NamespaceSpec{ 201 Finalizers: []api.FinalizerName{}, 202 }, 203 Status: api.NamespaceStatus{Phase: api.NamespaceActive}, 204 } 205 if err := storage.store.Storage.Create(ctx, key, namespace, nil, 0, false); err != nil { 206 t.Fatalf("unexpected error: %v", err) 207 } 208 ctx = genericapirequest.WithNamespace(genericapirequest.NewContext(), namespace.Name) 209 ns, err := storage.Get(ctx, "foo", &metav1.GetOptions{}) 210 if err != nil { 211 t.Fatalf("unexpected error: %v", err) 212 } 213 if _, _, err = storage.Update(ctx, "foo", rest.DefaultUpdatedObjectInfo(ns), rest.ValidateAllObjectFunc, rest.ValidateAllObjectUpdateFunc, false, &metav1.UpdateOptions{}); err != nil { 214 t.Fatalf("unexpected error: %v", err) 215 } 216 // should still exist 217 _, err = storage.Get(ctx, "foo", &metav1.GetOptions{}) 218 if err != nil { 219 t.Fatalf("unexpected error: %v", err) 220 } 221 } 222 223 func TestUpdateDeletingNamespaceWithIncompleteSpecFinalizers(t *testing.T) { 224 storage, server := newStorage(t) 225 defer server.Terminate(t) 226 defer storage.store.DestroyFunc() 227 key := "namespaces/foo" 228 ctx := genericapirequest.WithNamespace(genericapirequest.NewContext(), metav1.NamespaceNone) 229 now := metav1.Now() 230 namespace := &api.Namespace{ 231 ObjectMeta: metav1.ObjectMeta{ 232 Name: "foo", 233 DeletionTimestamp: &now, 234 }, 235 Spec: api.NamespaceSpec{ 236 Finalizers: []api.FinalizerName{api.FinalizerKubernetes}, 237 }, 238 Status: api.NamespaceStatus{Phase: api.NamespaceActive}, 239 } 240 if err := storage.store.Storage.Create(ctx, key, namespace, nil, 0, false); err != nil { 241 t.Fatalf("unexpected error: %v", err) 242 } 243 ns, err := storage.Get(ctx, "foo", &metav1.GetOptions{}) 244 if err != nil { 245 t.Fatalf("unexpected error: %v", err) 246 } 247 ctx = genericapirequest.WithNamespace(genericapirequest.NewContext(), namespace.Name) 248 if _, _, err = storage.Update(ctx, "foo", rest.DefaultUpdatedObjectInfo(ns), rest.ValidateAllObjectFunc, rest.ValidateAllObjectUpdateFunc, false, &metav1.UpdateOptions{}); err != nil { 249 t.Fatalf("unexpected error: %v", err) 250 } 251 // should still exist 252 _, err = storage.Get(ctx, "foo", &metav1.GetOptions{}) 253 if err != nil { 254 t.Fatalf("unexpected error: %v", err) 255 } 256 } 257 258 func TestUpdateDeletingNamespaceWithCompleteFinalizers(t *testing.T) { 259 storage, server := newStorage(t) 260 defer server.Terminate(t) 261 defer storage.store.DestroyFunc() 262 key := "namespaces/foo" 263 ctx := genericapirequest.WithNamespace(genericapirequest.NewContext(), metav1.NamespaceNone) 264 now := metav1.Now() 265 namespace := &api.Namespace{ 266 ObjectMeta: metav1.ObjectMeta{ 267 Name: "foo", 268 DeletionTimestamp: &now, 269 Finalizers: []string{"example.com/foo"}, 270 }, 271 Status: api.NamespaceStatus{Phase: api.NamespaceActive}, 272 } 273 if err := storage.store.Storage.Create(ctx, key, namespace, nil, 0, false); err != nil { 274 t.Fatalf("unexpected error: %v", err) 275 } 276 ns, err := storage.Get(ctx, "foo", &metav1.GetOptions{}) 277 if err != nil { 278 t.Fatalf("unexpected error: %v", err) 279 } 280 ns.(*api.Namespace).Finalizers = nil 281 ctx = genericapirequest.WithNamespace(genericapirequest.NewContext(), namespace.Name) 282 if _, _, err = storage.Update(ctx, "foo", rest.DefaultUpdatedObjectInfo(ns), rest.ValidateAllObjectFunc, rest.ValidateAllObjectUpdateFunc, false, &metav1.UpdateOptions{}); err != nil { 283 t.Fatalf("unexpected error: %v", err) 284 } 285 // should not exist 286 _, err = storage.Get(ctx, "foo", &metav1.GetOptions{}) 287 if !apierrors.IsNotFound(err) { 288 t.Errorf("expected NotFound, got %v", err) 289 } 290 } 291 292 func TestFinalizeDeletingNamespaceWithCompleteFinalizers(t *testing.T) { 293 // get finalize storage 294 etcdStorage, server := registrytest.NewEtcdStorage(t, "") 295 restOptions := generic.RESTOptions{StorageConfig: etcdStorage, Decorator: generic.UndecoratedStorage, DeleteCollectionWorkers: 1, ResourcePrefix: "namespaces"} 296 storage, _, finalizeStorage, err := NewREST(restOptions) 297 if err != nil { 298 t.Fatalf("unexpected error from REST storage: %v", err) 299 } 300 301 defer server.Terminate(t) 302 defer storage.store.DestroyFunc() 303 defer finalizeStorage.store.DestroyFunc() 304 key := "namespaces/foo" 305 ctx := genericapirequest.WithNamespace(genericapirequest.NewContext(), metav1.NamespaceNone) 306 now := metav1.Now() 307 namespace := &api.Namespace{ 308 ObjectMeta: metav1.ObjectMeta{ 309 Name: "foo", 310 DeletionTimestamp: &now, 311 }, 312 Spec: api.NamespaceSpec{ 313 Finalizers: []api.FinalizerName{api.FinalizerKubernetes}, 314 }, 315 Status: api.NamespaceStatus{Phase: api.NamespaceActive}, 316 } 317 if err := storage.store.Storage.Create(ctx, key, namespace, nil, 0, false); err != nil { 318 t.Fatalf("unexpected error: %v", err) 319 } 320 ns, err := storage.Get(ctx, "foo", &metav1.GetOptions{}) 321 if err != nil { 322 t.Fatalf("unexpected error: %v", err) 323 } 324 ns.(*api.Namespace).Spec.Finalizers = nil 325 ctx = genericapirequest.WithNamespace(genericapirequest.NewContext(), namespace.Name) 326 if _, _, err = finalizeStorage.Update(ctx, "foo", rest.DefaultUpdatedObjectInfo(ns), rest.ValidateAllObjectFunc, rest.ValidateAllObjectUpdateFunc, false, &metav1.UpdateOptions{}); err != nil { 327 t.Fatalf("unexpected error: %v", err) 328 } 329 // should not exist 330 _, err = storage.Get(ctx, "foo", &metav1.GetOptions{}) 331 if !apierrors.IsNotFound(err) { 332 t.Errorf("expected NotFound, got %v", err) 333 } 334 } 335 336 func TestFinalizeDeletingNamespaceWithIncompleteMetadataFinalizers(t *testing.T) { 337 // get finalize storage 338 etcdStorage, server := registrytest.NewEtcdStorage(t, "") 339 restOptions := generic.RESTOptions{StorageConfig: etcdStorage, Decorator: generic.UndecoratedStorage, DeleteCollectionWorkers: 1, ResourcePrefix: "namespaces"} 340 storage, _, finalizeStorage, err := NewREST(restOptions) 341 if err != nil { 342 t.Fatalf("unexpected error from REST storage: %v", err) 343 } 344 345 defer server.Terminate(t) 346 defer storage.store.DestroyFunc() 347 defer finalizeStorage.store.DestroyFunc() 348 key := "namespaces/foo" 349 ctx := genericapirequest.WithNamespace(genericapirequest.NewContext(), metav1.NamespaceNone) 350 now := metav1.Now() 351 namespace := &api.Namespace{ 352 ObjectMeta: metav1.ObjectMeta{ 353 Name: "foo", 354 DeletionTimestamp: &now, 355 Finalizers: []string{"example.com/foo"}, 356 }, 357 Spec: api.NamespaceSpec{ 358 Finalizers: []api.FinalizerName{api.FinalizerKubernetes}, 359 }, 360 Status: api.NamespaceStatus{Phase: api.NamespaceActive}, 361 } 362 if err := storage.store.Storage.Create(ctx, key, namespace, nil, 0, false); err != nil { 363 t.Fatalf("unexpected error: %v", err) 364 } 365 ns, err := storage.Get(ctx, "foo", &metav1.GetOptions{}) 366 if err != nil { 367 t.Fatalf("unexpected error: %v", err) 368 } 369 ns.(*api.Namespace).Spec.Finalizers = nil 370 ctx = genericapirequest.WithNamespace(genericapirequest.NewContext(), namespace.Name) 371 if _, _, err = finalizeStorage.Update(ctx, "foo", rest.DefaultUpdatedObjectInfo(ns), rest.ValidateAllObjectFunc, rest.ValidateAllObjectUpdateFunc, false, &metav1.UpdateOptions{}); err != nil { 372 t.Fatalf("unexpected error: %v", err) 373 } 374 // should still exist 375 _, err = storage.Get(ctx, "foo", &metav1.GetOptions{}) 376 if err != nil { 377 t.Fatalf("unexpected error: %v", err) 378 } 379 } 380 381 func TestDeleteNamespaceWithCompleteFinalizers(t *testing.T) { 382 storage, server := newStorage(t) 383 defer server.Terminate(t) 384 defer storage.store.DestroyFunc() 385 key := "namespaces/foo" 386 ctx := genericapirequest.WithNamespace(genericapirequest.NewContext(), metav1.NamespaceNone) 387 now := metav1.Now() 388 namespace := &api.Namespace{ 389 ObjectMeta: metav1.ObjectMeta{ 390 Name: "foo", 391 DeletionTimestamp: &now, 392 }, 393 Spec: api.NamespaceSpec{ 394 Finalizers: []api.FinalizerName{}, 395 }, 396 Status: api.NamespaceStatus{Phase: api.NamespaceActive}, 397 } 398 if err := storage.store.Storage.Create(ctx, key, namespace, nil, 0, false); err != nil { 399 t.Fatalf("unexpected error: %v", err) 400 } 401 ctx = genericapirequest.WithNamespace(genericapirequest.NewContext(), namespace.Name) 402 if _, _, err := storage.Delete(ctx, "foo", rest.ValidateAllObjectFunc, nil); err != nil { 403 t.Errorf("unexpected error: %v", err) 404 } 405 // should not exist 406 _, err := storage.Get(ctx, "foo", &metav1.GetOptions{}) 407 if !apierrors.IsNotFound(err) { 408 t.Errorf("expected NotFound, got %v", err) 409 } 410 } 411 412 func TestDeleteWithGCFinalizers(t *testing.T) { 413 storage, server := newStorage(t) 414 defer server.Terminate(t) 415 defer storage.store.DestroyFunc() 416 417 propagationBackground := metav1.DeletePropagationBackground 418 propagationForeground := metav1.DeletePropagationForeground 419 propagationOrphan := metav1.DeletePropagationOrphan 420 trueVar := true 421 422 var tests = []struct { 423 name string 424 deleteOptions *metav1.DeleteOptions 425 426 existingFinalizers []string 427 remainingFinalizers map[string]bool 428 }{ 429 { 430 name: "nil-with-orphan", 431 deleteOptions: nil, 432 existingFinalizers: []string{ 433 metav1.FinalizerOrphanDependents, 434 }, 435 remainingFinalizers: map[string]bool{ 436 metav1.FinalizerOrphanDependents: true, 437 }, 438 }, 439 { 440 name: "nil-with-delete", 441 deleteOptions: nil, 442 existingFinalizers: []string{ 443 metav1.FinalizerDeleteDependents, 444 }, 445 remainingFinalizers: map[string]bool{ 446 metav1.FinalizerDeleteDependents: true, 447 }, 448 }, 449 { 450 name: "nil-without-finalizers", 451 deleteOptions: nil, 452 existingFinalizers: []string{}, 453 remainingFinalizers: map[string]bool{}, 454 }, 455 { 456 name: "propagation-background-with-orphan", 457 deleteOptions: &metav1.DeleteOptions{ 458 PropagationPolicy: &propagationBackground, 459 }, 460 existingFinalizers: []string{ 461 metav1.FinalizerOrphanDependents, 462 }, 463 remainingFinalizers: map[string]bool{}, 464 }, 465 { 466 name: "propagation-background-with-delete", 467 deleteOptions: &metav1.DeleteOptions{ 468 PropagationPolicy: &propagationBackground, 469 }, 470 existingFinalizers: []string{ 471 metav1.FinalizerDeleteDependents, 472 }, 473 remainingFinalizers: map[string]bool{}, 474 }, 475 { 476 name: "propagation-background-without-finalizers", 477 deleteOptions: &metav1.DeleteOptions{ 478 PropagationPolicy: &propagationBackground, 479 }, 480 existingFinalizers: []string{}, 481 remainingFinalizers: map[string]bool{}, 482 }, 483 { 484 name: "propagation-foreground-with-orphan", 485 deleteOptions: &metav1.DeleteOptions{ 486 PropagationPolicy: &propagationForeground, 487 }, 488 existingFinalizers: []string{ 489 metav1.FinalizerOrphanDependents, 490 }, 491 remainingFinalizers: map[string]bool{ 492 metav1.FinalizerDeleteDependents: true, 493 }, 494 }, 495 { 496 name: "propagation-foreground-with-delete", 497 deleteOptions: &metav1.DeleteOptions{ 498 PropagationPolicy: &propagationForeground, 499 }, 500 existingFinalizers: []string{ 501 metav1.FinalizerDeleteDependents, 502 }, 503 remainingFinalizers: map[string]bool{ 504 metav1.FinalizerDeleteDependents: true, 505 }, 506 }, 507 { 508 name: "propagation-foreground-without-finalizers", 509 deleteOptions: &metav1.DeleteOptions{ 510 PropagationPolicy: &propagationForeground, 511 }, 512 existingFinalizers: []string{}, 513 remainingFinalizers: map[string]bool{ 514 metav1.FinalizerDeleteDependents: true, 515 }, 516 }, 517 { 518 name: "propagation-orphan-with-orphan", 519 deleteOptions: &metav1.DeleteOptions{ 520 PropagationPolicy: &propagationOrphan, 521 }, 522 existingFinalizers: []string{ 523 metav1.FinalizerOrphanDependents, 524 }, 525 remainingFinalizers: map[string]bool{ 526 metav1.FinalizerOrphanDependents: true, 527 }, 528 }, 529 { 530 name: "propagation-orphan-with-delete", 531 deleteOptions: &metav1.DeleteOptions{ 532 PropagationPolicy: &propagationOrphan, 533 }, 534 existingFinalizers: []string{ 535 metav1.FinalizerDeleteDependents, 536 }, 537 remainingFinalizers: map[string]bool{ 538 metav1.FinalizerOrphanDependents: true, 539 }, 540 }, 541 { 542 name: "propagation-orphan-without-finalizers", 543 deleteOptions: &metav1.DeleteOptions{ 544 PropagationPolicy: &propagationOrphan, 545 }, 546 existingFinalizers: []string{}, 547 remainingFinalizers: map[string]bool{ 548 metav1.FinalizerOrphanDependents: true, 549 }, 550 }, 551 { 552 name: "orphan-dependents-with-orphan", 553 deleteOptions: &metav1.DeleteOptions{ 554 OrphanDependents: &trueVar, 555 }, 556 existingFinalizers: []string{ 557 metav1.FinalizerOrphanDependents, 558 }, 559 remainingFinalizers: map[string]bool{ 560 metav1.FinalizerOrphanDependents: true, 561 }, 562 }, 563 { 564 name: "orphan-dependents-with-delete", 565 deleteOptions: &metav1.DeleteOptions{ 566 OrphanDependents: &trueVar, 567 }, 568 existingFinalizers: []string{ 569 metav1.FinalizerDeleteDependents, 570 }, 571 remainingFinalizers: map[string]bool{ 572 metav1.FinalizerOrphanDependents: true, 573 }, 574 }, 575 { 576 name: "orphan-dependents-without-finalizers", 577 deleteOptions: &metav1.DeleteOptions{ 578 OrphanDependents: &trueVar, 579 }, 580 existingFinalizers: []string{}, 581 remainingFinalizers: map[string]bool{ 582 metav1.FinalizerOrphanDependents: true, 583 }, 584 }, 585 } 586 587 for _, test := range tests { 588 key := "namespaces/" + test.name 589 ctx := genericapirequest.WithNamespace(genericapirequest.NewContext(), metav1.NamespaceNone) 590 namespace := &api.Namespace{ 591 ObjectMeta: metav1.ObjectMeta{ 592 Name: test.name, 593 Finalizers: test.existingFinalizers, 594 }, 595 Spec: api.NamespaceSpec{ 596 Finalizers: []api.FinalizerName{}, 597 }, 598 Status: api.NamespaceStatus{Phase: api.NamespaceActive}, 599 } 600 if err := storage.store.Storage.Create(ctx, key, namespace, nil, 0, false); err != nil { 601 t.Fatalf("unexpected error: %v", err) 602 } 603 var obj runtime.Object 604 var err error 605 ctx = genericapirequest.WithNamespace(genericapirequest.NewContext(), namespace.Name) 606 if obj, _, err = storage.Delete(ctx, test.name, rest.ValidateAllObjectFunc, test.deleteOptions); err != nil { 607 t.Fatalf("unexpected error: %v", err) 608 } 609 ns, ok := obj.(*api.Namespace) 610 if !ok { 611 t.Errorf("unexpected object kind: %+v", obj) 612 } 613 if len(ns.Finalizers) != len(test.remainingFinalizers) { 614 t.Errorf("%s: unexpected remaining finalizers: %v", test.name, ns.Finalizers) 615 } 616 for _, f := range ns.Finalizers { 617 if test.remainingFinalizers[f] != true { 618 t.Errorf("%s: unexpected finalizer %s", test.name, f) 619 } 620 } 621 } 622 } 623 624 func TestShortNames(t *testing.T) { 625 storage, server := newStorage(t) 626 defer server.Terminate(t) 627 defer storage.store.DestroyFunc() 628 expected := []string{"ns"} 629 registrytest.AssertShortNames(t, storage, expected) 630 }