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
06f49f7c
Commit
06f49f7c
authored
May 28, 2016
by
Chao Xu
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Let the dynamic client take a customized parameter codec for List, Watch, and DeleteCollection.
Let the gc's ListWatcher use api.ParameterCodec. Fixes 25890.
parent
344f26ae
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
102 additions
and
31 deletions
+102
-31
client.go
pkg/client/typed/dynamic/client.go
+45
-7
garbagecollector.go
pkg/controller/garbagecollector/garbagecollector.go
+30
-20
garbagecollector_test.go
pkg/controller/garbagecollector/garbagecollector_test.go
+27
-1
garbage_collector_test.go
test/integration/garbage_collector_test.go
+0
-3
No files found.
pkg/client/typed/dynamic/client.go
View file @
06f49f7c
...
...
@@ -42,6 +42,11 @@ type Client struct {
cl
*
restclient
.
RESTClient
}
type
ClientWithParameterCodec
struct
{
client
*
Client
parameterCodec
runtime
.
ParameterCodec
}
// NewClient returns a new client based on the passed in config. The
// codec is ignored, as the dynamic client uses it's own codec.
func
NewClient
(
conf
*
restclient
.
Config
)
(
*
Client
,
error
)
{
...
...
@@ -79,9 +84,9 @@ func NewClient(conf *restclient.Config) (*Client, error) {
return
&
Client
{
cl
:
cl
},
nil
}
// Resource returns an API interface to the specified resource for
//
this client's group and version. If resource is not a namespaced
//
resource, then namespace
is ignored.
// Resource returns an API interface to the specified resource for
this client's
//
group and version. If resource is not a namespaced resource, then namespace
// is ignored.
func
(
c
*
Client
)
Resource
(
resource
*
unversioned
.
APIResource
,
namespace
string
)
*
ResourceClient
{
return
&
ResourceClient
{
cl
:
c
.
cl
,
...
...
@@ -90,17 +95,42 @@ func (c *Client) Resource(resource *unversioned.APIResource, namespace string) *
}
}
// ParameterCodec wraps a parameterCodec around the Client.
func
(
c
*
Client
)
ParameterCodec
(
parameterCodec
runtime
.
ParameterCodec
)
*
ClientWithParameterCodec
{
return
&
ClientWithParameterCodec
{
client
:
c
,
parameterCodec
:
parameterCodec
,
}
}
// Resource returns an API interface to the specified resource for this client's
// group and version. If resource is not a namespaced resource, then namespace
// is ignored. The ResourceClient inherits the parameter codec of c.
func
(
c
*
ClientWithParameterCodec
)
Resource
(
resource
*
unversioned
.
APIResource
,
namespace
string
)
*
ResourceClient
{
return
&
ResourceClient
{
cl
:
c
.
client
.
cl
,
resource
:
resource
,
ns
:
namespace
,
parameterCodec
:
c
.
parameterCodec
,
}
}
// ResourceClient is an API interface to a specific resource under a
// dynamic client.
type
ResourceClient
struct
{
cl
*
restclient
.
RESTClient
resource
*
unversioned
.
APIResource
ns
string
cl
*
restclient
.
RESTClient
resource
*
unversioned
.
APIResource
ns
string
parameterCodec
runtime
.
ParameterCodec
}
// List returns a list of objects for this resource.
func
(
rc
*
ResourceClient
)
List
(
opts
runtime
.
Object
)
(
*
runtime
.
UnstructuredList
,
error
)
{
result
:=
new
(
runtime
.
UnstructuredList
)
parameterEncoder
:=
rc
.
parameterCodec
if
parameterEncoder
==
nil
{
parameterEncoder
=
defaultParameterEncoder
}
err
:=
rc
.
cl
.
Get
()
.
NamespaceIfScoped
(
rc
.
ns
,
rc
.
resource
.
Namespaced
)
.
Resource
(
rc
.
resource
.
Name
)
.
...
...
@@ -135,6 +165,10 @@ func (rc *ResourceClient) Delete(name string, opts *v1.DeleteOptions) error {
// DeleteCollection deletes a collection of objects.
func
(
rc
*
ResourceClient
)
DeleteCollection
(
deleteOptions
*
v1
.
DeleteOptions
,
listOptions
runtime
.
Object
)
error
{
parameterEncoder
:=
rc
.
parameterCodec
if
parameterEncoder
==
nil
{
parameterEncoder
=
defaultParameterEncoder
}
return
rc
.
cl
.
Delete
()
.
NamespaceIfScoped
(
rc
.
ns
,
rc
.
resource
.
Namespaced
)
.
Resource
(
rc
.
resource
.
Name
)
.
...
...
@@ -174,6 +208,10 @@ func (rc *ResourceClient) Update(obj *runtime.Unstructured) (*runtime.Unstructur
// Watch returns a watch.Interface that watches the resource.
func
(
rc
*
ResourceClient
)
Watch
(
opts
runtime
.
Object
)
(
watch
.
Interface
,
error
)
{
parameterEncoder
:=
rc
.
parameterCodec
if
parameterEncoder
==
nil
{
parameterEncoder
=
defaultParameterEncoder
}
return
rc
.
cl
.
Get
()
.
Prefix
(
"watch"
)
.
NamespaceIfScoped
(
rc
.
ns
,
rc
.
resource
.
Namespaced
)
.
...
...
@@ -231,4 +269,4 @@ func (parameterCodec) DecodeParameters(parameters url.Values, from unversioned.G
return
errors
.
New
(
"DecodeParameters not implemented on dynamic parameterCodec"
)
}
var
p
arameterEncoder
runtime
.
ParameterCodec
=
parameterCodec
{}
var
defaultP
arameterEncoder
runtime
.
ParameterCodec
=
parameterCodec
{}
pkg/controller/garbagecollector/garbagecollector.go
View file @
06f49f7c
...
...
@@ -433,6 +433,35 @@ type GarbageCollector struct {
propagator
*
Propagator
}
// TODO: make special List and Watch function that removes fields other than
// ObjectMeta.
func
gcListWatcher
(
client
*
dynamic
.
Client
,
resource
unversioned
.
GroupVersionResource
)
*
cache
.
ListWatch
{
return
&
cache
.
ListWatch
{
ListFunc
:
func
(
options
api
.
ListOptions
)
(
runtime
.
Object
,
error
)
{
// APIResource.Kind is not used by the dynamic client, so
// leave it empty. We want to list this resource in all
// namespaces if it's namespace scoped, so leave
// APIResource.Namespaced as false is all right.
apiResource
:=
unversioned
.
APIResource
{
Name
:
resource
.
Resource
}
// The default parameter codec used by the dynamic client cannot
// encode api.ListOptions.
// TODO: api.ParameterCodec doesn't support thirdparty objects.
// We need a generic parameter codec.
return
client
.
ParameterCodec
(
api
.
ParameterCodec
)
.
Resource
(
&
apiResource
,
api
.
NamespaceAll
)
.
List
(
&
options
)
},
WatchFunc
:
func
(
options
api
.
ListOptions
)
(
watch
.
Interface
,
error
)
{
// APIResource.Kind is not used by the dynamic client, so
// leave it empty. We want to list this resource in all
// namespaces if it's namespace scoped, so leave
// APIResource.Namespaced as false is all right.
apiResource
:=
unversioned
.
APIResource
{
Name
:
resource
.
Resource
}
// The default parameter codec used by the dynamic client cannot
// encode api.ListOptions.
return
client
.
ParameterCodec
(
api
.
ParameterCodec
)
.
Resource
(
&
apiResource
,
api
.
NamespaceAll
)
.
Watch
(
&
options
)
},
}
}
func
monitorFor
(
p
*
Propagator
,
clientPool
dynamic
.
ClientPool
,
resource
unversioned
.
GroupVersionResource
)
(
monitor
,
error
)
{
// TODO: consider store in one storage.
glog
.
V
(
6
)
.
Infof
(
"create storage for resource %s"
,
resource
)
...
...
@@ -442,26 +471,7 @@ func monitorFor(p *Propagator, clientPool dynamic.ClientPool, resource unversion
return
monitor
,
err
}
monitor
.
store
,
monitor
.
controller
=
framework
.
NewInformer
(
// TODO: make special List and Watch function that removes fields other
// than ObjectMeta.
&
cache
.
ListWatch
{
ListFunc
:
func
(
options
api
.
ListOptions
)
(
runtime
.
Object
,
error
)
{
// APIResource.Kind is not used by the dynamic client, so
// leave it empty. We want to list this resource in all
// namespaces if it's namespace scoped, so leave
// APIResource.Namespaced as false is all right.
apiResource
:=
unversioned
.
APIResource
{
Name
:
resource
.
Resource
}
return
client
.
Resource
(
&
apiResource
,
api
.
NamespaceAll
)
.
List
(
&
options
)
},
WatchFunc
:
func
(
options
api
.
ListOptions
)
(
watch
.
Interface
,
error
)
{
// APIResource.Kind is not used by the dynamic client, so
// leave it empty. We want to list this resource in all
// namespaces if it's namespace scoped, so leave
// APIResource.Namespaced as false is all right.
apiResource
:=
unversioned
.
APIResource
{
Name
:
resource
.
Resource
}
return
client
.
Resource
(
&
apiResource
,
api
.
NamespaceAll
)
.
Watch
(
&
options
)
},
},
gcListWatcher
(
client
,
resource
),
nil
,
ResourceResyncTime
,
framework
.
ResourceEventHandlerFuncs
{
...
...
pkg/controller/garbagecollector/garbagecollector_test.go
View file @
06f49f7c
...
...
@@ -52,6 +52,7 @@ func TestNewGarbageCollector(t *testing.T) {
type
fakeAction
struct
{
method
string
path
string
query
string
}
// String returns method=path to aid in testing
...
...
@@ -78,7 +79,7 @@ func (f *fakeActionHandler) ServeHTTP(response http.ResponseWriter, request *htt
f
.
lock
.
Lock
()
defer
f
.
lock
.
Unlock
()
f
.
actions
=
append
(
f
.
actions
,
fakeAction
{
method
:
request
.
Method
,
path
:
request
.
URL
.
Path
})
f
.
actions
=
append
(
f
.
actions
,
fakeAction
{
method
:
request
.
Method
,
path
:
request
.
URL
.
Path
,
query
:
request
.
URL
.
RawQuery
})
fakeResponse
,
ok
:=
f
.
response
[
request
.
Method
+
request
.
URL
.
Path
]
if
!
ok
{
fakeResponse
.
statusCode
=
200
...
...
@@ -317,3 +318,28 @@ func TestDependentsRace(t *testing.T) {
}
}()
}
// test the list and watch functions correctly converts the ListOptions
func
TestGCListWatcher
(
t
*
testing
.
T
)
{
testHandler
:=
&
fakeActionHandler
{}
srv
,
clientConfig
:=
testServerAndClientConfig
(
testHandler
.
ServeHTTP
)
defer
srv
.
Close
()
clientPool
:=
dynamic
.
NewClientPool
(
clientConfig
,
dynamic
.
LegacyAPIPathResolverFunc
)
podResource
:=
unversioned
.
GroupVersionResource
{
Version
:
"v1"
,
Resource
:
"pods"
}
client
,
err
:=
clientPool
.
ClientForGroupVersion
(
podResource
.
GroupVersion
())
if
err
!=
nil
{
t
.
Fatal
(
err
)
}
lw
:=
gcListWatcher
(
client
,
podResource
)
lw
.
Watch
(
api
.
ListOptions
{
ResourceVersion
:
"1"
})
lw
.
List
(
api
.
ListOptions
{
ResourceVersion
:
"1"
})
if
e
,
a
:=
2
,
len
(
testHandler
.
actions
);
e
!=
a
{
t
.
Errorf
(
"expect %d requests, got %d"
,
e
,
a
)
}
if
e
,
a
:=
"resourceVersion=1"
,
testHandler
.
actions
[
0
]
.
query
;
e
!=
a
{
t
.
Errorf
(
"expect %s, got %s"
,
e
,
a
)
}
if
e
,
a
:=
"resourceVersion=1"
,
testHandler
.
actions
[
1
]
.
query
;
e
!=
a
{
t
.
Errorf
(
"expect %s, got %s"
,
e
,
a
)
}
}
test/integration/garbage_collector_test.go
View file @
06f49f7c
...
...
@@ -149,9 +149,6 @@ func setup(t *testing.T) (*garbagecollector.GarbageCollector, clientset.Interfac
// This test simulates the cascading deletion.
func
TestCascadingDeletion
(
t
*
testing
.
T
)
{
// TODO: Figure out what's going on with this test!
t
.
Log
(
"This test is failing too much-- lavalamp removed it to stop the submit queue bleeding"
)
return
gc
,
clientSet
:=
setup
(
t
)
oldEnableGarbageCollector
:=
registry
.
EnableGarbageCollector
registry
.
EnableGarbageCollector
=
true
...
...
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