mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-24 12:15:52 +00:00
Move GuaranteedUpdateChecksData test to generic package
This commit is contained in:
parent
5344bc5e1b
commit
afc5ded839
@ -174,65 +174,7 @@ func TestGuaranteedUpdateWithTTL(t *testing.T) {
|
|||||||
|
|
||||||
func TestGuaranteedUpdateChecksStoredData(t *testing.T) {
|
func TestGuaranteedUpdateChecksStoredData(t *testing.T) {
|
||||||
ctx, store, _ := testSetup(t)
|
ctx, store, _ := testSetup(t)
|
||||||
input := &example.Pod{ObjectMeta: metav1.ObjectMeta{Name: "foo"}}
|
storagetesting.RunTestGuaranteedUpdateChecksStoredData(ctx, t, &storeWithPrefixTransformer{store})
|
||||||
key := "/somekey"
|
|
||||||
|
|
||||||
// serialize input into etcd with data that would be normalized by a write - in this case, leading
|
|
||||||
// and trailing whitespace
|
|
||||||
codec := codecs.LegacyCodec(examplev1.SchemeGroupVersion)
|
|
||||||
data, err := runtime.Encode(codec, input)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
resp, err := store.client.Put(ctx, key, "test! "+string(data)+" ")
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// this update should write the canonical value to etcd because the new serialization differs
|
|
||||||
// from the stored serialization
|
|
||||||
input.ResourceVersion = strconv.FormatInt(resp.Header.Revision, 10)
|
|
||||||
out := &example.Pod{}
|
|
||||||
err = store.GuaranteedUpdate(ctx, key, out, true, nil,
|
|
||||||
func(_ runtime.Object, _ storage.ResponseMeta) (runtime.Object, *uint64, error) {
|
|
||||||
return input, nil, nil
|
|
||||||
}, input)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("Update failed: %v", err)
|
|
||||||
}
|
|
||||||
if out.ResourceVersion == strconv.FormatInt(resp.Header.Revision, 10) {
|
|
||||||
t.Errorf("guaranteed update should have updated the serialized data, got %#v", out)
|
|
||||||
}
|
|
||||||
|
|
||||||
lastVersion := out.ResourceVersion
|
|
||||||
|
|
||||||
// this update should not write to etcd because the input matches the stored data
|
|
||||||
input = out
|
|
||||||
out = &example.Pod{}
|
|
||||||
err = store.GuaranteedUpdate(ctx, key, out, true, nil,
|
|
||||||
func(_ runtime.Object, _ storage.ResponseMeta) (runtime.Object, *uint64, error) {
|
|
||||||
return input, nil, nil
|
|
||||||
}, input)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("Update failed: %v", err)
|
|
||||||
}
|
|
||||||
if out.ResourceVersion != lastVersion {
|
|
||||||
t.Errorf("guaranteed update should have short-circuited write, got %#v", out)
|
|
||||||
}
|
|
||||||
|
|
||||||
store.transformer = storagetesting.NewPrefixTransformer([]byte(defaultTestPrefix), true)
|
|
||||||
|
|
||||||
// this update should write to etcd because the transformer reported stale
|
|
||||||
err = store.GuaranteedUpdate(ctx, key, out, true, nil,
|
|
||||||
func(_ runtime.Object, _ storage.ResponseMeta) (runtime.Object, *uint64, error) {
|
|
||||||
return input, nil, nil
|
|
||||||
}, input)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("Update failed: %v", err)
|
|
||||||
}
|
|
||||||
if out.ResourceVersion == lastVersion {
|
|
||||||
t.Errorf("guaranteed update should have written to etcd when transformer reported stale, got %#v", out)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestGuaranteedUpdateWithConflict(t *testing.T) {
|
func TestGuaranteedUpdateWithConflict(t *testing.T) {
|
||||||
@ -247,78 +189,7 @@ func TestGuaranteedUpdateWithSuggestionAndConflict(t *testing.T) {
|
|||||||
|
|
||||||
func TestTransformationFailure(t *testing.T) {
|
func TestTransformationFailure(t *testing.T) {
|
||||||
ctx, store, _ := testSetup(t)
|
ctx, store, _ := testSetup(t)
|
||||||
|
storagetesting.RunTestTransformationFailure(ctx, t, &storeWithPrefixTransformer{store})
|
||||||
preset := []struct {
|
|
||||||
key string
|
|
||||||
obj *example.Pod
|
|
||||||
storedObj *example.Pod
|
|
||||||
}{{
|
|
||||||
key: "/one-level/test",
|
|
||||||
obj: &example.Pod{
|
|
||||||
ObjectMeta: metav1.ObjectMeta{Name: "bar"},
|
|
||||||
Spec: storagetesting.DeepEqualSafePodSpec(),
|
|
||||||
},
|
|
||||||
}, {
|
|
||||||
key: "/two-level/1/test",
|
|
||||||
obj: &example.Pod{
|
|
||||||
ObjectMeta: metav1.ObjectMeta{Name: "baz"},
|
|
||||||
Spec: storagetesting.DeepEqualSafePodSpec(),
|
|
||||||
},
|
|
||||||
}}
|
|
||||||
for i, ps := range preset[:1] {
|
|
||||||
preset[i].storedObj = &example.Pod{}
|
|
||||||
err := store.Create(ctx, ps.key, ps.obj, preset[:1][i].storedObj, 0)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("Set failed: %v", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// create a second resource with an invalid prefix
|
|
||||||
oldTransformer := store.transformer
|
|
||||||
store.transformer = storagetesting.NewPrefixTransformer([]byte("otherprefix!"), false)
|
|
||||||
for i, ps := range preset[1:] {
|
|
||||||
preset[1:][i].storedObj = &example.Pod{}
|
|
||||||
err := store.Create(ctx, ps.key, ps.obj, preset[1:][i].storedObj, 0)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("Set failed: %v", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
store.transformer = oldTransformer
|
|
||||||
|
|
||||||
// List should fail
|
|
||||||
var got example.PodList
|
|
||||||
storageOpts := storage.ListOptions{
|
|
||||||
Predicate: storage.Everything,
|
|
||||||
Recursive: true,
|
|
||||||
}
|
|
||||||
if err := store.GetList(ctx, "/", storageOpts, &got); !storage.IsInternalError(err) {
|
|
||||||
t.Errorf("Unexpected error %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get should fail
|
|
||||||
if err := store.Get(ctx, preset[1].key, storage.GetOptions{}, &example.Pod{}); !storage.IsInternalError(err) {
|
|
||||||
t.Errorf("Unexpected error: %v", err)
|
|
||||||
}
|
|
||||||
// GuaranteedUpdate without suggestion should return an error
|
|
||||||
if err := store.GuaranteedUpdate(ctx, preset[1].key, &example.Pod{}, false, nil, func(input runtime.Object, res storage.ResponseMeta) (output runtime.Object, ttl *uint64, err error) {
|
|
||||||
return input, nil, nil
|
|
||||||
}, nil); !storage.IsInternalError(err) {
|
|
||||||
t.Errorf("Unexpected error: %v", err)
|
|
||||||
}
|
|
||||||
// GuaranteedUpdate with suggestion should return an error if we don't change the object
|
|
||||||
if err := store.GuaranteedUpdate(ctx, preset[1].key, &example.Pod{}, false, nil, func(input runtime.Object, res storage.ResponseMeta) (output runtime.Object, ttl *uint64, err error) {
|
|
||||||
return input, nil, nil
|
|
||||||
}, preset[1].obj); err == nil {
|
|
||||||
t.Errorf("Unexpected error: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Delete fails with internal error.
|
|
||||||
if err := store.Delete(ctx, preset[1].key, &example.Pod{}, nil, storage.ValidateAllObjectFunc, nil); !storage.IsInternalError(err) {
|
|
||||||
t.Errorf("Unexpected error: %v", err)
|
|
||||||
}
|
|
||||||
if err := store.Get(ctx, preset[1].key, storage.GetOptions{}, &example.Pod{}); !storage.IsInternalError(err) {
|
|
||||||
t.Errorf("Unexpected error: %v", err)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestList(t *testing.T) {
|
func TestList(t *testing.T) {
|
||||||
|
@ -1327,6 +1327,71 @@ func RunTestGuaranteedUpdateWithTTL(ctx context.Context, t *testing.T, store sto
|
|||||||
TestCheckEventType(t, watch.Deleted, w)
|
TestCheckEventType(t, watch.Deleted, w)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func RunTestGuaranteedUpdateChecksStoredData(ctx context.Context, t *testing.T, store InterfaceWithPrefixTransformer) {
|
||||||
|
input := &example.Pod{ObjectMeta: metav1.ObjectMeta{Name: "foo"}}
|
||||||
|
key := "/somekey"
|
||||||
|
|
||||||
|
// serialize input into etcd with data that would be normalized by a write -
|
||||||
|
// in this case, leading whitespace
|
||||||
|
revertTransformer := store.UpdatePrefixTransformer(
|
||||||
|
func(transformer *PrefixTransformer) value.Transformer {
|
||||||
|
transformer.prefix = []byte(string(transformer.prefix) + " ")
|
||||||
|
return transformer
|
||||||
|
})
|
||||||
|
_, initial := TestPropagateStore(ctx, t, store, input)
|
||||||
|
revertTransformer()
|
||||||
|
|
||||||
|
// this update should write the canonical value to etcd because the new serialization differs
|
||||||
|
// from the stored serialization
|
||||||
|
input.ResourceVersion = initial.ResourceVersion
|
||||||
|
out := &example.Pod{}
|
||||||
|
err := store.GuaranteedUpdate(ctx, key, out, true, nil,
|
||||||
|
func(_ runtime.Object, _ storage.ResponseMeta) (runtime.Object, *uint64, error) {
|
||||||
|
return input, nil, nil
|
||||||
|
}, input)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Update failed: %v", err)
|
||||||
|
}
|
||||||
|
if out.ResourceVersion == initial.ResourceVersion {
|
||||||
|
t.Errorf("guaranteed update should have updated the serialized data, got %#v", out)
|
||||||
|
}
|
||||||
|
|
||||||
|
lastVersion := out.ResourceVersion
|
||||||
|
|
||||||
|
// this update should not write to etcd because the input matches the stored data
|
||||||
|
input = out
|
||||||
|
out = &example.Pod{}
|
||||||
|
err = store.GuaranteedUpdate(ctx, key, out, true, nil,
|
||||||
|
func(_ runtime.Object, _ storage.ResponseMeta) (runtime.Object, *uint64, error) {
|
||||||
|
return input, nil, nil
|
||||||
|
}, input)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Update failed: %v", err)
|
||||||
|
}
|
||||||
|
if out.ResourceVersion != lastVersion {
|
||||||
|
t.Errorf("guaranteed update should have short-circuited write, got %#v", out)
|
||||||
|
}
|
||||||
|
|
||||||
|
revertTransformer = store.UpdatePrefixTransformer(
|
||||||
|
func(transformer *PrefixTransformer) value.Transformer {
|
||||||
|
transformer.stale = true
|
||||||
|
return transformer
|
||||||
|
})
|
||||||
|
defer revertTransformer()
|
||||||
|
|
||||||
|
// this update should write to etcd because the transformer reported stale
|
||||||
|
err = store.GuaranteedUpdate(ctx, key, out, true, nil,
|
||||||
|
func(_ runtime.Object, _ storage.ResponseMeta) (runtime.Object, *uint64, error) {
|
||||||
|
return input, nil, nil
|
||||||
|
}, input)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Update failed: %v", err)
|
||||||
|
}
|
||||||
|
if out.ResourceVersion == lastVersion {
|
||||||
|
t.Errorf("guaranteed update should have written to etcd when transformer reported stale, got %#v", out)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func RunTestGuaranteedUpdateWithConflict(ctx context.Context, t *testing.T, store storage.Interface) {
|
func RunTestGuaranteedUpdateWithConflict(ctx context.Context, t *testing.T, store storage.Interface) {
|
||||||
key, _ := TestPropagateStore(ctx, t, store, &example.Pod{ObjectMeta: metav1.ObjectMeta{Name: "foo"}})
|
key, _ := TestPropagateStore(ctx, t, store, &example.Pod{ObjectMeta: metav1.ObjectMeta{Name: "foo"}})
|
||||||
|
|
||||||
@ -1447,6 +1512,82 @@ func RunTestGuaranteedUpdateWithSuggestionAndConflict(ctx context.Context, t *te
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func RunTestTransformationFailure(ctx context.Context, t *testing.T, store InterfaceWithPrefixTransformer) {
|
||||||
|
preset := []struct {
|
||||||
|
key string
|
||||||
|
obj *example.Pod
|
||||||
|
storedObj *example.Pod
|
||||||
|
}{{
|
||||||
|
key: "/one-level/test",
|
||||||
|
obj: &example.Pod{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{Name: "bar"},
|
||||||
|
Spec: DeepEqualSafePodSpec(),
|
||||||
|
},
|
||||||
|
}, {
|
||||||
|
key: "/two-level/1/test",
|
||||||
|
obj: &example.Pod{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{Name: "baz"},
|
||||||
|
Spec: DeepEqualSafePodSpec(),
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
for i, ps := range preset[:1] {
|
||||||
|
preset[i].storedObj = &example.Pod{}
|
||||||
|
err := store.Create(ctx, ps.key, ps.obj, preset[:1][i].storedObj, 0)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Set failed: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// create a second resource with an invalid prefix
|
||||||
|
revertTransformer := store.UpdatePrefixTransformer(
|
||||||
|
func(transformer *PrefixTransformer) value.Transformer {
|
||||||
|
return NewPrefixTransformer([]byte("otherprefix!"), false)
|
||||||
|
})
|
||||||
|
for i, ps := range preset[1:] {
|
||||||
|
preset[1:][i].storedObj = &example.Pod{}
|
||||||
|
err := store.Create(ctx, ps.key, ps.obj, preset[1:][i].storedObj, 0)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Set failed: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
revertTransformer()
|
||||||
|
|
||||||
|
// List should fail
|
||||||
|
var got example.PodList
|
||||||
|
storageOpts := storage.ListOptions{
|
||||||
|
Predicate: storage.Everything,
|
||||||
|
Recursive: true,
|
||||||
|
}
|
||||||
|
if err := store.GetList(ctx, "/", storageOpts, &got); !storage.IsInternalError(err) {
|
||||||
|
t.Errorf("Unexpected error %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get should fail
|
||||||
|
if err := store.Get(ctx, preset[1].key, storage.GetOptions{}, &example.Pod{}); !storage.IsInternalError(err) {
|
||||||
|
t.Errorf("Unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
updateFunc := func(input runtime.Object, res storage.ResponseMeta) (runtime.Object, *uint64, error) {
|
||||||
|
return input, nil, nil
|
||||||
|
}
|
||||||
|
// GuaranteedUpdate without suggestion should return an error
|
||||||
|
if err := store.GuaranteedUpdate(ctx, preset[1].key, &example.Pod{}, false, nil, updateFunc, nil); !storage.IsInternalError(err) {
|
||||||
|
t.Errorf("Unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
// GuaranteedUpdate with suggestion should return an error if we don't change the object
|
||||||
|
if err := store.GuaranteedUpdate(ctx, preset[1].key, &example.Pod{}, false, nil, updateFunc, preset[1].obj); err == nil {
|
||||||
|
t.Errorf("Unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete fails with internal error.
|
||||||
|
if err := store.Delete(ctx, preset[1].key, &example.Pod{}, nil, storage.ValidateAllObjectFunc, nil); !storage.IsInternalError(err) {
|
||||||
|
t.Errorf("Unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
if err := store.Get(ctx, preset[1].key, storage.GetOptions{}, &example.Pod{}); !storage.IsInternalError(err) {
|
||||||
|
t.Errorf("Unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func RunTestCount(ctx context.Context, t *testing.T, store storage.Interface) {
|
func RunTestCount(ctx context.Context, t *testing.T, store storage.Interface) {
|
||||||
resourceA := "/foo.bar.io/abc"
|
resourceA := "/foo.bar.io/abc"
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user