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
Show whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
193 additions
and
375 deletions
+193
-375
etcd.go
pkg/registry/generic/etcd/etcd.go
+2
-0
etcd_test.go
pkg/registry/generic/etcd/etcd_test.go
+134
-375
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
{},
E
:
tools
.
EtcdErrorNotFound
,
},
m
:
everythingMatcher
{},
m
:
everythingMatcher
{},
out
:
&
api
.
PodList
{
Items
:
[]
api
.
Pod
{}},
out
:
&
api
.
PodList
{
Items
:
[]
api
.
Pod
{}},
succeed
:
true
,
},
},
"normal"
:
{
"normal"
:
{
in
:
tools
.
EtcdResponseWithError
{
in
:
&
api
.
PodList
{
Items
:
[]
api
.
Pod
{
*
podA
,
*
podB
}},
R
:
normalListResp
,
E
:
nil
,
},
m
:
everythingMatcher
{},
m
:
everythingMatcher
{},
out
:
&
api
.
PodList
{
Items
:
[]
api
.
Pod
{
*
podA
,
*
podB
}},
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
,
E
:
nil
,
},
m
:
setMatcher
{
sets
.
NewString
(
"foo"
)},
m
:
setMatcher
{
sets
.
NewString
(
"foo"
)},
out
:
&
api
.
PodList
{
Items
:
[]
api
.
Pod
{
*
podA
}},
out
:
&
api
.
PodList
{
Items
:
[]
api
.
Pod
{
*
podB
}},
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
,
E
:
nil
,
},
m
:
setMatcher
{
sets
.
NewString
(
"foo"
,
"makeMatchSingleReturnFalse"
)},
m
:
setMatcher
{
sets
.
NewString
(
"foo"
,
"makeMatchSingleReturnFalse"
)},
out
:
&
api
.
PodList
{
Items
:
[]
api
.
Pod
{
*
podA
}},
out
:
&
api
.
PodList
{
Items
:
[]
api
.
Pod
{
*
podB
}},
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
))
}
func
updateAndVerify
(
t
*
testing
.
T
,
ctx
api
.
Context
,
registry
*
Etcd
,
pod
*
api
.
Pod
)
bool
{
obj
,
_
,
err
:=
registry
.
Update
(
ctx
,
pod
)
if
err
!=
nil
{
if
err
!=
nil
{
t
.
Errorf
(
"unable to decode stored value for %#v"
,
actual
)
t
.
Errorf
(
"Unexpected error: %v"
,
err
)
continue
return
false
}
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
))
}
}
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
podCopy
(
in
*
api
.
Pod
)
*
api
.
Pod
{
out
:=
*
in
return
&
out
}
}
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
{
registry
.
UpdateStrategy
.
(
*
testRESTStrategy
)
.
allowCreateOnUpdate
=
false
R
:
&
etcd
.
Response
{},
E
:
tools
.
EtcdErrorNotFound
,
}
testContext
:=
api
.
WithNamespace
(
api
.
NewContext
(),
"test"
)
table
:=
map
[
string
]
struct
{
// Test3 outofDate
existing
tools
.
EtcdResponseWithError
_
,
_
,
err
=
registry
.
Update
(
testContext
,
podAWithResourceVersion
)
expect
tools
.
EtcdResponseWithError
if
!
errors
.
IsConflict
(
err
)
{
toUpdate
runtime
.
Object
t
.
Errorf
(
"Unexpected error: %v"
,
err
)
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
{
// Test4 normal update and verify
fakeClient
,
registry
:=
NewTestGenericEtcdRegistry
(
t
)
if
!
updateAndVerify
(
t
,
testContext
,
registry
,
podB
)
{
registry
.
UpdateStrategy
.
(
*
testRESTStrategy
)
.
allowCreateOnUpdate
=
item
.
allowCreate
t
.
Errorf
(
"Unexpected error updating podB"
)
registry
.
UpdateStrategy
.
(
*
testRESTStrategy
)
.
allowUnconditionalUpdate
=
item
.
allowUnconditionalUpdate
path
:=
etcdtest
.
AddPrefix
(
"pods/foo"
)
fakeClient
.
Data
[
path
]
=
item
.
existing
obj
,
_
,
err
:=
registry
.
Update
(
testContext
,
item
.
toUpdate
)
if
!
item
.
errOK
(
err
)
{
t
.
Errorf
(
"%v: unexpected error: %v"
,
name
,
err
)
}
}
actual
:=
fakeClient
.
Data
[
path
]
// Test5 unconditional update
if
item
.
objOK
!=
nil
{
// NOTE: The logic for unconditional updates doesn't make sense to me, and imho should be removed.
if
!
item
.
objOK
(
obj
)
{
// doUnconditionalUpdate := resourceVersion == 0 && e.UpdateStrategy.AllowUnconditionalUpdate()
t
.
Errorf
(
"%v: unexpected returned: %#v"
,
name
,
obj
)
// ^^ That condition can *never be true due to the creation of root objects.
}
//
actualObj
,
err
:=
api
.
Scheme
.
Decode
([]
byte
(
actual
.
R
.
Node
.
Value
))
// registry.UpdateStrategy.(*testRESTStrategy).allowUnconditionalUpdate = true
if
err
!=
nil
{
// updateAndVerify(t, testContext, registry, podAWithResourceVersion)
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
{
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
,
}
key
:=
"foo"
table
:=
map
[
string
]
struct
{
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"
)
testContext
:=
api
.
WithNamespace
(
api
.
NewContext
(),
"test"
)
server
,
registry
:=
NewTestGenericEtcdRegistry
(
t
)
defer
server
.
Terminate
(
t
)
for
name
,
item
:=
range
table
{
_
,
err
:=
registry
.
Get
(
testContext
,
podA
.
Name
)
fakeClient
,
registry
:=
NewTestGenericEtcdRegistry
(
t
)
if
!
errors
.
IsNotFound
(
err
)
{
path
:=
etcdtest
.
AddPrefix
(
"pods/foo"
)
t
.
Errorf
(
"Unexpected error: %v"
,
err
)
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
)
{
registry
.
UpdateStrategy
.
(
*
testRESTStrategy
)
.
allowCreateOnUpdate
=
true
t
.
Errorf
(
"%v:
\n
%s"
,
name
,
util
.
ObjectDiff
(
e
,
a
))
if
!
updateAndVerify
(
t
,
testContext
,
registry
,
podA
)
{
}
t
.
Errorf
(
"Unexpected error updating podA"
)
}
}
}
}
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
)
table
:=
map
[
string
]
struct
{
if
!
errors
.
IsNotFound
(
err
)
{
existing
tools
.
EtcdResponseWithError
t
.
Errorf
(
"Unexpected error: %v"
,
err
)
expect
tools
.
EtcdResponseWithError
errOK
func
(
error
)
bool
}{
"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
{
// create pod
fakeClient
,
registry
:=
NewTestGenericEtcdRegistry
(
t
)
_
,
err
=
registry
.
Create
(
testContext
,
podA
)
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
{
// delete object
item
.
expect
.
E
.
(
*
etcd
.
EtcdError
)
.
Index
=
fakeClient
.
ChangeIndex
_
,
err
=
registry
.
Delete
(
testContext
,
podA
.
Name
,
nil
)
}
if
err
!=
nil
{
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
))
}
}
// try to get a item which should be deleted
_
,
err
=
registry
.
Get
(
testContext
,
podA
.
Name
)
if
!
errors
.
IsNotFound
(
err
)
{
t
.
Errorf
(
"Unexpected error: %v"
,
err
)
}
}
}
}
...
@@ -623,40 +394,28 @@ func TestEtcdWatch(t *testing.T) {
...
@@ -623,40 +394,28 @@ func TestEtcdWatch(t *testing.T) {
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
{
go
func
()
{
fakeClient
.
WatchResponse
<-
respWithPodA
}()
got
,
open
:=
<-
wi
.
ResultChan
()
got
,
open
:=
<-
wi
.
ResultChan
()
if
!
open
{
if
!
open
{
t
.
Errorf
(
"%v: unexpected channel close"
,
name
)
t
.
Errorf
(
"%v: unexpected channel close"
,
name
)
continue
}
else
{
if
e
,
a
:=
obj
,
got
.
Object
;
!
reflect
.
DeepEqual
(
e
,
a
)
{
t
.
Errorf
(
"Expected %#v, got %#v"
,
e
,
a
)
}
}
}
if
e
,
a
:=
podA
,
got
.
Object
;
!
api
.
Semantic
.
DeepDerivative
(
e
,
a
)
{
t
.
Errorf
(
"%v: difference: %s"
,
name
,
util
.
ObjectDiff
(
e
,
a
))
}
}
}
}
server
.
Terminate
(
t
)
}
}
}
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