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
8e91097f
Commit
8e91097f
authored
Apr 03, 2015
by
Brian Grant
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #6423 from lavalamp/fix
Fix incorrect reference to name in v1beta3 API.
parents
e4c91df3
34b399ca
Hide whitespace changes
Inline
Side-by-side
Showing
16 changed files
with
290 additions
and
183 deletions
+290
-183
conversion.go
pkg/api/v1beta1/conversion.go
+3
-3
conversion.go
pkg/api/v1beta2/conversion.go
+3
-3
conversion.go
pkg/api/v1beta3/conversion.go
+5
-6
store.go
pkg/client/cache/store.go
+2
-1
etcd_test.go
pkg/registry/controller/etcd/etcd_test.go
+6
-5
rest.go
pkg/registry/controller/rest.go
+12
-10
etcd.go
pkg/registry/generic/etcd/etcd.go
+19
-20
etcd_test.go
pkg/registry/generic/etcd/etcd_test.go
+66
-36
registry.go
pkg/registry/generic/registry.go
+56
-3
registry_test.go
pkg/registry/generic/registry_test.go
+40
-10
etcd.go
pkg/registry/minion/etcd/etcd.go
+2
-8
etcd_test.go
pkg/registry/minion/etcd/etcd_test.go
+0
-53
rest.go
pkg/registry/minion/rest.go
+14
-11
rest_test.go
pkg/registry/minion/rest_test.go
+45
-0
etcd_test.go
pkg/registry/pod/etcd/etcd_test.go
+1
-1
rest.go
pkg/registry/pod/rest.go
+16
-13
No files found.
pkg/api/v1beta1/conversion.go
View file @
8e91097f
...
...
@@ -1534,7 +1534,7 @@ func init() {
func
(
label
,
value
string
)
(
string
,
string
,
error
)
{
switch
label
{
case
"name"
:
return
"name"
,
value
,
nil
return
"
metadata.
name"
,
value
,
nil
case
"DesiredState.Host"
:
return
"spec.host"
,
value
,
nil
case
"DesiredState.Status"
:
...
...
@@ -1554,7 +1554,7 @@ func init() {
func
(
label
,
value
string
)
(
string
,
string
,
error
)
{
switch
label
{
case
"name"
:
return
"name"
,
value
,
nil
return
"
metadata.
name"
,
value
,
nil
default
:
return
""
,
""
,
fmt
.
Errorf
(
"field label not supported: %s"
,
label
)
}
...
...
@@ -1567,7 +1567,7 @@ func init() {
func
(
label
,
value
string
)
(
string
,
string
,
error
)
{
switch
label
{
case
"name"
:
return
"name"
,
value
,
nil
return
"
metadata.
name"
,
value
,
nil
case
"currentState.replicas"
:
return
"status.replicas"
,
value
,
nil
default
:
...
...
pkg/api/v1beta2/conversion.go
View file @
8e91097f
...
...
@@ -1459,7 +1459,7 @@ func init() {
func
(
label
,
value
string
)
(
string
,
string
,
error
)
{
switch
label
{
case
"name"
:
return
"name"
,
value
,
nil
return
"
metadata.
name"
,
value
,
nil
case
"DesiredState.Host"
:
return
"spec.host"
,
value
,
nil
case
"DesiredState.Status"
:
...
...
@@ -1479,7 +1479,7 @@ func init() {
func
(
label
,
value
string
)
(
string
,
string
,
error
)
{
switch
label
{
case
"name"
:
return
"name"
,
value
,
nil
return
"
metadata.
name"
,
value
,
nil
default
:
return
""
,
""
,
fmt
.
Errorf
(
"field label not supported: %s"
,
label
)
}
...
...
@@ -1492,7 +1492,7 @@ func init() {
func
(
label
,
value
string
)
(
string
,
string
,
error
)
{
switch
label
{
case
"name"
:
return
"name"
,
value
,
nil
return
"
metadata.
name"
,
value
,
nil
case
"currentState.replicas"
:
return
"status.replicas"
,
value
,
nil
default
:
...
...
pkg/api/v1beta3/conversion.go
View file @
8e91097f
...
...
@@ -27,7 +27,7 @@ func init() {
err
:=
newer
.
Scheme
.
AddFieldLabelConversionFunc
(
"v1beta3"
,
"Pod"
,
func
(
label
,
value
string
)
(
string
,
string
,
error
)
{
switch
label
{
case
"name"
,
case
"
metadata.
name"
,
"status.phase"
,
"spec.host"
:
return
label
,
value
,
nil
...
...
@@ -42,7 +42,7 @@ func init() {
err
=
newer
.
Scheme
.
AddFieldLabelConversionFunc
(
"v1beta3"
,
"Node"
,
func
(
label
,
value
string
)
(
string
,
string
,
error
)
{
switch
label
{
case
"name"
:
case
"
metadata.
name"
:
return
label
,
value
,
nil
default
:
return
""
,
""
,
fmt
.
Errorf
(
"field label not supported: %s"
,
label
)
...
...
@@ -55,10 +55,9 @@ func init() {
err
=
newer
.
Scheme
.
AddFieldLabelConversionFunc
(
"v1beta3"
,
"ReplicationController"
,
func
(
label
,
value
string
)
(
string
,
string
,
error
)
{
switch
label
{
case
"name"
:
return
"name"
,
value
,
nil
case
"status.replicas"
:
return
"status.replicas"
,
value
,
nil
case
"metadata.name"
,
"status.replicas"
:
return
label
,
value
,
nil
default
:
return
""
,
""
,
fmt
.
Errorf
(
"field label not supported: %s"
,
label
)
}
...
...
pkg/client/cache/store.go
View file @
8e91097f
...
...
@@ -63,7 +63,8 @@ func (k KeyError) Error() string {
// MetaNamespaceKeyFunc is a convenient default KeyFunc which knows how to make
// keys for API objects which implement meta.Interface.
// The key uses the format: <namespace>/<name>
// The key uses the format <namespace>/<name> unless <namespace> is empty, then
// it's just <name>.
func
MetaNamespaceKeyFunc
(
obj
interface
{})
(
string
,
error
)
{
meta
,
err
:=
meta
.
Accessor
(
obj
)
if
err
!=
nil
{
...
...
pkg/registry/controller/etcd/etcd_test.go
View file @
8e91097f
...
...
@@ -544,14 +544,15 @@ func TestEtcdWatchControllersFields(t *testing.T) {
testFieldMap
:=
map
[
int
][]
fields
.
Set
{
PASS
:
{
{
"status.replicas"
:
"0"
},
{
"name"
:
"foo"
},
{
"status.replicas"
:
"0"
,
"name"
:
"foo"
},
{
"
metadata.
name"
:
"foo"
},
{
"status.replicas"
:
"0"
,
"
metadata.
name"
:
"foo"
},
},
FAIL
:
{
{
"status.replicas"
:
"10"
},
{
"name"
:
"bar"
},
{
"status.replicas"
:
"10"
,
"name"
:
"foo"
},
{
"status.replicas"
:
"0"
,
"name"
:
"bar"
},
{
"metadata.name"
:
"bar"
},
{
"name"
:
"foo"
},
{
"status.replicas"
:
"10"
,
"metadata.name"
:
"foo"
},
{
"status.replicas"
:
"0"
,
"metadata.name"
:
"bar"
},
},
}
testEtcdActions
:=
[]
string
{
...
...
pkg/registry/controller/rest.go
View file @
8e91097f
...
...
@@ -75,9 +75,9 @@ func (rcStrategy) ValidateUpdate(ctx api.Context, obj, old runtime.Object) field
}
// ControllerToSelectableFields returns a label set that represents the object.
func
ControllerToSelectableFields
(
controller
*
api
.
ReplicationController
)
label
s
.
Set
{
return
label
s
.
Set
{
"
name"
:
controller
.
Name
,
func
ControllerToSelectableFields
(
controller
*
api
.
ReplicationController
)
field
s
.
Set
{
return
field
s
.
Set
{
"
metadata.name"
:
controller
.
Name
,
"status.replicas"
:
strconv
.
Itoa
(
controller
.
Status
.
Replicas
),
}
}
...
...
@@ -86,13 +86,15 @@ func ControllerToSelectableFields(controller *api.ReplicationController) labels.
// watch events from etcd to clients of the apiserver only interested in specific
// labels/fields.
func
MatchController
(
label
labels
.
Selector
,
field
fields
.
Selector
)
generic
.
Matcher
{
return
generic
.
MatcherFunc
(
func
(
obj
runtime
.
Object
)
(
bool
,
error
)
{
controllerObj
,
ok
:=
obj
.
(
*
api
.
ReplicationController
)
return
&
generic
.
SelectionPredicate
{
Label
:
label
,
Field
:
field
,
GetAttrs
:
func
(
obj
runtime
.
Object
)
(
labels
.
Set
,
fields
.
Set
,
error
)
{
rc
,
ok
:=
obj
.
(
*
api
.
ReplicationController
)
if
!
ok
{
return
false
,
fmt
.
Errorf
(
"Given object is not a replication controller."
)
return
nil
,
nil
,
fmt
.
Errorf
(
"Given object is not a replication controller."
)
}
fields
:=
ControllerToSelectableFields
(
controllerObj
)
return
label
.
Matches
(
labels
.
Set
(
controllerObj
.
Labels
))
&&
field
.
Matches
(
fields
),
nil
})
return
labels
.
Set
(
rc
.
ObjectMeta
.
Labels
),
ControllerToSelectableFields
(
rc
),
nil
},
}
}
pkg/registry/generic/etcd/etcd.go
View file @
8e91097f
...
...
@@ -62,13 +62,10 @@ type Etcd struct {
// Used for listing/watching; should not include trailing "/"
KeyRootFunc
func
(
ctx
api
.
Context
)
string
// Called for Create/Update/Get/Delete
// Called for Create/Update/Get/Delete. Note that 'namespace' can be
// gotten from ctx.
KeyFunc
func
(
ctx
api
.
Context
,
name
string
)
(
string
,
error
)
// If field.Selector of Watch contains a label with such name, this will be
// translated to watching a single object (not all objects of that type).
WatchSingleFieldName
string
// Called to get the name of an object
ObjectNameFunc
func
(
obj
runtime
.
Object
)
(
string
,
error
)
...
...
@@ -407,30 +404,32 @@ func (e *Etcd) finalizeDelete(obj runtime.Object, runHooks bool) (runtime.Object
return
&
api
.
Status
{
Status
:
api
.
StatusSuccess
},
nil
}
// WatchPredicate starts a watch for the items that m matches.
// Watch makes a matcher for the given label and field, and calls
// WatchPredicate. If possible, you should customize PredicateFunc to produre a
// matcher that matches by key.
func
(
e
*
Etcd
)
Watch
(
ctx
api
.
Context
,
label
labels
.
Selector
,
field
fields
.
Selector
,
resourceVersion
string
)
(
watch
.
Interface
,
error
)
{
if
value
,
found
:=
field
.
RequiresExactMatch
(
e
.
WatchSingleFieldName
);
found
&&
len
(
e
.
WatchSingleFieldName
)
>
0
{
key
,
err
:=
e
.
KeyFunc
(
ctx
,
value
)
if
err
!=
nil
{
return
nil
,
err
}
return
e
.
watchPredicate
(
key
,
e
.
PredicateFunc
(
label
,
field
),
resourceVersion
)
}
return
e
.
watchPredicate
(
e
.
KeyRootFunc
(
ctx
),
e
.
PredicateFunc
(
label
,
field
),
resourceVersion
)
return
e
.
WatchPredicate
(
ctx
,
e
.
PredicateFunc
(
label
,
field
),
resourceVersion
)
}
// WatchPredicate starts a watch for the items that m matches.
// TODO: Detect if m references a single object instead of a list.
func
(
e
*
Etcd
)
WatchPredicate
(
ctx
api
.
Context
,
m
generic
.
Matcher
,
resourceVersion
string
)
(
watch
.
Interface
,
error
)
{
return
e
.
watchPredicate
(
e
.
KeyRootFunc
(
ctx
),
m
,
resourceVersion
)
}
func
(
e
*
Etcd
)
watchPredicate
(
key
string
,
m
generic
.
Matcher
,
resourceVersion
string
)
(
watch
.
Interface
,
error
)
{
version
,
err
:=
tools
.
ParseWatchResourceVersion
(
resourceVersion
,
e
.
EndpointName
)
if
err
!=
nil
{
return
nil
,
err
}
return
e
.
Helper
.
WatchList
(
key
,
version
,
func
(
obj
runtime
.
Object
)
bool
{
var
watchKey
string
if
name
,
ok
:=
m
.
MatchesSingle
();
ok
{
key
,
err
:=
e
.
KeyFunc
(
ctx
,
name
)
if
err
!=
nil
{
return
nil
,
err
}
watchKey
=
key
}
else
{
watchKey
=
e
.
KeyRootFunc
(
ctx
)
}
return
e
.
Helper
.
WatchList
(
watchKey
,
version
,
func
(
obj
runtime
.
Object
)
bool
{
matches
,
err
:=
m
.
Matches
(
obj
)
if
err
!=
nil
{
glog
.
Errorf
(
"unable to match watch: %v"
,
err
)
...
...
pkg/registry/generic/etcd/etcd_test.go
View file @
8e91097f
...
...
@@ -83,13 +83,13 @@ func NewTestGenericEtcdRegistry(t *testing.T) (*tools.FakeEtcdClient, *Etcd) {
}
}
//
S
etMatcher is a matcher that matches any pod with id in the set.
//
s
etMatcher is a matcher that matches any pod with id in the set.
// Makes testing simpler.
type
S
etMatcher
struct
{
type
s
etMatcher
struct
{
util
.
StringSet
}
func
(
sm
S
etMatcher
)
Matches
(
obj
runtime
.
Object
)
(
bool
,
error
)
{
func
(
sm
s
etMatcher
)
Matches
(
obj
runtime
.
Object
)
(
bool
,
error
)
{
pod
,
ok
:=
obj
.
(
*
api
.
Pod
)
if
!
ok
{
return
false
,
fmt
.
Errorf
(
"wrong object"
)
...
...
@@ -97,13 +97,25 @@ func (sm SetMatcher) Matches(obj runtime.Object) (bool, error) {
return
sm
.
Has
(
pod
.
Name
),
nil
}
// EverythingMatcher matches everything
type
EverythingMatcher
struct
{}
func
(
sm
setMatcher
)
MatchesSingle
()
(
string
,
bool
)
{
if
sm
.
Len
()
==
1
{
// Since pod name is its key, we can optimize this case.
return
sm
.
List
()[
0
],
true
}
return
""
,
false
}
// everythingMatcher matches everything
type
everythingMatcher
struct
{}
func
(
E
verythingMatcher
)
Matches
(
obj
runtime
.
Object
)
(
bool
,
error
)
{
func
(
e
verythingMatcher
)
Matches
(
obj
runtime
.
Object
)
(
bool
,
error
)
{
return
true
,
nil
}
func
(
everythingMatcher
)
MatchesSingle
()
(
string
,
bool
)
{
return
""
,
false
}
func
TestEtcdList
(
t
*
testing
.
T
)
{
podA
:=
&
api
.
Pod
{
ObjectMeta
:
api
.
ObjectMeta
{
Name
:
"foo"
},
...
...
@@ -138,7 +150,7 @@ func TestEtcdList(t *testing.T) {
},
E
:
nil
,
},
m
:
E
verythingMatcher
{},
m
:
e
verythingMatcher
{},
out
:
&
api
.
PodList
{
Items
:
[]
api
.
Pod
{}},
succeed
:
true
,
},
...
...
@@ -147,7 +159,7 @@ func TestEtcdList(t *testing.T) {
R
:
&
etcd
.
Response
{},
E
:
tools
.
EtcdErrorNotFound
,
},
m
:
E
verythingMatcher
{},
m
:
e
verythingMatcher
{},
out
:
&
api
.
PodList
{
Items
:
[]
api
.
Pod
{}},
succeed
:
true
,
},
...
...
@@ -156,7 +168,7 @@ func TestEtcdList(t *testing.T) {
R
:
normalListResp
,
E
:
nil
,
},
m
:
E
verythingMatcher
{},
m
:
e
verythingMatcher
{},
out
:
&
api
.
PodList
{
Items
:
[]
api
.
Pod
{
*
podA
,
*
podB
}},
succeed
:
true
,
},
...
...
@@ -165,7 +177,16 @@ func TestEtcdList(t *testing.T) {
R
:
normalListResp
,
E
:
nil
,
},
m
:
SetMatcher
{
util
.
NewStringSet
(
"foo"
)},
m
:
setMatcher
{
util
.
NewStringSet
(
"foo"
)},
out
:
&
api
.
PodList
{
Items
:
[]
api
.
Pod
{
*
podA
}},
succeed
:
true
,
},
"normalFilteredMatchMultiple"
:
{
in
:
tools
.
EtcdResponseWithError
{
R
:
normalListResp
,
E
:
nil
,
},
m
:
setMatcher
{
util
.
NewStringSet
(
"foo"
,
"makeMatchSingleReturnFalse"
)},
out
:
&
api
.
PodList
{
Items
:
[]
api
.
Pod
{
*
podA
}},
succeed
:
true
,
},
...
...
@@ -648,36 +669,45 @@ func TestEtcdDelete(t *testing.T) {
}
func
TestEtcdWatch
(
t
*
testing
.
T
)
{
podA
:=
&
api
.
Pod
{
ObjectMeta
:
api
.
ObjectMeta
{
Name
:
"foo"
,
ResourceVersion
:
"1"
},
Spec
:
api
.
PodSpec
{
Host
:
"machine"
},
}
respWithPodA
:=
&
etcd
.
Response
{
Node
:
&
etcd
.
Node
{
Value
:
runtime
.
EncodeOrDie
(
testapi
.
Codec
(),
podA
),
ModifiedIndex
:
1
,
CreatedIndex
:
1
,
},
Action
:
"create"
,
table
:=
map
[
string
]
generic
.
Matcher
{
"single"
:
setMatcher
{
util
.
NewStringSet
(
"foo"
)},
"multi"
:
setMatcher
{
util
.
NewStringSet
(
"foo"
,
"bar"
)},
}
fakeClient
,
registry
:=
NewTestGenericEtcdRegistry
(
t
)
wi
,
err
:=
registry
.
WatchPredicate
(
api
.
NewContext
(),
EverythingMatcher
{},
"1"
)
if
err
!=
nil
{
t
.
Fatalf
(
"unexpected error: %v"
,
err
)
}
fakeClient
.
WaitForWatchCompletion
()
for
name
,
m
:=
range
table
{
podA
:=
&
api
.
Pod
{
ObjectMeta
:
api
.
ObjectMeta
{
Name
:
"foo"
,
ResourceVersion
:
"1"
},
Spec
:
api
.
PodSpec
{
Host
:
"machine"
},
}
respWithPodA
:=
&
etcd
.
Response
{
Node
:
&
etcd
.
Node
{
Value
:
runtime
.
EncodeOrDie
(
testapi
.
Codec
(),
podA
),
ModifiedIndex
:
1
,
CreatedIndex
:
1
,
},
Action
:
"create"
,
}
go
func
()
{
fakeClient
.
WatchResponse
<-
respWithPodA
}()
fakeClient
,
registry
:=
NewTestGenericEtcdRegistry
(
t
)
wi
,
err
:=
registry
.
WatchPredicate
(
api
.
NewContext
(),
m
,
"1"
)
if
err
!=
nil
{
t
.
Errorf
(
"%v: unexpected error: %v"
,
name
,
err
)
continue
}
fakeClient
.
WaitForWatchCompletion
()
got
,
open
:=
<-
wi
.
ResultChan
()
if
!
open
{
t
.
Fatalf
(
"unexpected channel close"
)
}
go
func
()
{
fakeClient
.
WatchResponse
<-
respWithPodA
}()
if
e
,
a
:=
podA
,
got
.
Object
;
!
api
.
Semantic
.
DeepDerivative
(
e
,
a
)
{
t
.
Errorf
(
"difference: %s"
,
util
.
ObjectDiff
(
e
,
a
))
got
,
open
:=
<-
wi
.
ResultChan
()
if
!
open
{
t
.
Errorf
(
"%v: unexpected channel close"
,
name
)
continue
}
if
e
,
a
:=
podA
,
got
.
Object
;
!
api
.
Semantic
.
DeepDerivative
(
e
,
a
)
{
t
.
Errorf
(
"%v: difference: %s"
,
name
,
util
.
ObjectDiff
(
e
,
a
))
}
}
}
pkg/registry/generic/registry.go
View file @
8e91097f
...
...
@@ -49,14 +49,37 @@ func (s *SelectionPredicate) Matches(obj runtime.Object) (bool, error) {
return
s
.
Label
.
Matches
(
labels
)
&&
s
.
Field
.
Matches
(
fields
),
nil
}
// MatchesSingle will return (name, true) iff s.Field matches on the object's
// name.
func
(
s
*
SelectionPredicate
)
MatchesSingle
()
(
string
,
bool
)
{
// TODO: should be namespace.name
if
name
,
ok
:=
s
.
Field
.
RequiresExactMatch
(
"metadata.name"
);
ok
{
return
name
,
true
}
return
""
,
false
}
// Matcher can return true if an object matches the Matcher's selection
// criteria.
// criteria. If it is known that the matcher will match only a single object
// then MatchesSingle should return the key of that object and true. This is an
// optimization only--Matches() should continue to work.
type
Matcher
interface
{
Matches
(
obj
runtime
.
Object
)
(
bool
,
error
)
// Matches should return true if obj matches this matcher's requirements.
Matches
(
obj
runtime
.
Object
)
(
matchesThisObject
bool
,
err
error
)
// If this matcher matches a single object, return the key for that
// object and true here. This will greatly increase efficiency. You
// must still implement Matches(). Note that key does NOT need to
// include the object's namespace.
MatchesSingle
()
(
key
string
,
matchesSingleObject
bool
)
// TODO: when we start indexing objects, add something like the below:
// MatchesIndices() (indexName []string, indexValue []string)
// where indexName/indexValue are the same length.
}
// MatcherFunc makes a matcher from the provided function. For easy definition
// of matchers for testing.
// of matchers for testing.
Note: use SelectionPredicate above for real code!
func
MatcherFunc
(
f
func
(
obj
runtime
.
Object
)
(
bool
,
error
))
Matcher
{
return
matcherFunc
(
f
)
}
...
...
@@ -68,6 +91,36 @@ func (m matcherFunc) Matches(obj runtime.Object) (bool, error) {
return
m
(
obj
)
}
// MatchesSingle always returns "", false-- because this is a predicate
// implementation of Matcher.
func
(
m
matcherFunc
)
MatchesSingle
()
(
string
,
bool
)
{
return
""
,
false
}
// MatchOnKey returns a matcher that will send only the object matching key
// through the matching function f. For testing!
// Note: use SelectionPredicate above for real code!
func
MatchOnKey
(
key
string
,
f
func
(
obj
runtime
.
Object
)
(
bool
,
error
))
Matcher
{
return
matchKey
{
key
,
f
}
}
type
matchKey
struct
{
key
string
matcherFunc
}
// MatchesSingle always returns its key, true.
func
(
m
matchKey
)
MatchesSingle
()
(
string
,
bool
)
{
return
m
.
key
,
true
}
var
(
// Assert implementations match the interface.
_
=
Matcher
(
matchKey
{})
_
=
Matcher
(
&
SelectionPredicate
{})
_
=
Matcher
(
matcherFunc
(
nil
))
)
// DecoratorFunc can mutate the provided object prior to being returned.
type
DecoratorFunc
func
(
obj
runtime
.
Object
)
error
...
...
pkg/registry/generic/registry_test.go
View file @
8e91097f
...
...
@@ -44,6 +44,7 @@ func TestSelectionPredicate(t *testing.T) {
fields
fields
.
Set
err
error
shouldMatch
bool
matchSingleKey
string
}{
"A"
:
{
labelSelector
:
"name=foo"
,
...
...
@@ -66,6 +67,13 @@ func TestSelectionPredicate(t *testing.T) {
fields
:
fields
.
Set
{
"uid"
:
"12345"
},
shouldMatch
:
false
,
},
"D"
:
{
fieldSelector
:
"metadata.name=12345"
,
labels
:
labels
.
Set
{},
fields
:
fields
.
Set
{
"metadata.name"
:
"12345"
},
shouldMatch
:
true
,
matchSingleKey
:
"12345"
,
},
"error"
:
{
labelSelector
:
"name=foo"
,
fieldSelector
:
"uid=12345"
,
...
...
@@ -98,6 +106,15 @@ func TestSelectionPredicate(t *testing.T) {
if
e
,
a
:=
item
.
shouldMatch
,
got
;
e
!=
a
{
t
.
Errorf
(
"%v: expected %v, got %v"
,
name
,
e
,
a
)
}
if
key
:=
item
.
matchSingleKey
;
key
!=
""
{
got
,
ok
:=
sp
.
MatchesSingle
()
if
!
ok
{
t
.
Errorf
(
"%v: expected single match"
,
name
)
}
if
e
,
a
:=
key
,
got
;
e
!=
a
{
t
.
Errorf
(
"%v: expected %v, got %v"
,
name
,
e
,
a
)
}
}
}
}
...
...
@@ -118,16 +135,18 @@ func TestFilterList(t *testing.T) {
},
}
got
,
err
:=
FilterList
(
try
,
MatcherFunc
(
func
(
obj
runtime
.
Object
)
(
bool
,
error
)
{
i
,
ok
:=
obj
.
(
*
Ignored
)
if
!
ok
{
return
false
,
errors
.
New
(
"wrong type"
)
}
return
i
.
ID
[
0
]
==
'b'
,
nil
}),
nil
,
)
m
:=
MatcherFunc
(
func
(
obj
runtime
.
Object
)
(
bool
,
error
)
{
i
,
ok
:=
obj
.
(
*
Ignored
)
if
!
ok
{
return
false
,
errors
.
New
(
"wrong type"
)
}
return
i
.
ID
[
0
]
==
'b'
,
nil
})
if
_
,
matchesSingleObject
:=
m
.
MatchesSingle
();
matchesSingleObject
{
t
.
Errorf
(
"matcher unexpectedly matches only a single object."
)
}
got
,
err
:=
FilterList
(
try
,
m
,
nil
)
if
err
!=
nil
{
t
.
Fatalf
(
"Unexpected error %v"
,
err
)
}
...
...
@@ -136,3 +155,14 @@ func TestFilterList(t *testing.T) {
t
.
Errorf
(
"Expected %#v, got %#v"
,
e
,
a
)
}
}
func
TestSingleMatch
(
t
*
testing
.
T
)
{
m
:=
MatchOnKey
(
"pod-name-here"
,
func
(
obj
runtime
.
Object
)
(
bool
,
error
)
{
return
true
,
nil
})
got
,
ok
:=
m
.
MatchesSingle
()
if
!
ok
{
t
.
Errorf
(
"Expected MatchesSingle to return true"
)
}
if
e
,
a
:=
"pod-name-here"
,
got
;
e
!=
a
{
t
.
Errorf
(
"Expected %#v, got %#v"
,
e
,
a
)
}
}
pkg/registry/minion/etcd/etcd.go
View file @
8e91097f
...
...
@@ -23,9 +23,6 @@ import (
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/rest"
"github.com/GoogleCloudPlatform/kubernetes/pkg/client"
"github.com/GoogleCloudPlatform/kubernetes/pkg/fields"
"github.com/GoogleCloudPlatform/kubernetes/pkg/labels"
"github.com/GoogleCloudPlatform/kubernetes/pkg/registry/generic"
etcdgeneric
"github.com/GoogleCloudPlatform/kubernetes/pkg/registry/generic/etcd"
"github.com/GoogleCloudPlatform/kubernetes/pkg/registry/minion"
"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
...
...
@@ -49,14 +46,11 @@ func NewStorage(h tools.EtcdHelper, connection client.ConnectionInfoGetter) *RES
KeyFunc
:
func
(
ctx
api
.
Context
,
name
string
)
(
string
,
error
)
{
return
prefix
+
"/"
+
name
,
nil
},
WatchSingleFieldName
:
"name"
,
ObjectNameFunc
:
func
(
obj
runtime
.
Object
)
(
string
,
error
)
{
return
obj
.
(
*
api
.
Node
)
.
Name
,
nil
},
PredicateFunc
:
func
(
label
labels
.
Selector
,
field
fields
.
Selector
)
generic
.
Matcher
{
return
minion
.
MatchNode
(
label
,
field
)
},
EndpointName
:
"minion"
,
PredicateFunc
:
minion
.
MatchNode
,
EndpointName
:
"minion"
,
CreateStrategy
:
minion
.
Strategy
,
UpdateStrategy
:
minion
.
Strategy
,
...
...
pkg/registry/minion/etcd/etcd_test.go
View file @
8e91097f
...
...
@@ -347,59 +347,6 @@ func TestEtcdWatchNodesMatch(t *testing.T) {
watching
.
Stop
()
}
func
TestEtcdWatchNodesFields
(
t
*
testing
.
T
)
{
ctx
:=
api
.
NewDefaultContext
()
storage
,
fakeClient
:=
newStorage
(
t
)
node
:=
validNewNode
()
nodeBytes
,
_
:=
latest
.
Codec
.
Encode
(
node
)
testFieldMap
:=
map
[
int
][]
fields
.
Set
{
PASS
:
{
{
"name"
:
"foo"
},
},
FAIL
:
{
{
"name"
:
"bar"
},
},
}
for
_
,
singleWatchField
:=
range
[]
string
{
""
,
"name"
}
{
storage
.
WatchSingleFieldName
=
singleWatchField
for
expectedResult
,
fieldSet
:=
range
testFieldMap
{
for
_
,
field
:=
range
fieldSet
{
watching
,
err
:=
storage
.
Watch
(
ctx
,
labels
.
Everything
(),
field
.
AsSelector
(),
"1"
,
)
if
err
!=
nil
{
t
.
Fatalf
(
"unexpected error: %v"
,
err
)
}
fakeClient
.
WaitForWatchCompletion
()
fakeClient
.
WatchResponse
<-
&
etcd
.
Response
{
Action
:
"create"
,
Node
:
&
etcd
.
Node
{
Value
:
string
(
nodeBytes
),
},
}
select
{
case
r
,
ok
:=
<-
watching
.
ResultChan
()
:
if
expectedResult
==
FAIL
{
t
.
Errorf
(
"unexpected result from channel %#v"
,
r
)
}
if
!
ok
{
t
.
Errorf
(
"watching channel should be open"
)
}
case
<-
time
.
After
(
time
.
Millisecond
*
100
)
:
if
expectedResult
==
PASS
{
t
.
Errorf
(
"unexpected timeout from result channel"
)
}
}
watching
.
Stop
()
}
}
}
}
func
TestEtcdWatchNodesNotMatch
(
t
*
testing
.
T
)
{
ctx
:=
api
.
NewDefaultContext
()
storage
,
fakeClient
:=
newStorage
(
t
)
...
...
pkg/registry/minion/rest.go
View file @
8e91097f
...
...
@@ -83,22 +83,25 @@ type ResourceGetter interface {
}
// NodeToSelectableFields returns a label set that represents the object.
func
NodeToSelectableFields
(
node
*
api
.
Node
)
label
s
.
Set
{
return
label
s
.
Set
{
"name"
:
node
.
Name
,
func
NodeToSelectableFields
(
node
*
api
.
Node
)
field
s
.
Set
{
return
field
s
.
Set
{
"
metadata.
name"
:
node
.
Name
,
}
}
// MatchNode returns a generic matcher for a given label and field selector.
func
MatchNode
(
label
labels
.
Selector
,
field
fields
.
Selector
)
generic
.
Matcher
{
return
generic
.
MatcherFunc
(
func
(
obj
runtime
.
Object
)
(
bool
,
error
)
{
nodeObj
,
ok
:=
obj
.
(
*
api
.
Node
)
if
!
ok
{
return
false
,
fmt
.
Errorf
(
"not a node"
)
}
fields
:=
NodeToSelectableFields
(
nodeObj
)
return
label
.
Matches
(
labels
.
Set
(
nodeObj
.
Labels
))
&&
field
.
Matches
(
fields
),
nil
})
return
&
generic
.
SelectionPredicate
{
Label
:
label
,
Field
:
field
,
GetAttrs
:
func
(
obj
runtime
.
Object
)
(
labels
.
Set
,
fields
.
Set
,
error
)
{
nodeObj
,
ok
:=
obj
.
(
*
api
.
Node
)
if
!
ok
{
return
nil
,
nil
,
fmt
.
Errorf
(
"not a node"
)
}
return
labels
.
Set
(
nodeObj
.
ObjectMeta
.
Labels
),
NodeToSelectableFields
(
nodeObj
),
nil
},
}
}
// ResourceLocation returns a URL to which one can send traffic for the specified node.
...
...
pkg/registry/minion/rest_test.go
0 → 100644
View file @
8e91097f
/*
Copyright 2015 Google Inc. 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
minion
import
(
"testing"
"github.com/GoogleCloudPlatform/kubernetes/pkg/fields"
"github.com/GoogleCloudPlatform/kubernetes/pkg/labels"
)
func
TestMatchNode
(
t
*
testing
.
T
)
{
testFieldMap
:=
map
[
bool
][]
fields
.
Set
{
true
:
{
{
"metadata.name"
:
"foo"
},
},
false
:
{
{
"foo"
:
"bar"
},
},
}
for
expectedResult
,
fieldSet
:=
range
testFieldMap
{
for
_
,
field
:=
range
fieldSet
{
m
:=
MatchNode
(
labels
.
Everything
(),
field
.
AsSelector
())
_
,
matchesSingle
:=
m
.
MatchesSingle
()
if
e
,
a
:=
expectedResult
,
matchesSingle
;
e
!=
a
{
t
.
Errorf
(
"%+v: expected %v, got %v"
,
e
,
a
)
}
}
}
}
pkg/registry/pod/etcd/etcd_test.go
View file @
8e91097f
...
...
@@ -291,7 +291,7 @@ func TestListPodListSelection(t *testing.T) {
{
expectedIDs
:
util
.
NewStringSet
(
"foo"
,
"bar"
,
"baz"
,
"qux"
,
"zot"
),
},
{
field
:
"name=zot"
,
field
:
"
metadata.
name=zot"
,
expectedIDs
:
util
.
NewStringSet
(
"zot"
),
},
{
label
:
"label=qux"
,
...
...
pkg/registry/pod/rest.go
View file @
8e91097f
...
...
@@ -105,23 +105,26 @@ func (podStatusStrategy) ValidateUpdate(ctx api.Context, obj, old runtime.Object
// MatchPod returns a generic matcher for a given label and field selector.
func
MatchPod
(
label
labels
.
Selector
,
field
fields
.
Selector
)
generic
.
Matcher
{
return
generic
.
MatcherFunc
(
func
(
obj
runtime
.
Object
)
(
bool
,
error
)
{
podObj
,
ok
:=
obj
.
(
*
api
.
Pod
)
if
!
ok
{
return
false
,
fmt
.
Errorf
(
"not a pod"
)
}
fields
:=
PodToSelectableFields
(
podObj
)
return
label
.
Matches
(
labels
.
Set
(
podObj
.
Labels
))
&&
field
.
Matches
(
fields
),
nil
})
return
&
generic
.
SelectionPredicate
{
Label
:
label
,
Field
:
field
,
GetAttrs
:
func
(
obj
runtime
.
Object
)
(
labels
.
Set
,
fields
.
Set
,
error
)
{
pod
,
ok
:=
obj
.
(
*
api
.
Pod
)
if
!
ok
{
return
nil
,
nil
,
fmt
.
Errorf
(
"not a pod"
)
}
return
labels
.
Set
(
pod
.
ObjectMeta
.
Labels
),
PodToSelectableFields
(
pod
),
nil
},
}
}
// PodToSelectableFields returns a label set that represents the object
// TODO: fields are not labels, and the validation rules for them do not apply.
func
PodToSelectableFields
(
pod
*
api
.
Pod
)
label
s
.
Set
{
return
label
s
.
Set
{
"
name"
:
pod
.
Name
,
"spec.host"
:
pod
.
Spec
.
Host
,
"status.phase"
:
string
(
pod
.
Status
.
Phase
),
func
PodToSelectableFields
(
pod
*
api
.
Pod
)
field
s
.
Set
{
return
field
s
.
Set
{
"
metadata.name"
:
pod
.
Name
,
"spec.host"
:
pod
.
Spec
.
Host
,
"status.phase"
:
string
(
pod
.
Status
.
Phase
),
}
}
...
...
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