k8s.io/apiserver/storage: add a new TestCreate case.

Add a test case of create with rv set.

Signed-off-by: Siyuan Zhang <sizhang@google.com>
This commit is contained in:
Siyuan Zhang 2023-10-11 10:24:31 -07:00
parent 0d63366bdf
commit 2f923e356e
3 changed files with 44 additions and 26 deletions

View File

@ -17,13 +17,16 @@ limitations under the License.
package storage
import (
"errors"
"fmt"
"k8s.io/apimachinery/pkg/api/errors"
apierrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/util/validation/field"
)
var ErrResourceVersionSetOnCreate = errors.New("resourceVersion should not be set on objects to be created")
const (
ErrCodeKeyNotFound int = iota + 1
ErrCodeKeyExists
@ -176,7 +179,7 @@ var tooLargeResourceVersionCauseMsg = "Too large resource version"
// NewTooLargeResourceVersionError returns a timeout error with the given retrySeconds for a request for
// a minimum resource version that is larger than the largest currently available resource version for a requested resource.
func NewTooLargeResourceVersionError(minimumResourceVersion, currentRevision uint64, retrySeconds int) error {
err := errors.NewTimeoutError(fmt.Sprintf("Too large resource version: %d, current: %d", minimumResourceVersion, currentRevision), retrySeconds)
err := apierrors.NewTimeoutError(fmt.Sprintf("Too large resource version: %d, current: %d", minimumResourceVersion, currentRevision), retrySeconds)
err.ErrStatus.Details.Causes = []metav1.StatusCause{
{
Type: metav1.CauseTypeResourceVersionTooLarge,
@ -188,8 +191,8 @@ func NewTooLargeResourceVersionError(minimumResourceVersion, currentRevision uin
// IsTooLargeResourceVersion returns true if the error is a TooLargeResourceVersion error.
func IsTooLargeResourceVersion(err error) bool {
if !errors.IsTimeout(err) {
if !apierrors.IsTimeout(err) {
return false
}
return errors.HasStatusCause(err, metav1.CauseTypeResourceVersionTooLarge)
return apierrors.HasStatusCause(err, metav1.CauseTypeResourceVersionTooLarge)
}

View File

@ -199,7 +199,7 @@ func (s *store) Create(ctx context.Context, key string, obj, out runtime.Object,
)
defer span.End(500 * time.Millisecond)
if version, err := s.versioner.ObjectResourceVersion(obj); err == nil && version != 0 {
return errors.New("resourceVersion should not be set on objects to be created")
return storage.ErrResourceVersionSetOnCreate
}
if err := s.versioner.PrepareObjectForStorage(obj); err != nil {
return fmt.Errorf("PrepareObjectForStorage failed: %v", err)

View File

@ -44,30 +44,45 @@ import (
type KeyValidation func(ctx context.Context, t *testing.T, key string)
func RunTestCreate(ctx context.Context, t *testing.T, store storage.Interface, validation KeyValidation) {
out := &example.Pod{}
obj := &example.Pod{ObjectMeta: metav1.ObjectMeta{Name: "foo", Namespace: "test-ns", SelfLink: "testlink"}}
tests := []struct {
name string
inputObj *example.Pod
expectedError error
}{{
name: "successful create",
inputObj: &example.Pod{ObjectMeta: metav1.ObjectMeta{Name: "foo", Namespace: "test-ns"}},
}, {
name: "create with ResourceVersion set",
inputObj: &example.Pod{ObjectMeta: metav1.ObjectMeta{Name: "bar", Namespace: "test-ns", ResourceVersion: "1"}},
expectedError: storage.ErrResourceVersionSetOnCreate,
}}
// verify that kv pair is empty before set
key := computePodKey(obj)
if err := store.Get(ctx, key, storage.GetOptions{}, out); !storage.IsNotFound(err) {
t.Fatalf("expecting empty result on key %s, got %v", key, err)
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
out := &example.Pod{} // reset
// verify that kv pair is empty before set
key := computePodKey(tt.inputObj)
if err := store.Get(ctx, key, storage.GetOptions{}, out); !storage.IsNotFound(err) {
t.Fatalf("expecting empty result on key %s, got %v", key, err)
}
if err := store.Create(ctx, key, obj, out, 0); err != nil {
t.Fatalf("Set failed: %v", err)
err := store.Create(ctx, key, tt.inputObj, out, 0)
if !errors.Is(err, tt.expectedError) {
t.Errorf("expecting error %v, but get: %v", tt.expectedError, err)
}
if err != nil {
return
}
// basic tests of the output
if tt.inputObj.ObjectMeta.Name != out.ObjectMeta.Name {
t.Errorf("pod name want=%s, get=%s", tt.inputObj.ObjectMeta.Name, out.ObjectMeta.Name)
}
if out.ResourceVersion == "" {
t.Errorf("output should have non-empty resource version")
}
validation(ctx, t, key)
})
}
// basic tests of the output
if obj.ObjectMeta.Name != out.ObjectMeta.Name {
t.Errorf("pod name want=%s, get=%s", obj.ObjectMeta.Name, out.ObjectMeta.Name)
}
if out.ResourceVersion == "" {
t.Errorf("output should have non-empty resource version")
}
if out.SelfLink != "" {
t.Errorf("output should have empty selfLink")
}
validation(ctx, t, key)
}
func RunTestCreateWithTTL(ctx context.Context, t *testing.T, store storage.Interface) {