mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-09-12 12:48:51 +00:00
Make ResourceVersion a string internally instead of uint64
Allows us to define different watch versioning regimes in the future as well as to encode information with the resource version. This changes /watch/resources?resourceVersion=3 to start the watch at 4 instead of 3, which means clients can read a resource version and then send it back to the server. Clients should no longer do math on resource versions.
This commit is contained in:
@@ -20,6 +20,7 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"strconv"
|
||||
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
|
||||
"github.com/coreos/go-etcd/etcd"
|
||||
@@ -62,12 +63,43 @@ type EtcdGetSet interface {
|
||||
Watch(prefix string, waitIndex uint64, recursive bool, receiver chan *etcd.Response, stop chan bool) (*etcd.Response, error)
|
||||
}
|
||||
|
||||
type EtcdResourceVersioner interface {
|
||||
SetResourceVersion(obj runtime.Object, version uint64) error
|
||||
ResourceVersion(obj runtime.Object) (uint64, error)
|
||||
}
|
||||
|
||||
// RuntimeVersionAdapter converts a string based versioner to EtcdResourceVersioner
|
||||
type RuntimeVersionAdapter struct {
|
||||
Versioner runtime.ResourceVersioner
|
||||
}
|
||||
|
||||
// SetResourceVersion implements EtcdResourceVersioner
|
||||
func (a RuntimeVersionAdapter) SetResourceVersion(obj runtime.Object, version uint64) error {
|
||||
if version == 0 {
|
||||
return a.Versioner.SetResourceVersion(obj, "")
|
||||
}
|
||||
s := strconv.FormatUint(version, 10)
|
||||
return a.Versioner.SetResourceVersion(obj, s)
|
||||
}
|
||||
|
||||
// SetResourceVersion implements EtcdResourceVersioner
|
||||
func (a RuntimeVersionAdapter) ResourceVersion(obj runtime.Object) (uint64, error) {
|
||||
version, err := a.Versioner.ResourceVersion(obj)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
if version == "" {
|
||||
return 0, nil
|
||||
}
|
||||
return strconv.ParseUint(version, 10, 64)
|
||||
}
|
||||
|
||||
// EtcdHelper offers common object marshalling/unmarshalling operations on an etcd client.
|
||||
type EtcdHelper struct {
|
||||
Client EtcdGetSet
|
||||
Codec runtime.Codec
|
||||
// optional, no atomic operations can be performed without this interface
|
||||
ResourceVersioner runtime.ResourceVersioner
|
||||
ResourceVersioner EtcdResourceVersioner
|
||||
}
|
||||
|
||||
// IsEtcdNotFound returns true iff err is an etcd not found error.
|
||||
|
@@ -44,7 +44,7 @@ func (*TestResource) IsAnAPIObject() {}
|
||||
|
||||
var scheme *runtime.Scheme
|
||||
var codec runtime.Codec
|
||||
var versioner = runtime.NewTypeMetaResourceVersioner()
|
||||
var versioner = RuntimeVersionAdapter{runtime.NewTypeMetaResourceVersioner()}
|
||||
|
||||
func init() {
|
||||
scheme = runtime.NewScheme()
|
||||
@@ -89,11 +89,11 @@ func TestExtractToList(t *testing.T) {
|
||||
},
|
||||
}
|
||||
expect := api.PodList{
|
||||
TypeMeta: api.TypeMeta{ResourceVersion: 10},
|
||||
TypeMeta: api.TypeMeta{ResourceVersion: "10"},
|
||||
Items: []api.Pod{
|
||||
{TypeMeta: api.TypeMeta{ID: "foo", ResourceVersion: 1}},
|
||||
{TypeMeta: api.TypeMeta{ID: "bar", ResourceVersion: 2}},
|
||||
{TypeMeta: api.TypeMeta{ID: "baz", ResourceVersion: 3}},
|
||||
{TypeMeta: api.TypeMeta{ID: "foo", ResourceVersion: "1"}},
|
||||
{TypeMeta: api.TypeMeta{ID: "bar", ResourceVersion: "2"}},
|
||||
{TypeMeta: api.TypeMeta{ID: "baz", ResourceVersion: "3"}},
|
||||
},
|
||||
}
|
||||
|
||||
@@ -204,7 +204,7 @@ func TestSetObj(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestSetObjWithVersion(t *testing.T) {
|
||||
obj := &api.Pod{TypeMeta: api.TypeMeta{ID: "foo", ResourceVersion: 1}}
|
||||
obj := &api.Pod{TypeMeta: api.TypeMeta{ID: "foo", ResourceVersion: "1"}}
|
||||
fakeClient := NewFakeEtcdClient(t)
|
||||
fakeClient.TestIndex = true
|
||||
fakeClient.Data["/some/key"] = EtcdResponseWithError{
|
||||
@@ -254,7 +254,7 @@ func TestSetObjWithoutResourceVersioner(t *testing.T) {
|
||||
func TestAtomicUpdate(t *testing.T) {
|
||||
fakeClient := NewFakeEtcdClient(t)
|
||||
fakeClient.TestIndex = true
|
||||
helper := EtcdHelper{fakeClient, codec, runtime.NewTypeMetaResourceVersioner()}
|
||||
helper := EtcdHelper{fakeClient, codec, versioner}
|
||||
|
||||
// Create a new node.
|
||||
fakeClient.ExpectNotFoundGet("/some/key")
|
||||
@@ -308,7 +308,7 @@ func TestAtomicUpdate(t *testing.T) {
|
||||
func TestAtomicUpdateNoChange(t *testing.T) {
|
||||
fakeClient := NewFakeEtcdClient(t)
|
||||
fakeClient.TestIndex = true
|
||||
helper := EtcdHelper{fakeClient, codec, runtime.NewTypeMetaResourceVersioner()}
|
||||
helper := EtcdHelper{fakeClient, codec, versioner}
|
||||
|
||||
// Create a new node.
|
||||
fakeClient.ExpectNotFoundGet("/some/key")
|
||||
@@ -339,7 +339,7 @@ func TestAtomicUpdateNoChange(t *testing.T) {
|
||||
func TestAtomicUpdate_CreateCollision(t *testing.T) {
|
||||
fakeClient := NewFakeEtcdClient(t)
|
||||
fakeClient.TestIndex = true
|
||||
helper := EtcdHelper{fakeClient, codec, runtime.NewTypeMetaResourceVersioner()}
|
||||
helper := EtcdHelper{fakeClient, codec, versioner}
|
||||
|
||||
fakeClient.ExpectNotFoundGet("/some/key")
|
||||
|
||||
|
@@ -82,7 +82,7 @@ type TransformFunc func(runtime.Object) (runtime.Object, error)
|
||||
// etcdWatcher converts a native etcd watch to a watch.Interface.
|
||||
type etcdWatcher struct {
|
||||
encoding runtime.Codec
|
||||
versioner runtime.ResourceVersioner
|
||||
versioner EtcdResourceVersioner
|
||||
transform TransformFunc
|
||||
|
||||
list bool // If we're doing a recursive watch, should be true.
|
||||
@@ -107,7 +107,7 @@ const watchWaitDuration = 100 * time.Millisecond
|
||||
|
||||
// newEtcdWatcher returns a new etcdWatcher; if list is true, watch sub-nodes. If you provide a transform
|
||||
// and a versioner, the versioner must be able to handle the objects that transform creates.
|
||||
func newEtcdWatcher(list bool, filter FilterFunc, encoding runtime.Codec, versioner runtime.ResourceVersioner, transform TransformFunc) *etcdWatcher {
|
||||
func newEtcdWatcher(list bool, filter FilterFunc, encoding runtime.Codec, versioner EtcdResourceVersioner, transform TransformFunc) *etcdWatcher {
|
||||
w := &etcdWatcher{
|
||||
encoding: encoding,
|
||||
versioner: versioner,
|
||||
|
@@ -395,7 +395,7 @@ func TestWatchFromZeroIndex(t *testing.T) {
|
||||
|
||||
testCases := map[string]struct {
|
||||
Response EtcdResponseWithError
|
||||
ExpectedVersion uint64
|
||||
ExpectedVersion string
|
||||
ExpectedType watch.EventType
|
||||
}{
|
||||
"get value created": {
|
||||
@@ -410,7 +410,7 @@ func TestWatchFromZeroIndex(t *testing.T) {
|
||||
EtcdIndex: 2,
|
||||
},
|
||||
},
|
||||
1,
|
||||
"1",
|
||||
watch.Added,
|
||||
},
|
||||
"get value modified": {
|
||||
@@ -425,7 +425,7 @@ func TestWatchFromZeroIndex(t *testing.T) {
|
||||
EtcdIndex: 3,
|
||||
},
|
||||
},
|
||||
2,
|
||||
"2",
|
||||
watch.Modified,
|
||||
},
|
||||
}
|
||||
@@ -510,10 +510,10 @@ func TestWatchListFromZeroIndex(t *testing.T) {
|
||||
if !ok {
|
||||
t.Fatalf("expected a pod, got %#v", event.Object)
|
||||
}
|
||||
if actualPod.ResourceVersion != 1 {
|
||||
if actualPod.ResourceVersion != "1" {
|
||||
t.Errorf("Expected pod with resource version %d, Got %#v", 1, actualPod)
|
||||
}
|
||||
pod.ResourceVersion = 1
|
||||
pod.ResourceVersion = "1"
|
||||
if e, a := pod, event.Object; !reflect.DeepEqual(e, a) {
|
||||
t.Errorf("Expected %v, got %v", e, a)
|
||||
}
|
||||
|
Reference in New Issue
Block a user