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 package storage
import ( import (
"errors"
"fmt" "fmt"
"k8s.io/apimachinery/pkg/api/errors" apierrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/util/validation/field" "k8s.io/apimachinery/pkg/util/validation/field"
) )
var ErrResourceVersionSetOnCreate = errors.New("resourceVersion should not be set on objects to be created")
const ( const (
ErrCodeKeyNotFound int = iota + 1 ErrCodeKeyNotFound int = iota + 1
ErrCodeKeyExists ErrCodeKeyExists
@ -176,7 +179,7 @@ var tooLargeResourceVersionCauseMsg = "Too large resource version"
// NewTooLargeResourceVersionError returns a timeout error with the given retrySeconds for a request for // 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. // 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 { 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{ err.ErrStatus.Details.Causes = []metav1.StatusCause{
{ {
Type: metav1.CauseTypeResourceVersionTooLarge, Type: metav1.CauseTypeResourceVersionTooLarge,
@ -188,8 +191,8 @@ func NewTooLargeResourceVersionError(minimumResourceVersion, currentRevision uin
// IsTooLargeResourceVersion returns true if the error is a TooLargeResourceVersion error. // IsTooLargeResourceVersion returns true if the error is a TooLargeResourceVersion error.
func IsTooLargeResourceVersion(err error) bool { func IsTooLargeResourceVersion(err error) bool {
if !errors.IsTimeout(err) { if !apierrors.IsTimeout(err) {
return false 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) defer span.End(500 * time.Millisecond)
if version, err := s.versioner.ObjectResourceVersion(obj); err == nil && version != 0 { 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 { if err := s.versioner.PrepareObjectForStorage(obj); err != nil {
return fmt.Errorf("PrepareObjectForStorage failed: %v", err) 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) type KeyValidation func(ctx context.Context, t *testing.T, key string)
func RunTestCreate(ctx context.Context, t *testing.T, store storage.Interface, validation KeyValidation) { func RunTestCreate(ctx context.Context, t *testing.T, store storage.Interface, validation KeyValidation) {
out := &example.Pod{} tests := []struct {
obj := &example.Pod{ObjectMeta: metav1.ObjectMeta{Name: "foo", Namespace: "test-ns", SelfLink: "testlink"}} 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 for _, tt := range tests {
key := computePodKey(obj) t.Run(tt.name, func(t *testing.T) {
if err := store.Get(ctx, key, storage.GetOptions{}, out); !storage.IsNotFound(err) { out := &example.Pod{} // reset
t.Fatalf("expecting empty result on key %s, got %v", key, err) // 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 { err := store.Create(ctx, key, tt.inputObj, out, 0)
t.Fatalf("Set failed: %v", err) 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) { func RunTestCreateWithTTL(ctx context.Context, t *testing.T, store storage.Interface) {