Skip to content

Commit da24601

Browse files
committed
test(cr::update): add corresponding tests
Signed-off-by: knight42 <[email protected]>
1 parent 34de08a commit da24601

File tree

1 file changed

+180
-0
lines changed
  • staging/src/k8s.io/apiextensions-apiserver/pkg/registry/customresource

1 file changed

+180
-0
lines changed

staging/src/k8s.io/apiextensions-apiserver/pkg/registry/customresource/etcd_test.go

Lines changed: 180 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ limitations under the License.
1717
package customresource_test
1818

1919
import (
20+
"context"
21+
"fmt"
2022
"reflect"
2123
"strings"
2224
"testing"
@@ -526,6 +528,184 @@ func TestScaleUpdateWithoutSpecReplicas(t *testing.T) {
526528
}
527529
}
528530

531+
func TestScaleUpdateWithoutResourceVersion(t *testing.T) {
532+
storage, server := newStorage(t)
533+
defer server.Terminate(t)
534+
defer storage.CustomResource.Store.DestroyFunc()
535+
536+
name := "foo"
537+
538+
var cr unstructured.Unstructured
539+
ctx := genericapirequest.WithNamespace(genericapirequest.NewContext(), metav1.NamespaceDefault)
540+
key := "/noxus/" + metav1.NamespaceDefault + "/" + name
541+
if err := storage.CustomResource.Storage.Create(ctx, key, &validCustomResource, &cr, 0, false); err != nil {
542+
t.Fatalf("error setting new custom resource (key: %s) %v: %v", key, validCustomResource, err)
543+
}
544+
545+
replicas := int32(8)
546+
update := autoscalingv1.Scale{
547+
ObjectMeta: metav1.ObjectMeta{
548+
Name: name,
549+
},
550+
Spec: autoscalingv1.ScaleSpec{
551+
Replicas: replicas,
552+
},
553+
}
554+
555+
if _, _, err := storage.Scale.Update(ctx, update.Name, rest.DefaultUpdatedObjectInfo(&update), rest.ValidateAllObjectFunc, rest.ValidateAllObjectUpdateFunc, false, &metav1.UpdateOptions{}); err != nil {
556+
t.Fatalf("error updating scale %v: %v", update, err)
557+
}
558+
559+
obj, err := storage.Scale.Get(ctx, name, &metav1.GetOptions{})
560+
if err != nil {
561+
t.Fatalf("error fetching scale for %s: %v", name, err)
562+
}
563+
scale := obj.(*autoscalingv1.Scale)
564+
if scale.Spec.Replicas != replicas {
565+
t.Errorf("wrong replicas count: expected: %d got: %d", replicas, scale.Spec.Replicas)
566+
}
567+
}
568+
569+
func TestScaleUpdateWithoutResourceVersionWithConflicts(t *testing.T) {
570+
storage, server := newStorage(t)
571+
defer server.Terminate(t)
572+
defer storage.CustomResource.Store.DestroyFunc()
573+
574+
name := "foo"
575+
576+
var cr unstructured.Unstructured
577+
ctx := genericapirequest.WithNamespace(genericapirequest.NewContext(), metav1.NamespaceDefault)
578+
key := "/noxus/" + metav1.NamespaceDefault + "/" + name
579+
if err := storage.CustomResource.Storage.Create(ctx, key, &validCustomResource, &cr, 0, false); err != nil {
580+
t.Fatalf("error setting new custom resource (key: %s) %v: %v", key, validCustomResource, err)
581+
}
582+
583+
fetchObject := func(name string) (*unstructured.Unstructured, error) {
584+
gotObj, err := storage.CustomResource.Get(ctx, name, &metav1.GetOptions{})
585+
if err != nil {
586+
return nil, fmt.Errorf("error fetching custom resource %s: %v", name, err)
587+
}
588+
return gotObj.(*unstructured.Unstructured), nil
589+
}
590+
591+
applyPatch := func(labelName, labelValue string) rest.TransformFunc {
592+
return func(_ context.Context, _, currentObject runtime.Object) (objToUpdate runtime.Object, patchErr error) {
593+
o := currentObject.(metav1.Object)
594+
o.SetLabels(map[string]string{
595+
labelName: labelValue,
596+
})
597+
return currentObject, nil
598+
}
599+
}
600+
601+
errs := make(chan error, 1)
602+
rounds := 100
603+
go func() {
604+
// continuously submits a patch that updates a label and verifies the label update was effective
605+
labelName := "timestamp"
606+
for i := 0; i < rounds; i++ {
607+
expectedLabelValue := fmt.Sprint(i)
608+
update, err := fetchObject(name)
609+
if err != nil {
610+
errs <- err
611+
return
612+
}
613+
setNestedField(update, expectedLabelValue, "metadata", "labels", labelName)
614+
if _, _, err := storage.CustomResource.Update(ctx, name, rest.DefaultUpdatedObjectInfo(nil, applyPatch(labelName, fmt.Sprint(i))), rest.ValidateAllObjectFunc, rest.ValidateAllObjectUpdateFunc, false, &metav1.UpdateOptions{}); err != nil {
615+
616+
errs <- fmt.Errorf("error updating custom resource label: %v", err)
617+
return
618+
}
619+
620+
gotObj, err := fetchObject(name)
621+
if err != nil {
622+
errs <- err
623+
return
624+
}
625+
gotLabelValue, _, err := unstructured.NestedString(gotObj.Object, "metadata", "labels", labelName)
626+
if err != nil {
627+
errs <- fmt.Errorf("error getting label %s of custom resource %s: %v", labelName, name, err)
628+
return
629+
}
630+
if gotLabelValue != expectedLabelValue {
631+
errs <- fmt.Errorf("wrong label value: expected: %s, got: %s", expectedLabelValue, gotLabelValue)
632+
return
633+
}
634+
}
635+
}()
636+
637+
replicas := int32(0)
638+
update := autoscalingv1.Scale{
639+
ObjectMeta: metav1.ObjectMeta{
640+
Name: name,
641+
},
642+
}
643+
// continuously submits a scale update without a resourceVersion for a monotonically increasing replica value
644+
// and verifies the scale update was effective
645+
for i := 0; i < rounds; i++ {
646+
select {
647+
case err := <-errs:
648+
t.Fatal(err)
649+
default:
650+
replicas++
651+
update.Spec.Replicas = replicas
652+
if _, _, err := storage.Scale.Update(ctx, update.Name, rest.DefaultUpdatedObjectInfo(&update), rest.ValidateAllObjectFunc, rest.ValidateAllObjectUpdateFunc, false, &metav1.UpdateOptions{}); err != nil {
653+
t.Fatalf("error updating scale %v: %v", update, err)
654+
}
655+
656+
obj, err := storage.Scale.Get(ctx, name, &metav1.GetOptions{})
657+
if err != nil {
658+
t.Fatalf("error fetching scale for %s: %v", name, err)
659+
}
660+
scale := obj.(*autoscalingv1.Scale)
661+
if scale.Spec.Replicas != replicas {
662+
t.Errorf("wrong replicas count: expected: %d got: %d", replicas, scale.Spec.Replicas)
663+
}
664+
}
665+
}
666+
}
667+
668+
func TestScaleUpdateWithResourceVersionWithConflicts(t *testing.T) {
669+
storage, server := newStorage(t)
670+
defer server.Terminate(t)
671+
defer storage.CustomResource.Store.DestroyFunc()
672+
673+
name := "foo"
674+
675+
var cr unstructured.Unstructured
676+
ctx := genericapirequest.WithNamespace(genericapirequest.NewContext(), metav1.NamespaceDefault)
677+
key := "/noxus/" + metav1.NamespaceDefault + "/" + name
678+
if err := storage.CustomResource.Storage.Create(ctx, key, &validCustomResource, &cr, 0, false); err != nil {
679+
t.Fatalf("error setting new custom resource (key: %s) %v: %v", key, validCustomResource, err)
680+
}
681+
682+
obj, err := storage.Scale.Get(ctx, name, &metav1.GetOptions{})
683+
if err != nil {
684+
t.Fatalf("error fetching scale for %s: %v", name, err)
685+
}
686+
scale, ok := obj.(*autoscalingv1.Scale)
687+
if !ok {
688+
t.Fatalf("%v is not of the type autoscalingv1.Scale", scale)
689+
}
690+
691+
replicas := int32(12)
692+
update := autoscalingv1.Scale{
693+
ObjectMeta: scale.ObjectMeta,
694+
Spec: autoscalingv1.ScaleSpec{
695+
Replicas: replicas,
696+
},
697+
}
698+
update.ResourceVersion = "1"
699+
700+
_, _, err = storage.Scale.Update(ctx, update.Name, rest.DefaultUpdatedObjectInfo(&update), rest.ValidateAllObjectFunc, rest.ValidateAllObjectUpdateFunc, false, &metav1.UpdateOptions{})
701+
if err == nil {
702+
t.Fatal("expecting an update conflict error")
703+
}
704+
if !errors.IsConflict(err) {
705+
t.Fatalf("unexpected error, expecting an update conflict but got %v", err)
706+
}
707+
}
708+
529709
func setSpecReplicas(u *unstructured.Unstructured, replicas int64) {
530710
setNestedField(u, replicas, "spec", "replicas")
531711
}

0 commit comments

Comments
 (0)