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
4242d1b7
Commit
4242d1b7
authored
Nov 07, 2018
by
wojtekt
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Use watch cache when rv=0 even when limit is set
parent
0ab29b48
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
157 additions
and
3 deletions
+157
-3
BUILD
staging/src/k8s.io/apiserver/pkg/storage/cacher/BUILD
+4
-0
cacher.go
staging/src/k8s.io/apiserver/pkg/storage/cacher/cacher.go
+7
-2
cacher_whitebox_test.go
...s.io/apiserver/pkg/storage/cacher/cacher_whitebox_test.go
+146
-1
No files found.
staging/src/k8s.io/apiserver/pkg/storage/cacher/BUILD
View file @
4242d1b7
...
@@ -50,10 +50,14 @@ go_test(
...
@@ -50,10 +50,14 @@ go_test(
"//staging/src/k8s.io/apimachinery/pkg/fields:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/fields:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/labels:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/labels:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/runtime/serializer:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/util/clock:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/util/clock:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/util/diff:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/util/diff:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/util/runtime:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/util/wait:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/util/wait:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/watch:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/watch:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/apis/example:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/apis/example/v1:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/storage:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/storage:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/storage/etcd:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/storage/etcd:go_default_library",
"//staging/src/k8s.io/client-go/tools/cache:go_default_library",
"//staging/src/k8s.io/client-go/tools/cache:go_default_library",
...
...
staging/src/k8s.io/apiserver/pkg/storage/cacher/cacher.go
View file @
4242d1b7
...
@@ -404,10 +404,15 @@ func (c *Cacher) Get(ctx context.Context, key string, resourceVersion string, ob
...
@@ -404,10 +404,15 @@ func (c *Cacher) Get(ctx context.Context, key string, resourceVersion string, ob
// GetToList implements storage.Interface.
// GetToList implements storage.Interface.
func
(
c
*
Cacher
)
GetToList
(
ctx
context
.
Context
,
key
string
,
resourceVersion
string
,
pred
storage
.
SelectionPredicate
,
listObj
runtime
.
Object
)
error
{
func
(
c
*
Cacher
)
GetToList
(
ctx
context
.
Context
,
key
string
,
resourceVersion
string
,
pred
storage
.
SelectionPredicate
,
listObj
runtime
.
Object
)
error
{
pagingEnabled
:=
utilfeature
.
DefaultFeatureGate
.
Enabled
(
features
.
APIListChunking
)
pagingEnabled
:=
utilfeature
.
DefaultFeatureGate
.
Enabled
(
features
.
APIListChunking
)
if
resourceVersion
==
""
||
(
pagingEnabled
&&
(
len
(
pred
.
Continue
)
>
0
||
pred
.
Limit
>
0
))
{
hasContinuation
:=
pagingEnabled
&&
len
(
pred
.
Continue
)
>
0
hasLimit
:=
pagingEnabled
&&
pred
.
Limit
>
0
&&
resourceVersion
!=
"0"
if
resourceVersion
==
""
||
hasContinuation
||
hasLimit
{
// If resourceVersion is not specified, serve it from underlying
// If resourceVersion is not specified, serve it from underlying
// storage (for backward compatibility). If a continuation
or limit
is
// storage (for backward compatibility). If a continuation is
// requested, serve it from the underlying storage as well.
// requested, serve it from the underlying storage as well.
// Limits are only sent to storage when resourceVersion is non-zero
// since the watch cache isn't able to perform continuations, and
// limits are ignored when resource version is zero
return
c
.
storage
.
GetToList
(
ctx
,
key
,
resourceVersion
,
pred
,
listObj
)
return
c
.
storage
.
GetToList
(
ctx
,
key
,
resourceVersion
,
pred
,
listObj
)
}
}
...
...
staging/src/k8s.io/apiserver/pkg/storage/cacher/cacher_whitebox_test.go
View file @
4242d1b7
...
@@ -17,6 +17,7 @@ limitations under the License.
...
@@ -17,6 +17,7 @@ limitations under the License.
package
cacher
package
cacher
import
(
import
(
"context"
"fmt"
"fmt"
"reflect"
"reflect"
"strconv"
"strconv"
...
@@ -30,9 +31,14 @@ import (
...
@@ -30,9 +31,14 @@ import (
"k8s.io/apimachinery/pkg/fields"
"k8s.io/apimachinery/pkg/fields"
"k8s.io/apimachinery/pkg/labels"
"k8s.io/apimachinery/pkg/labels"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/serializer"
"k8s.io/apimachinery/pkg/util/diff"
"k8s.io/apimachinery/pkg/util/diff"
utilruntime
"k8s.io/apimachinery/pkg/util/runtime"
"k8s.io/apimachinery/pkg/util/wait"
"k8s.io/apimachinery/pkg/util/wait"
"k8s.io/apimachinery/pkg/watch"
"k8s.io/apimachinery/pkg/watch"
"k8s.io/apiserver/pkg/apis/example"
examplev1
"k8s.io/apiserver/pkg/apis/example/v1"
"k8s.io/apiserver/pkg/storage"
)
)
// verifies the cacheWatcher.process goroutine is properly cleaned up even if
// verifies the cacheWatcher.process goroutine is properly cleaned up even if
...
@@ -195,7 +201,13 @@ func (testVersioner) UpdateObject(obj runtime.Object, resourceVersion uint64) er
...
@@ -195,7 +201,13 @@ func (testVersioner) UpdateObject(obj runtime.Object, resourceVersion uint64) er
return
meta
.
NewAccessor
()
.
SetResourceVersion
(
obj
,
strconv
.
FormatUint
(
resourceVersion
,
10
))
return
meta
.
NewAccessor
()
.
SetResourceVersion
(
obj
,
strconv
.
FormatUint
(
resourceVersion
,
10
))
}
}
func
(
testVersioner
)
UpdateList
(
obj
runtime
.
Object
,
resourceVersion
uint64
,
continueValue
string
)
error
{
func
(
testVersioner
)
UpdateList
(
obj
runtime
.
Object
,
resourceVersion
uint64
,
continueValue
string
)
error
{
return
fmt
.
Errorf
(
"unimplemented"
)
listAccessor
,
err
:=
meta
.
ListAccessor
(
obj
)
if
err
!=
nil
||
listAccessor
==
nil
{
return
err
}
listAccessor
.
SetResourceVersion
(
strconv
.
FormatUint
(
resourceVersion
,
10
))
listAccessor
.
SetContinue
(
continueValue
)
return
nil
}
}
func
(
testVersioner
)
PrepareObjectForStorage
(
obj
runtime
.
Object
)
error
{
func
(
testVersioner
)
PrepareObjectForStorage
(
obj
runtime
.
Object
)
error
{
return
fmt
.
Errorf
(
"unimplemented"
)
return
fmt
.
Errorf
(
"unimplemented"
)
...
@@ -206,3 +218,136 @@ func (testVersioner) ObjectResourceVersion(obj runtime.Object) (uint64, error) {
...
@@ -206,3 +218,136 @@ func (testVersioner) ObjectResourceVersion(obj runtime.Object) (uint64, error) {
func
(
testVersioner
)
ParseResourceVersion
(
resourceVersion
string
)
(
uint64
,
error
)
{
func
(
testVersioner
)
ParseResourceVersion
(
resourceVersion
string
)
(
uint64
,
error
)
{
return
strconv
.
ParseUint
(
resourceVersion
,
10
,
64
)
return
strconv
.
ParseUint
(
resourceVersion
,
10
,
64
)
}
}
var
(
scheme
=
runtime
.
NewScheme
()
codecs
=
serializer
.
NewCodecFactory
(
scheme
)
errDummy
=
fmt
.
Errorf
(
"dummy error"
)
)
func
init
()
{
metav1
.
AddToGroupVersion
(
scheme
,
metav1
.
SchemeGroupVersion
)
utilruntime
.
Must
(
example
.
AddToScheme
(
scheme
))
utilruntime
.
Must
(
examplev1
.
AddToScheme
(
scheme
))
}
func
newTestCacher
(
s
storage
.
Interface
,
cap
int
)
(
*
Cacher
,
storage
.
Versioner
)
{
prefix
:=
"pods"
config
:=
Config
{
CacheCapacity
:
cap
,
Storage
:
s
,
Versioner
:
testVersioner
{},
Type
:
&
example
.
Pod
{},
ResourcePrefix
:
prefix
,
KeyFunc
:
func
(
obj
runtime
.
Object
)
(
string
,
error
)
{
return
storage
.
NamespaceKeyFunc
(
prefix
,
obj
)
},
GetAttrsFunc
:
func
(
obj
runtime
.
Object
)
(
labels
.
Set
,
fields
.
Set
,
bool
,
error
)
{
return
nil
,
nil
,
true
,
nil
},
NewListFunc
:
func
()
runtime
.
Object
{
return
&
example
.
PodList
{}
},
Codec
:
codecs
.
LegacyCodec
(
examplev1
.
SchemeGroupVersion
),
}
return
NewCacherFromConfig
(
config
),
testVersioner
{}
}
type
dummyStorage
struct
{
err
error
}
type
dummyWatch
struct
{
ch
chan
watch
.
Event
}
func
(
w
*
dummyWatch
)
ResultChan
()
<-
chan
watch
.
Event
{
return
w
.
ch
}
func
(
w
*
dummyWatch
)
Stop
()
{
close
(
w
.
ch
)
}
func
newDummyWatch
()
watch
.
Interface
{
return
&
dummyWatch
{
ch
:
make
(
chan
watch
.
Event
),
}
}
func
(
d
*
dummyStorage
)
Versioner
()
storage
.
Versioner
{
return
nil
}
func
(
d
*
dummyStorage
)
Create
(
_
context
.
Context
,
_
string
,
_
,
_
runtime
.
Object
,
_
uint64
)
error
{
return
fmt
.
Errorf
(
"unimplemented"
)
}
func
(
d
*
dummyStorage
)
Delete
(
_
context
.
Context
,
_
string
,
_
runtime
.
Object
,
_
*
storage
.
Preconditions
)
error
{
return
fmt
.
Errorf
(
"unimplemented"
)
}
func
(
d
*
dummyStorage
)
Watch
(
_
context
.
Context
,
_
string
,
_
string
,
_
storage
.
SelectionPredicate
)
(
watch
.
Interface
,
error
)
{
return
newDummyWatch
(),
nil
}
func
(
d
*
dummyStorage
)
WatchList
(
_
context
.
Context
,
_
string
,
_
string
,
_
storage
.
SelectionPredicate
)
(
watch
.
Interface
,
error
)
{
return
newDummyWatch
(),
nil
}
func
(
d
*
dummyStorage
)
Get
(
_
context
.
Context
,
_
string
,
_
string
,
_
runtime
.
Object
,
_
bool
)
error
{
return
fmt
.
Errorf
(
"unimplemented"
)
}
func
(
d
*
dummyStorage
)
GetToList
(
_
context
.
Context
,
_
string
,
_
string
,
_
storage
.
SelectionPredicate
,
_
runtime
.
Object
)
error
{
return
d
.
err
}
func
(
d
*
dummyStorage
)
List
(
_
context
.
Context
,
_
string
,
_
string
,
_
storage
.
SelectionPredicate
,
listObj
runtime
.
Object
)
error
{
podList
:=
listObj
.
(
*
example
.
PodList
)
podList
.
ListMeta
=
metav1
.
ListMeta
{
ResourceVersion
:
"100"
}
return
d
.
err
}
func
(
d
*
dummyStorage
)
GuaranteedUpdate
(
_
context
.
Context
,
_
string
,
_
runtime
.
Object
,
_
bool
,
_
*
storage
.
Preconditions
,
_
storage
.
UpdateFunc
,
_
...
runtime
.
Object
)
error
{
return
fmt
.
Errorf
(
"unimplemented"
)
}
func
(
d
*
dummyStorage
)
Count
(
_
string
)
(
int64
,
error
)
{
return
0
,
fmt
.
Errorf
(
"unimplemented"
)
}
func
TestListWithLimitAndRV0
(
t
*
testing
.
T
)
{
backingStorage
:=
&
dummyStorage
{}
cacher
,
_
:=
newTestCacher
(
backingStorage
,
0
)
defer
cacher
.
Stop
()
pred
:=
storage
.
SelectionPredicate
{
Limit
:
500
,
}
result
:=
&
example
.
PodList
{}
// Wait until cacher is initialized.
cacher
.
ready
.
wait
()
// Inject error to underlying layer and check if cacher is not bypassed.
backingStorage
.
err
=
errDummy
err
:=
cacher
.
List
(
context
.
TODO
(),
"pods/ns"
,
"0"
,
pred
,
result
)
if
err
!=
nil
{
t
.
Errorf
(
"List with Limit and RV=0 should be served from cache: %v"
,
err
)
}
err
=
cacher
.
List
(
context
.
TODO
(),
"pods/ns"
,
""
,
pred
,
result
)
if
err
!=
errDummy
{
t
.
Errorf
(
"List with Limit without RV=0 should bypass cacher: %v"
,
err
)
}
}
func
TestGetToListWithLimitAndRV0
(
t
*
testing
.
T
)
{
backingStorage
:=
&
dummyStorage
{}
cacher
,
_
:=
newTestCacher
(
backingStorage
,
0
)
defer
cacher
.
Stop
()
pred
:=
storage
.
SelectionPredicate
{
Limit
:
500
,
}
result
:=
&
example
.
PodList
{}
// Wait until cacher is initialized.
cacher
.
ready
.
wait
()
// Inject error to underlying layer and check if cacher is not bypassed.
backingStorage
.
err
=
errDummy
err
:=
cacher
.
GetToList
(
context
.
TODO
(),
"pods/ns"
,
"0"
,
pred
,
result
)
if
err
!=
nil
{
t
.
Errorf
(
"GetToList with Limit and RV=0 should be served from cache: %v"
,
err
)
}
err
=
cacher
.
GetToList
(
context
.
TODO
(),
"pods/ns"
,
""
,
pred
,
result
)
if
err
!=
errDummy
{
t
.
Errorf
(
"List with Limit without RV=0 should bypass cacher: %v"
,
err
)
}
}
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