Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
K
k3s
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Jacklull
k3s
Commits
f6f2f41a
Commit
f6f2f41a
authored
Oct 29, 2015
by
Timothy St. Clair
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Removal of fakeClient from registry/generic/etcd/etcd_test.go in leiu of
NewEtcdTestClientServer
parent
4711a873
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
208 additions
and
390 deletions
+208
-390
etcd.go
pkg/registry/generic/etcd/etcd.go
+2
-0
etcd_test.go
pkg/registry/generic/etcd/etcd_test.go
+149
-390
utils.go
pkg/storage/testing/utils.go
+57
-0
No files found.
pkg/registry/generic/etcd/etcd.go
View file @
f6f2f41a
...
@@ -54,6 +54,8 @@ import (
...
@@ -54,6 +54,8 @@ import (
// logic specific to the API.
// logic specific to the API.
//
//
// TODO: make the default exposed methods exactly match a generic RESTStorage
// TODO: make the default exposed methods exactly match a generic RESTStorage
// TODO: because all aspects of etcd have been removed it should really
// just be called a registry implementation.
type
Etcd
struct
{
type
Etcd
struct
{
// Called to make a new object, should return e.g., &api.Pod{}
// Called to make a new object, should return e.g., &api.Pod{}
NewFunc
func
()
runtime
.
Object
NewFunc
func
()
runtime
.
Object
...
...
pkg/registry/generic/etcd/etcd_test.go
View file @
f6f2f41a
...
@@ -19,6 +19,7 @@ package etcd
...
@@ -19,6 +19,7 @@ package etcd
import
(
import
(
"fmt"
"fmt"
"path"
"path"
"reflect"
"testing"
"testing"
"k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/api"
...
@@ -27,13 +28,11 @@ import (
...
@@ -27,13 +28,11 @@ import (
"k8s.io/kubernetes/pkg/registry/generic"
"k8s.io/kubernetes/pkg/registry/generic"
"k8s.io/kubernetes/pkg/runtime"
"k8s.io/kubernetes/pkg/runtime"
etcdstorage
"k8s.io/kubernetes/pkg/storage/etcd"
etcdstorage
"k8s.io/kubernetes/pkg/storage/etcd"
"k8s.io/kubernetes/pkg/tools"
etcdtesting
"k8s.io/kubernetes/pkg/storage/etcd/testing"
storagetesting
"k8s.io/kubernetes/pkg/storage/testing"
"k8s.io/kubernetes/pkg/tools/etcdtest"
"k8s.io/kubernetes/pkg/tools/etcdtest"
"k8s.io/kubernetes/pkg/util"
"k8s.io/kubernetes/pkg/util/fielderrors"
"k8s.io/kubernetes/pkg/util/fielderrors"
"k8s.io/kubernetes/pkg/util/sets"
"k8s.io/kubernetes/pkg/util/sets"
"github.com/coreos/go-etcd/etcd"
)
)
type
testRESTStrategy
struct
{
type
testRESTStrategy
struct
{
...
@@ -68,13 +67,13 @@ func hasCreated(t *testing.T, pod *api.Pod) func(runtime.Object) bool {
...
@@ -68,13 +67,13 @@ func hasCreated(t *testing.T, pod *api.Pod) func(runtime.Object) bool {
}
}
}
}
func
NewTestGenericEtcdRegistry
(
t
*
testing
.
T
)
(
*
tools
.
FakeEtcdClient
,
*
Etcd
)
{
func
NewTestGenericEtcdRegistry
(
t
*
testing
.
T
)
(
*
etcdtesting
.
EtcdTestServer
,
*
Etcd
)
{
f
:=
tools
.
NewFakeEtcdClient
(
t
)
f
.
TestIndex
=
true
s
:=
etcdstorage
.
NewEtcdStorage
(
f
,
testapi
.
Default
.
Codec
(),
etcdtest
.
PathPrefix
())
strategy
:=
&
testRESTStrategy
{
api
.
Scheme
,
api
.
SimpleNameGenerator
,
true
,
false
,
true
}
podPrefix
:=
"/pods"
podPrefix
:=
"/pods"
return
f
,
&
Etcd
{
server
:=
etcdtesting
.
NewEtcdTestClientServer
(
t
)
s
:=
etcdstorage
.
NewEtcdStorage
(
server
.
Client
,
testapi
.
Default
.
Codec
(),
etcdtest
.
PathPrefix
())
strategy
:=
&
testRESTStrategy
{
api
.
Scheme
,
api
.
SimpleNameGenerator
,
true
,
false
,
true
}
return
server
,
&
Etcd
{
NewFunc
:
func
()
runtime
.
Object
{
return
&
api
.
Pod
{}
},
NewFunc
:
func
()
runtime
.
Object
{
return
&
api
.
Pod
{}
},
NewListFunc
:
func
()
runtime
.
Object
{
return
&
api
.
PodList
{}
},
NewListFunc
:
func
()
runtime
.
Object
{
return
&
api
.
PodList
{}
},
EndpointName
:
"pods"
,
EndpointName
:
"pods"
,
...
@@ -129,96 +128,48 @@ func (everythingMatcher) MatchesSingle() (string, bool) {
...
@@ -129,96 +128,48 @@ func (everythingMatcher) MatchesSingle() (string, bool) {
func
TestEtcdList
(
t
*
testing
.
T
)
{
func
TestEtcdList
(
t
*
testing
.
T
)
{
podA
:=
&
api
.
Pod
{
podA
:=
&
api
.
Pod
{
ObjectMeta
:
api
.
ObjectMeta
{
Namespace
:
"test"
,
Name
:
"
foo
"
},
ObjectMeta
:
api
.
ObjectMeta
{
Namespace
:
"test"
,
Name
:
"
bar
"
},
Spec
:
api
.
PodSpec
{
NodeName
:
"machine"
},
Spec
:
api
.
PodSpec
{
NodeName
:
"machine"
},
}
}
podB
:=
&
api
.
Pod
{
podB
:=
&
api
.
Pod
{
ObjectMeta
:
api
.
ObjectMeta
{
Namespace
:
"test"
,
Name
:
"
bar
"
},
ObjectMeta
:
api
.
ObjectMeta
{
Namespace
:
"test"
,
Name
:
"
foo
"
},
Spec
:
api
.
PodSpec
{
NodeName
:
"machine"
},
Spec
:
api
.
PodSpec
{
NodeName
:
"machine"
},
}
}
singleElemListResp
:=
&
etcd
.
Response
{
Node
:
&
etcd
.
Node
{
Value
:
runtime
.
EncodeOrDie
(
testapi
.
Default
.
Codec
(),
podA
),
},
}
normalListResp
:=
&
etcd
.
Response
{
Node
:
&
etcd
.
Node
{
Nodes
:
[]
*
etcd
.
Node
{
{
Value
:
runtime
.
EncodeOrDie
(
testapi
.
Default
.
Codec
(),
podA
)},
{
Value
:
runtime
.
EncodeOrDie
(
testapi
.
Default
.
Codec
(),
podB
)},
},
},
}
testContext
:=
api
.
WithNamespace
(
api
.
NewContext
(),
"test"
)
testContext
:=
api
.
WithNamespace
(
api
.
NewContext
(),
"test"
)
noNamespaceContext
:=
api
.
NewContext
()
noNamespaceContext
:=
api
.
NewContext
()
table
:=
map
[
string
]
struct
{
table
:=
map
[
string
]
struct
{
in
tools
.
EtcdResponseWithError
in
*
api
.
PodList
m
generic
.
Matcher
m
generic
.
Matcher
out
runtime
.
Object
out
runtime
.
Object
context
api
.
Context
context
api
.
Context
succeed
bool
}{
}{
"empty"
:
{
in
:
tools
.
EtcdResponseWithError
{
R
:
&
etcd
.
Response
{
Node
:
&
etcd
.
Node
{
Nodes
:
[]
*
etcd
.
Node
{},
},
},
E
:
nil
,
},
m
:
everythingMatcher
{},
out
:
&
api
.
PodList
{
Items
:
[]
api
.
Pod
{}},
succeed
:
true
,
},
"notFound"
:
{
"notFound"
:
{
in
:
tools
.
EtcdResponseWithError
{
in
:
nil
,
R
:
&
etcd
.
Response
{},
m
:
everythingMatcher
{},
E
:
tools
.
EtcdErrorNotFound
,
out
:
&
api
.
PodList
{
Items
:
[]
api
.
Pod
{}},
},
m
:
everythingMatcher
{},
out
:
&
api
.
PodList
{
Items
:
[]
api
.
Pod
{}},
succeed
:
true
,
},
},
"normal"
:
{
"normal"
:
{
in
:
tools
.
EtcdResponseWithError
{
in
:
&
api
.
PodList
{
Items
:
[]
api
.
Pod
{
*
podA
,
*
podB
}},
R
:
normalListResp
,
m
:
everythingMatcher
{},
E
:
nil
,
out
:
&
api
.
PodList
{
Items
:
[]
api
.
Pod
{
*
podA
,
*
podB
}},
},
m
:
everythingMatcher
{},
out
:
&
api
.
PodList
{
Items
:
[]
api
.
Pod
{
*
podA
,
*
podB
}},
succeed
:
true
,
},
},
"normalFiltered"
:
{
"normalFiltered"
:
{
in
:
tools
.
EtcdResponseWithError
{
in
:
&
api
.
PodList
{
Items
:
[]
api
.
Pod
{
*
podA
,
*
podB
}},
R
:
singleElemListResp
,
m
:
setMatcher
{
sets
.
NewString
(
"foo"
)},
E
:
nil
,
out
:
&
api
.
PodList
{
Items
:
[]
api
.
Pod
{
*
podB
}},
},
m
:
setMatcher
{
sets
.
NewString
(
"foo"
)},
out
:
&
api
.
PodList
{
Items
:
[]
api
.
Pod
{
*
podA
}},
succeed
:
true
,
},
},
"normalFilteredNoNamespace"
:
{
"normalFilteredNoNamespace"
:
{
in
:
tools
.
EtcdResponseWithError
{
in
:
&
api
.
PodList
{
Items
:
[]
api
.
Pod
{
*
podA
,
*
podB
}},
R
:
normalListResp
,
E
:
nil
,
},
m
:
setMatcher
{
sets
.
NewString
(
"foo"
)},
m
:
setMatcher
{
sets
.
NewString
(
"foo"
)},
out
:
&
api
.
PodList
{
Items
:
[]
api
.
Pod
{
*
pod
A
}},
out
:
&
api
.
PodList
{
Items
:
[]
api
.
Pod
{
*
pod
B
}},
context
:
noNamespaceContext
,
context
:
noNamespaceContext
,
succeed
:
true
,
},
},
"normalFilteredMatchMultiple"
:
{
"normalFilteredMatchMultiple"
:
{
in
:
tools
.
EtcdResponseWithError
{
in
:
&
api
.
PodList
{
Items
:
[]
api
.
Pod
{
*
podA
,
*
podB
}},
R
:
normalListResp
,
m
:
setMatcher
{
sets
.
NewString
(
"foo"
,
"makeMatchSingleReturnFalse"
)},
E
:
nil
,
out
:
&
api
.
PodList
{
Items
:
[]
api
.
Pod
{
*
podB
}},
},
m
:
setMatcher
{
sets
.
NewString
(
"foo"
,
"makeMatchSingleReturnFalse"
)},
out
:
&
api
.
PodList
{
Items
:
[]
api
.
Pod
{
*
podA
}},
succeed
:
true
,
},
},
}
}
...
@@ -227,29 +178,25 @@ func TestEtcdList(t *testing.T) {
...
@@ -227,29 +178,25 @@ func TestEtcdList(t *testing.T) {
if
item
.
context
!=
nil
{
if
item
.
context
!=
nil
{
ctx
=
item
.
context
ctx
=
item
.
context
}
}
fakeClient
,
registry
:=
NewTestGenericEtcdRegistry
(
t
)
server
,
registry
:=
NewTestGenericEtcdRegistry
(
t
)
if
name
,
ok
:=
item
.
m
.
MatchesSingle
();
ok
{
if
key
,
err
:=
registry
.
KeyFunc
(
ctx
,
name
);
err
==
nil
{
if
item
.
in
!=
nil
{
key
=
etcdtest
.
AddPrefix
(
key
)
if
err
:=
storagetesting
.
CreateList
(
t
,
"/pods"
,
registry
.
Storage
,
item
.
in
);
err
!=
nil
{
fakeClient
.
Data
[
key
]
=
item
.
in
t
.
Errorf
(
"Unexpected error %v"
,
err
)
}
else
{
key
:=
registry
.
KeyRootFunc
(
ctx
)
key
=
etcdtest
.
AddPrefix
(
key
)
fakeClient
.
Data
[
key
]
=
item
.
in
}
}
}
else
{
key
:=
registry
.
KeyRootFunc
(
ctx
)
key
=
etcdtest
.
AddPrefix
(
key
)
fakeClient
.
Data
[
key
]
=
item
.
in
}
}
list
,
err
:=
registry
.
ListPredicate
(
ctx
,
item
.
m
,
nil
)
list
,
err
:=
registry
.
ListPredicate
(
ctx
,
item
.
m
,
nil
)
if
e
,
a
:=
item
.
succeed
,
err
==
nil
;
e
!=
a
{
if
e
rr
!=
nil
{
t
.
Errorf
(
"
%v: expected %v, got %v: %v"
,
name
,
e
,
a
,
err
)
t
.
Errorf
(
"
Unexpected error %v"
,
err
)
continue
continue
}
}
// DeepDerivative e,a is needed here b/c the storage layer sets ResourceVersion
if
e
,
a
:=
item
.
out
,
list
;
!
api
.
Semantic
.
DeepDerivative
(
e
,
a
)
{
if
e
,
a
:=
item
.
out
,
list
;
!
api
.
Semantic
.
DeepDerivative
(
e
,
a
)
{
t
.
Errorf
(
"%v: Expected %#v, got %#v"
,
name
,
e
,
a
)
t
.
Errorf
(
"%v: Expected %#v, got %#v"
,
name
,
e
,
a
)
}
}
server
.
Terminate
(
t
)
}
}
}
}
...
@@ -263,78 +210,50 @@ func TestEtcdCreate(t *testing.T) {
...
@@ -263,78 +210,50 @@ func TestEtcdCreate(t *testing.T) {
Spec
:
api
.
PodSpec
{
NodeName
:
"machine2"
},
Spec
:
api
.
PodSpec
{
NodeName
:
"machine2"
},
}
}
nodeWithPodA
:=
tools
.
EtcdResponseWithError
{
testContext
:=
api
.
WithNamespace
(
api
.
NewContext
(),
"test"
)
R
:
&
etcd
.
Response
{
server
,
registry
:=
NewTestGenericEtcdRegistry
(
t
)
Node
:
&
etcd
.
Node
{
defer
server
.
Terminate
(
t
)
Value
:
runtime
.
EncodeOrDie
(
testapi
.
Default
.
Codec
(),
podA
),
ModifiedIndex
:
1
,
CreatedIndex
:
1
,
},
},
E
:
nil
,
}
emptyNode
:=
tools
.
EtcdResponseWithError
{
// create the object
R
:
&
etcd
.
Response
{},
objA
,
err
:=
registry
.
Create
(
testContext
,
podA
)
E
:
tools
.
EtcdErrorNotFound
,
if
err
!=
nil
{
t
.
Errorf
(
"Unexpected error: %v"
,
err
)
}
}
testContext
:=
api
.
WithNamespace
(
api
.
NewContext
(),
"test"
)
// get the object
checkobj
,
err
:=
registry
.
Get
(
testContext
,
podA
.
Name
)
table
:=
map
[
string
]
struct
{
if
err
!=
nil
{
existing
tools
.
EtcdResponseWithError
t
.
Errorf
(
"Unexpected error: %v"
,
err
)
expect
tools
.
EtcdResponseWithError
toCreate
runtime
.
Object
objOK
func
(
obj
runtime
.
Object
)
bool
errOK
func
(
error
)
bool
}{
"normal"
:
{
existing
:
emptyNode
,
toCreate
:
podA
,
objOK
:
hasCreated
(
t
,
podA
),
errOK
:
func
(
err
error
)
bool
{
return
err
==
nil
},
},
"preExisting"
:
{
existing
:
nodeWithPodA
,
expect
:
nodeWithPodA
,
toCreate
:
podB
,
errOK
:
errors
.
IsAlreadyExists
,
},
}
}
for
name
,
item
:=
range
table
{
// verify objects are equal
fakeClient
,
registry
:=
NewTestGenericEtcdRegistry
(
t
)
if
e
,
a
:=
objA
,
checkobj
;
!
reflect
.
DeepEqual
(
e
,
a
)
{
path
:=
etcdtest
.
AddPrefix
(
"pods/foo"
)
t
.
Errorf
(
"Expected %#v, got %#v"
,
e
,
a
)
fakeClient
.
Data
[
path
]
=
item
.
existing
}
obj
,
err
:=
registry
.
Create
(
testContext
,
item
.
toCreate
)
if
!
item
.
errOK
(
err
)
{
t
.
Errorf
(
"%v: unexpected error: %v"
,
name
,
err
)
}
actual
:=
fakeClient
.
Data
[
path
]
// now try to create the second pod
if
item
.
objOK
!=
nil
{
_
,
err
=
registry
.
Create
(
testContext
,
podB
)
if
!
item
.
objOK
(
obj
)
{
if
!
errors
.
IsAlreadyExists
(
err
)
{
t
.
Errorf
(
"%v: unexpected returned: %v"
,
name
,
obj
)
t
.
Errorf
(
"Unexpected error: %v"
,
err
)
}
actualObj
,
err
:=
api
.
Scheme
.
Decode
([]
byte
(
actual
.
R
.
Node
.
Value
))
if
err
!=
nil
{
t
.
Errorf
(
"unable to decode stored value for %#v"
,
actual
)
continue
}
if
!
item
.
objOK
(
actualObj
)
{
t
.
Errorf
(
"%v: unexpected response: %v"
,
name
,
actual
)
}
}
else
{
if
e
,
a
:=
item
.
expect
,
actual
;
!
api
.
Semantic
.
DeepDerivative
(
e
,
a
)
{
t
.
Errorf
(
"%v:
\n
%s"
,
name
,
util
.
ObjectDiff
(
e
,
a
))
}
}
}
}
}
}
func
podCopy
(
in
*
api
.
Pod
)
*
api
.
Pod
{
func
updateAndVerify
(
t
*
testing
.
T
,
ctx
api
.
Context
,
registry
*
Etcd
,
pod
*
api
.
Pod
)
bool
{
out
:=
*
in
obj
,
_
,
err
:=
registry
.
Update
(
ctx
,
pod
)
return
&
out
if
err
!=
nil
{
t
.
Errorf
(
"Unexpected error: %v"
,
err
)
return
false
}
checkObj
,
err
:=
registry
.
Get
(
ctx
,
pod
.
Name
)
if
err
!=
nil
{
t
.
Errorf
(
"Unexpected error: %v"
,
err
)
return
false
}
if
e
,
a
:=
obj
,
checkObj
;
!
reflect
.
DeepEqual
(
e
,
a
)
{
t
.
Errorf
(
"Expected %#v, got %#v"
,
e
,
a
)
return
false
}
return
true
}
}
func
TestEtcdUpdate
(
t
*
testing
.
T
)
{
func
TestEtcdUpdate
(
t
*
testing
.
T
)
{
...
@@ -343,254 +262,106 @@ func TestEtcdUpdate(t *testing.T) {
...
@@ -343,254 +262,106 @@ func TestEtcdUpdate(t *testing.T) {
Spec
:
api
.
PodSpec
{
NodeName
:
"machine"
},
Spec
:
api
.
PodSpec
{
NodeName
:
"machine"
},
}
}
podB
:=
&
api
.
Pod
{
podB
:=
&
api
.
Pod
{
ObjectMeta
:
api
.
ObjectMeta
{
Name
:
"foo"
,
Namespace
:
"test"
,
ResourceVersion
:
"1"
},
ObjectMeta
:
api
.
ObjectMeta
{
Name
:
"foo"
,
Namespace
:
"test"
},
Spec
:
api
.
PodSpec
{
NodeName
:
"machine2"
},
Spec
:
api
.
PodSpec
{
NodeName
:
"machine2"
},
}
}
podAWithResourceVersion
:=
&
api
.
Pod
{
podAWithResourceVersion
:=
&
api
.
Pod
{
ObjectMeta
:
api
.
ObjectMeta
{
Name
:
"foo"
,
Namespace
:
"test"
,
ResourceVersion
:
"
3
"
},
ObjectMeta
:
api
.
ObjectMeta
{
Name
:
"foo"
,
Namespace
:
"test"
,
ResourceVersion
:
"
7
"
},
Spec
:
api
.
PodSpec
{
NodeName
:
"machine"
},
Spec
:
api
.
PodSpec
{
NodeName
:
"machine"
},
}
}
nodeWithPodA
:=
tools
.
EtcdResponseWithError
{
R
:
&
etcd
.
Response
{
Node
:
&
etcd
.
Node
{
Value
:
runtime
.
EncodeOrDie
(
testapi
.
Default
.
Codec
(),
podA
),
ModifiedIndex
:
1
,
CreatedIndex
:
1
,
},
},
E
:
nil
,
}
newerNodeWithPodA
:=
tools
.
EtcdResponseWithError
{
testContext
:=
api
.
WithNamespace
(
api
.
NewContext
(),
"test"
)
R
:
&
etcd
.
Response
{
server
,
registry
:=
NewTestGenericEtcdRegistry
(
t
)
Node
:
&
etcd
.
Node
{
defer
server
.
Terminate
(
t
)
Value
:
runtime
.
EncodeOrDie
(
testapi
.
Default
.
Codec
(),
podA
),
ModifiedIndex
:
2
,
CreatedIndex
:
1
,
},
},
E
:
nil
,
}
nodeWithPodB
:=
tools
.
EtcdResponseWithError
{
// Test1 try to update a non-existing node
R
:
&
etcd
.
Response
{
_
,
_
,
err
:=
registry
.
Update
(
testContext
,
podA
)
Node
:
&
etcd
.
Node
{
if
!
errors
.
IsNotFound
(
err
)
{
Value
:
runtime
.
EncodeOrDie
(
testapi
.
Default
.
Codec
(),
podB
),
t
.
Errorf
(
"Unexpected error: %v"
,
err
)
ModifiedIndex
:
1
,
CreatedIndex
:
1
,
},
},
E
:
nil
,
}
}
nodeWithPodAWithResourceVersion
:=
tools
.
EtcdResponseWithError
{
// Test2 createIfNotFound and verify
R
:
&
etcd
.
Response
{
registry
.
UpdateStrategy
.
(
*
testRESTStrategy
)
.
allowCreateOnUpdate
=
true
Node
:
&
etcd
.
Node
{
if
!
updateAndVerify
(
t
,
testContext
,
registry
,
podA
)
{
Value
:
runtime
.
EncodeOrDie
(
testapi
.
Default
.
Codec
(),
podAWithResourceVersion
),
t
.
Errorf
(
"Unexpected error updating podA"
)
ModifiedIndex
:
3
,
CreatedIndex
:
1
,
},
},
E
:
nil
,
}
emptyNode
:=
tools
.
EtcdResponseWithError
{
R
:
&
etcd
.
Response
{},
E
:
tools
.
EtcdErrorNotFound
,
}
}
registry
.
UpdateStrategy
.
(
*
testRESTStrategy
)
.
allowCreateOnUpdate
=
false
testContext
:=
api
.
WithNamespace
(
api
.
NewContext
(),
"test"
)
// Test3 outofDate
_
,
_
,
err
=
registry
.
Update
(
testContext
,
podAWithResourceVersion
)
if
!
errors
.
IsConflict
(
err
)
{
t
.
Errorf
(
"Unexpected error: %v"
,
err
)
}
table
:=
map
[
string
]
struct
{
// Test4 normal update and verify
existing
tools
.
EtcdResponseWithError
if
!
updateAndVerify
(
t
,
testContext
,
registry
,
podB
)
{
expect
tools
.
EtcdResponseWithError
t
.
Errorf
(
"Unexpected error updating podB"
)
toUpdate
runtime
.
Object
allowCreate
bool
allowUnconditionalUpdate
bool
objOK
func
(
obj
runtime
.
Object
)
bool
errOK
func
(
error
)
bool
}{
"normal"
:
{
existing
:
nodeWithPodA
,
expect
:
nodeWithPodB
,
toUpdate
:
podCopy
(
podB
),
errOK
:
func
(
err
error
)
bool
{
return
err
==
nil
},
},
"notExisting"
:
{
existing
:
emptyNode
,
expect
:
emptyNode
,
toUpdate
:
podCopy
(
podA
),
errOK
:
func
(
err
error
)
bool
{
return
errors
.
IsNotFound
(
err
)
},
},
"createIfNotFound"
:
{
existing
:
emptyNode
,
toUpdate
:
podCopy
(
podA
),
allowCreate
:
true
,
objOK
:
hasCreated
(
t
,
podA
),
errOK
:
func
(
err
error
)
bool
{
return
err
==
nil
},
},
"outOfDate"
:
{
existing
:
newerNodeWithPodA
,
expect
:
newerNodeWithPodA
,
toUpdate
:
podCopy
(
podB
),
errOK
:
func
(
err
error
)
bool
{
return
errors
.
IsConflict
(
err
)
},
},
"unconditionalUpdate"
:
{
existing
:
nodeWithPodAWithResourceVersion
,
allowUnconditionalUpdate
:
true
,
toUpdate
:
podCopy
(
podA
),
objOK
:
func
(
obj
runtime
.
Object
)
bool
{
return
true
},
errOK
:
func
(
err
error
)
bool
{
return
err
==
nil
},
},
}
}
for
name
,
item
:=
range
table
{
// Test5 unconditional update
fakeClient
,
registry
:=
NewTestGenericEtcdRegistry
(
t
)
// NOTE: The logic for unconditional updates doesn't make sense to me, and imho should be removed.
registry
.
UpdateStrategy
.
(
*
testRESTStrategy
)
.
allowCreateOnUpdate
=
item
.
allowCreate
// doUnconditionalUpdate := resourceVersion == 0 && e.UpdateStrategy.AllowUnconditionalUpdate()
registry
.
UpdateStrategy
.
(
*
testRESTStrategy
)
.
allowUnconditionalUpdate
=
item
.
allowUnconditionalUpdate
// ^^ That condition can *never be true due to the creation of root objects.
path
:=
etcdtest
.
AddPrefix
(
"pods/foo"
)
//
fakeClient
.
Data
[
path
]
=
item
.
existing
// registry.UpdateStrategy.(*testRESTStrategy).allowUnconditionalUpdate = true
obj
,
_
,
err
:=
registry
.
Update
(
testContext
,
item
.
toUpdate
)
// updateAndVerify(t, testContext, registry, podAWithResourceVersion)
if
!
item
.
errOK
(
err
)
{
t
.
Errorf
(
"%v: unexpected error: %v"
,
name
,
err
)
}
actual
:=
fakeClient
.
Data
[
path
]
if
item
.
objOK
!=
nil
{
if
!
item
.
objOK
(
obj
)
{
t
.
Errorf
(
"%v: unexpected returned: %#v"
,
name
,
obj
)
}
actualObj
,
err
:=
api
.
Scheme
.
Decode
([]
byte
(
actual
.
R
.
Node
.
Value
))
if
err
!=
nil
{
t
.
Errorf
(
"unable to decode stored value for %#v"
,
actual
)
continue
}
if
!
item
.
objOK
(
actualObj
)
{
t
.
Errorf
(
"%v: unexpected response: %#v"
,
name
,
actual
)
}
}
else
{
if
e
,
a
:=
item
.
expect
,
actual
;
!
api
.
Semantic
.
DeepDerivative
(
e
,
a
)
{
t
.
Errorf
(
"%v:
\n
%s"
,
name
,
util
.
ObjectDiff
(
e
,
a
))
}
}
}
}
}
func
TestEtcdGet
(
t
*
testing
.
T
)
{
func
TestEtcdGet
(
t
*
testing
.
T
)
{
podA
:=
&
api
.
Pod
{
podA
:=
&
api
.
Pod
{
ObjectMeta
:
api
.
ObjectMeta
{
Namespace
:
"test"
,
Name
:
"foo"
,
ResourceVersion
:
"1"
},
ObjectMeta
:
api
.
ObjectMeta
{
Namespace
:
"test"
,
Name
:
"foo"
},
Spec
:
api
.
PodSpec
{
NodeName
:
"machine"
},
Spec
:
api
.
PodSpec
{
NodeName
:
"machine"
},
}
}
nodeWithPodA
:=
tools
.
EtcdResponseWithError
{
testContext
:=
api
.
WithNamespace
(
api
.
NewContext
(),
"test"
)
R
:
&
etcd
.
Response
{
server
,
registry
:=
NewTestGenericEtcdRegistry
(
t
)
Node
:
&
etcd
.
Node
{
defer
server
.
Terminate
(
t
)
Value
:
runtime
.
EncodeOrDie
(
testapi
.
Default
.
Codec
(),
podA
),
ModifiedIndex
:
1
,
CreatedIndex
:
1
,
},
},
E
:
nil
,
}
emptyNode
:=
tools
.
EtcdResponseWithError
{
_
,
err
:=
registry
.
Get
(
testContext
,
podA
.
Name
)
R
:
&
etcd
.
Response
{},
if
!
errors
.
IsNotFound
(
err
)
{
E
:
tools
.
EtcdErrorNotFound
,
t
.
Errorf
(
"Unexpected error: %v"
,
err
)
}
}
key
:=
"foo"
registry
.
UpdateStrategy
.
(
*
testRESTStrategy
)
.
allowCreateOnUpdate
=
true
if
!
updateAndVerify
(
t
,
testContext
,
registry
,
podA
)
{
table
:=
map
[
string
]
struct
{
t
.
Errorf
(
"Unexpected error updating podA"
)
existing
tools
.
EtcdResponseWithError
expect
runtime
.
Object
errOK
func
(
error
)
bool
}{
"normal"
:
{
existing
:
nodeWithPodA
,
expect
:
podA
,
errOK
:
func
(
err
error
)
bool
{
return
err
==
nil
},
},
"notExisting"
:
{
existing
:
emptyNode
,
expect
:
nil
,
errOK
:
errors
.
IsNotFound
,
},
}
}
testContext
:=
api
.
WithNamespace
(
api
.
NewContext
(),
"test"
)
for
name
,
item
:=
range
table
{
fakeClient
,
registry
:=
NewTestGenericEtcdRegistry
(
t
)
path
:=
etcdtest
.
AddPrefix
(
"pods/foo"
)
fakeClient
.
Data
[
path
]
=
item
.
existing
got
,
err
:=
registry
.
Get
(
testContext
,
key
)
if
!
item
.
errOK
(
err
)
{
t
.
Errorf
(
"%v: unexpected error: %v"
,
name
,
err
)
}
if
e
,
a
:=
item
.
expect
,
got
;
!
api
.
Semantic
.
DeepDerivative
(
e
,
a
)
{
t
.
Errorf
(
"%v:
\n
%s"
,
name
,
util
.
ObjectDiff
(
e
,
a
))
}
}
}
}
func
TestEtcdDelete
(
t
*
testing
.
T
)
{
func
TestEtcdDelete
(
t
*
testing
.
T
)
{
podA
:=
&
api
.
Pod
{
podA
:=
&
api
.
Pod
{
ObjectMeta
:
api
.
ObjectMeta
{
Name
:
"foo"
,
ResourceVersion
:
"1"
},
ObjectMeta
:
api
.
ObjectMeta
{
Name
:
"foo"
},
Spec
:
api
.
PodSpec
{
NodeName
:
"machine"
},
Spec
:
api
.
PodSpec
{
NodeName
:
"machine"
},
}
}
nodeWithPodA
:=
tools
.
EtcdResponseWithError
{
R
:
&
etcd
.
Response
{
Node
:
&
etcd
.
Node
{
Value
:
runtime
.
EncodeOrDie
(
testapi
.
Default
.
Codec
(),
podA
),
ModifiedIndex
:
1
,
CreatedIndex
:
1
,
},
},
E
:
nil
,
}
emptyNode
:=
tools
.
EtcdResponseWithError
{
R
:
&
etcd
.
Response
{},
E
:
tools
.
EtcdErrorNotFound
,
}
testContext
:=
api
.
WithNamespace
(
api
.
NewContext
(),
"test"
)
testContext
:=
api
.
WithNamespace
(
api
.
NewContext
(),
"test"
)
server
,
registry
:=
NewTestGenericEtcdRegistry
(
t
)
defer
server
.
Terminate
(
t
)
key
:=
"foo"
// test failure condition
_
,
err
:=
registry
.
Delete
(
testContext
,
podA
.
Name
,
nil
)
if
!
errors
.
IsNotFound
(
err
)
{
t
.
Errorf
(
"Unexpected error: %v"
,
err
)
}
table
:=
map
[
string
]
struct
{
// create pod
existing
tools
.
EtcdResponseWithError
_
,
err
=
registry
.
Create
(
testContext
,
podA
)
expect
tools
.
EtcdResponseWithError
if
err
!=
nil
{
errOK
func
(
error
)
bool
t
.
Errorf
(
"Unexpected error: %v"
,
err
)
}{
"normal"
:
{
existing
:
nodeWithPodA
,
expect
:
emptyNode
,
errOK
:
func
(
err
error
)
bool
{
return
err
==
nil
},
},
"notExisting"
:
{
existing
:
emptyNode
,
expect
:
emptyNode
,
errOK
:
func
(
err
error
)
bool
{
return
errors
.
IsNotFound
(
err
)
},
},
}
}
for
name
,
item
:=
range
table
{
// delete object
fakeClient
,
registry
:=
NewTestGenericEtcdRegistry
(
t
)
_
,
err
=
registry
.
Delete
(
testContext
,
podA
.
Name
,
nil
)
path
:=
etcdtest
.
AddPrefix
(
"pods/foo"
)
if
err
!=
nil
{
fakeClient
.
Data
[
path
]
=
item
.
existing
t
.
Errorf
(
"Unexpected error: %v"
,
err
)
obj
,
err
:=
registry
.
Delete
(
testContext
,
key
,
nil
)
}
if
!
item
.
errOK
(
err
)
{
t
.
Errorf
(
"%v: unexpected error: %v (%#v)"
,
name
,
err
,
obj
)
}
if
item
.
expect
.
E
!=
nil
{
// try to get a item which should be deleted
item
.
expect
.
E
.
(
*
etcd
.
EtcdError
)
.
Index
=
fakeClient
.
ChangeIndex
_
,
err
=
registry
.
Get
(
testContext
,
podA
.
Name
)
}
if
!
errors
.
IsNotFound
(
err
)
{
if
e
,
a
:=
item
.
expect
,
fakeClient
.
Data
[
path
];
!
api
.
Semantic
.
DeepDerivative
(
e
,
a
)
{
t
.
Errorf
(
"Unexpected error: %v"
,
err
)
t
.
Errorf
(
"%v:
\n
%s"
,
name
,
util
.
ObjectDiff
(
e
,
a
))
}
}
}
}
}
...
@@ -621,42 +392,30 @@ func TestEtcdWatch(t *testing.T) {
...
@@ -621,42 +392,30 @@ func TestEtcdWatch(t *testing.T) {
}
}
podA
:=
&
api
.
Pod
{
podA
:=
&
api
.
Pod
{
ObjectMeta
:
api
.
ObjectMeta
{
ObjectMeta
:
api
.
ObjectMeta
{
Name
:
"foo"
,
Name
:
"foo"
,
Namespace
:
"test"
,
Namespace
:
"test"
,
ResourceVersion
:
"1"
,
},
},
Spec
:
api
.
PodSpec
{
NodeName
:
"machine"
},
Spec
:
api
.
PodSpec
{
NodeName
:
"machine"
},
}
}
respWithPodA
:=
&
etcd
.
Response
{
Node
:
&
etcd
.
Node
{
Key
:
"/registry/pods/test/foo"
,
Value
:
runtime
.
EncodeOrDie
(
testapi
.
Default
.
Codec
(),
podA
),
ModifiedIndex
:
1
,
CreatedIndex
:
1
,
},
Action
:
"create"
,
}
fakeClient
,
registry
:=
NewTestGenericEtcdRegistry
(
t
)
server
,
registry
:=
NewTestGenericEtcdRegistry
(
t
)
wi
,
err
:=
registry
.
WatchPredicate
(
ctx
,
m
,
"
1
"
)
wi
,
err
:=
registry
.
WatchPredicate
(
ctx
,
m
,
"
0
"
)
if
err
!=
nil
{
if
err
!=
nil
{
t
.
Errorf
(
"%v: unexpected error: %v"
,
name
,
err
)
t
.
Errorf
(
"%v: unexpected error: %v"
,
name
,
err
)
continue
}
else
{
}
obj
,
err
:=
registry
.
Create
(
testContext
,
podA
)
fakeClient
.
WaitForWatchCompletion
()
if
err
!=
nil
{
got
,
open
:=
<-
wi
.
ResultChan
()
go
func
()
{
if
!
open
{
fakeClient
.
WatchResponse
<-
respWithPodA
t
.
Errorf
(
"%v: unexpected channel close"
,
name
)
}()
}
else
{
if
e
,
a
:=
obj
,
got
.
Object
;
!
reflect
.
DeepEqual
(
e
,
a
)
{
got
,
open
:=
<-
wi
.
ResultChan
(
)
t
.
Errorf
(
"Expected %#v, got %#v"
,
e
,
a
)
if
!
open
{
}
t
.
Errorf
(
"%v: unexpected channel close"
,
name
)
}
continue
}
}
}
if
e
,
a
:=
podA
,
got
.
Object
;
!
api
.
Semantic
.
DeepDerivative
(
e
,
a
)
{
server
.
Terminate
(
t
)
t
.
Errorf
(
"%v: difference: %s"
,
name
,
util
.
ObjectDiff
(
e
,
a
))
}
}
}
}
}
pkg/storage/testing/utils.go
0 → 100644
View file @
f6f2f41a
/*
Copyright 2015 The Kubernetes Authors All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package
testing
import
(
"path"
"testing"
"golang.org/x/net/context"
"k8s.io/kubernetes/pkg/api/meta"
"k8s.io/kubernetes/pkg/runtime"
"k8s.io/kubernetes/pkg/storage"
)
// CreateObj will create a single object using the storage interface
func
CreateObj
(
t
*
testing
.
T
,
helper
storage
.
Interface
,
name
string
,
obj
,
out
runtime
.
Object
,
ttl
uint64
)
error
{
err
:=
helper
.
Set
(
context
.
TODO
(),
name
,
obj
,
out
,
ttl
)
if
err
!=
nil
{
t
.
Errorf
(
"Unexpected error %v"
,
err
)
}
return
err
}
// CreateList will properly create a list using the storage interface
func
CreateList
(
t
*
testing
.
T
,
prefix
string
,
helper
storage
.
Interface
,
list
runtime
.
Object
)
error
{
items
,
err
:=
runtime
.
ExtractList
(
list
)
if
err
!=
nil
{
return
err
}
for
i
:=
range
items
{
obj
:=
items
[
i
]
meta
,
err
:=
meta
.
Accessor
(
obj
)
if
err
!=
nil
{
return
err
}
err
=
CreateObj
(
t
,
helper
,
path
.
Join
(
prefix
,
meta
.
Name
()),
obj
,
obj
,
0
)
if
err
!=
nil
{
return
err
}
items
[
i
]
=
obj
}
return
runtime
.
SetList
(
list
,
items
)
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment