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
1bb90b58
Unverified
Commit
1bb90b58
authored
Jul 01, 2019
by
Kubernetes Prow Robot
Committed by
GitHub
Jul 01, 2019
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #79439 from roycaihw/automated-cherry-pick-of-#79114-upstream-release-1.15
Automated cherry pick of #79114: crd-handler: level-trigger storage recreation and fix a race
parents
162b46b3
262ebe84
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
57 additions
and
7 deletions
+57
-7
customresource_handler.go
...ensions-apiserver/pkg/apiserver/customresource_handler.go
+57
-7
No files found.
staging/src/k8s.io/apiextensions-apiserver/pkg/apiserver/customresource_handler.go
View file @
1bb90b58
...
@@ -170,6 +170,7 @@ func NewCustomResourceDefinitionHandler(
...
@@ -170,6 +170,7 @@ func NewCustomResourceDefinitionHandler(
requestTimeout
:
requestTimeout
,
requestTimeout
:
requestTimeout
,
}
}
crdInformer
.
Informer
()
.
AddEventHandler
(
cache
.
ResourceEventHandlerFuncs
{
crdInformer
.
Informer
()
.
AddEventHandler
(
cache
.
ResourceEventHandlerFuncs
{
AddFunc
:
ret
.
createCustomResourceDefinition
,
UpdateFunc
:
ret
.
updateCustomResourceDefinition
,
UpdateFunc
:
ret
.
updateCustomResourceDefinition
,
DeleteFunc
:
func
(
obj
interface
{})
{
DeleteFunc
:
func
(
obj
interface
{})
{
ret
.
removeDeadStorage
()
ret
.
removeDeadStorage
()
...
@@ -242,11 +243,19 @@ func (r *crdHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
...
@@ -242,11 +243,19 @@ func (r *crdHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
terminating
:=
apiextensions
.
IsCRDConditionTrue
(
crd
,
apiextensions
.
Terminating
)
terminating
:=
apiextensions
.
IsCRDConditionTrue
(
crd
,
apiextensions
.
Terminating
)
crdInfo
,
err
:=
r
.
getOrCreateServingInfoFor
(
crd
)
crdInfo
,
err
:=
r
.
getOrCreateServingInfoFor
(
crd
.
UID
,
crd
.
Name
)
if
apierrors
.
IsNotFound
(
err
)
{
r
.
delegate
.
ServeHTTP
(
w
,
req
)
return
}
if
err
!=
nil
{
if
err
!=
nil
{
http
.
Error
(
w
,
err
.
Error
(),
http
.
StatusInternalServerError
)
http
.
Error
(
w
,
err
.
Error
(),
http
.
StatusInternalServerError
)
return
return
}
}
if
!
hasServedCRDVersion
(
crdInfo
.
spec
,
requestInfo
.
APIVersion
)
{
r
.
delegate
.
ServeHTTP
(
w
,
req
)
return
}
verb
:=
strings
.
ToUpper
(
requestInfo
.
Verb
)
verb
:=
strings
.
ToUpper
(
requestInfo
.
Verb
)
resource
:=
requestInfo
.
Resource
resource
:=
requestInfo
.
Resource
...
@@ -356,6 +365,16 @@ func (r *crdHandler) serveScale(w http.ResponseWriter, req *http.Request, reques
...
@@ -356,6 +365,16 @@ func (r *crdHandler) serveScale(w http.ResponseWriter, req *http.Request, reques
}
}
}
}
// createCustomResourceDefinition removes potentially stale storage so it gets re-created
func
(
r
*
crdHandler
)
createCustomResourceDefinition
(
obj
interface
{})
{
crd
:=
obj
.
(
*
apiextensions
.
CustomResourceDefinition
)
r
.
customStorageLock
.
Lock
()
defer
r
.
customStorageLock
.
Unlock
()
// this could happen if the create event is merged from create-update events
r
.
removeStorage_locked
(
crd
.
UID
)
}
// updateCustomResourceDefinition removes potentially stale storage so it gets re-created
func
(
r
*
crdHandler
)
updateCustomResourceDefinition
(
oldObj
,
newObj
interface
{})
{
func
(
r
*
crdHandler
)
updateCustomResourceDefinition
(
oldObj
,
newObj
interface
{})
{
oldCRD
:=
oldObj
.
(
*
apiextensions
.
CustomResourceDefinition
)
oldCRD
:=
oldObj
.
(
*
apiextensions
.
CustomResourceDefinition
)
newCRD
:=
newObj
.
(
*
apiextensions
.
CustomResourceDefinition
)
newCRD
:=
newObj
.
(
*
apiextensions
.
CustomResourceDefinition
)
...
@@ -376,6 +395,10 @@ func (r *crdHandler) updateCustomResourceDefinition(oldObj, newObj interface{})
...
@@ -376,6 +395,10 @@ func (r *crdHandler) updateCustomResourceDefinition(oldObj, newObj interface{})
}
}
}
}
if
oldCRD
.
UID
!=
newCRD
.
UID
{
r
.
removeStorage_locked
(
oldCRD
.
UID
)
}
storageMap
:=
r
.
customStorage
.
Load
()
.
(
crdStorageMap
)
storageMap
:=
r
.
customStorage
.
Load
()
.
(
crdStorageMap
)
oldInfo
,
found
:=
storageMap
[
newCRD
.
UID
]
oldInfo
,
found
:=
storageMap
[
newCRD
.
UID
]
if
!
found
{
if
!
found
{
...
@@ -386,15 +409,22 @@ func (r *crdHandler) updateCustomResourceDefinition(oldObj, newObj interface{})
...
@@ -386,15 +409,22 @@ func (r *crdHandler) updateCustomResourceDefinition(oldObj, newObj interface{})
return
return
}
}
klog
.
V
(
4
)
.
Infof
(
"Updating customresourcedefinition %s"
,
oldCRD
.
Name
)
klog
.
V
(
4
)
.
Infof
(
"Updating customresourcedefinition %s"
,
newCRD
.
Name
)
r
.
removeStorage_locked
(
newCRD
.
UID
)
}
if
oldInfo
,
ok
:=
storageMap
[
types
.
UID
(
oldCRD
.
UID
)];
ok
{
// removeStorage_locked removes the cached storage with the given uid as key from the storage map. This function
// updates r.customStorage with the cleaned-up storageMap and tears down the old storage.
// NOTE: Caller MUST hold r.customStorageLock to write r.customStorage thread-safely.
func
(
r
*
crdHandler
)
removeStorage_locked
(
uid
types
.
UID
)
{
storageMap
:=
r
.
customStorage
.
Load
()
.
(
crdStorageMap
)
if
oldInfo
,
ok
:=
storageMap
[
uid
];
ok
{
// Copy because we cannot write to storageMap without a race
// Copy because we cannot write to storageMap without a race
// as it is used without locking elsewhere.
// as it is used without locking elsewhere.
storageMap2
:=
storageMap
.
clone
()
storageMap2
:=
storageMap
.
clone
()
// Remove from the CRD info map and store the map
// Remove from the CRD info map and store the map
delete
(
storageMap2
,
types
.
UID
(
oldCRD
.
UID
)
)
delete
(
storageMap2
,
uid
)
r
.
customStorage
.
Store
(
storageMap2
)
r
.
customStorage
.
Store
(
storageMap2
)
// Tear down the old storage
// Tear down the old storage
...
@@ -465,22 +495,32 @@ func (r *crdHandler) tearDown(oldInfo *crdInfo) {
...
@@ -465,22 +495,32 @@ func (r *crdHandler) tearDown(oldInfo *crdInfo) {
// GetCustomResourceListerCollectionDeleter returns the ListerCollectionDeleter of
// GetCustomResourceListerCollectionDeleter returns the ListerCollectionDeleter of
// the given crd.
// the given crd.
func
(
r
*
crdHandler
)
GetCustomResourceListerCollectionDeleter
(
crd
*
apiextensions
.
CustomResourceDefinition
)
(
finalizer
.
ListerCollectionDeleter
,
error
)
{
func
(
r
*
crdHandler
)
GetCustomResourceListerCollectionDeleter
(
crd
*
apiextensions
.
CustomResourceDefinition
)
(
finalizer
.
ListerCollectionDeleter
,
error
)
{
info
,
err
:=
r
.
getOrCreateServingInfoFor
(
crd
)
info
,
err
:=
r
.
getOrCreateServingInfoFor
(
crd
.
UID
,
crd
.
Name
)
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
err
return
nil
,
err
}
}
return
info
.
storages
[
info
.
storageVersion
]
.
CustomResource
,
nil
return
info
.
storages
[
info
.
storageVersion
]
.
CustomResource
,
nil
}
}
func
(
r
*
crdHandler
)
getOrCreateServingInfoFor
(
crd
*
apiextensions
.
CustomResourceDefinition
)
(
*
crdInfo
,
error
)
{
// getOrCreateServingInfoFor gets the CRD serving info for the given CRD UID if the key exists in the storage map.
// Otherwise the function fetches the up-to-date CRD using the given CRD name and creates CRD serving info.
func
(
r
*
crdHandler
)
getOrCreateServingInfoFor
(
uid
types
.
UID
,
name
string
)
(
*
crdInfo
,
error
)
{
storageMap
:=
r
.
customStorage
.
Load
()
.
(
crdStorageMap
)
storageMap
:=
r
.
customStorage
.
Load
()
.
(
crdStorageMap
)
if
ret
,
ok
:=
storageMap
[
crd
.
UID
];
ok
{
if
ret
,
ok
:=
storageMap
[
uid
];
ok
{
return
ret
,
nil
return
ret
,
nil
}
}
r
.
customStorageLock
.
Lock
()
r
.
customStorageLock
.
Lock
()
defer
r
.
customStorageLock
.
Unlock
()
defer
r
.
customStorageLock
.
Unlock
()
// Get the up-to-date CRD when we have the lock, to avoid racing with updateCustomResourceDefinition.
// If updateCustomResourceDefinition sees an update and happens later, the storage will be deleted and
// we will re-create the updated storage on demand. If updateCustomResourceDefinition happens before,
// we make sure that we observe the same up-to-date CRD.
crd
,
err
:=
r
.
crdLister
.
Get
(
name
)
if
err
!=
nil
{
return
nil
,
err
}
storageMap
=
r
.
customStorage
.
Load
()
.
(
crdStorageMap
)
storageMap
=
r
.
customStorage
.
Load
()
.
(
crdStorageMap
)
if
ret
,
ok
:=
storageMap
[
crd
.
UID
];
ok
{
if
ret
,
ok
:=
storageMap
[
crd
.
UID
];
ok
{
return
ret
,
nil
return
ret
,
nil
...
@@ -1060,3 +1100,13 @@ func (v *unstructuredSchemaCoercer) apply(u *unstructured.Unstructured) error {
...
@@ -1060,3 +1100,13 @@ func (v *unstructuredSchemaCoercer) apply(u *unstructured.Unstructured) error {
return
nil
return
nil
}
}
// hasServedCRDVersion returns true if the given version is in the list of CRD's versions and the Served flag is set.
func
hasServedCRDVersion
(
spec
*
apiextensions
.
CustomResourceDefinitionSpec
,
version
string
)
bool
{
for
_
,
v
:=
range
spec
.
Versions
{
if
v
.
Name
==
version
{
return
v
.
Served
}
}
return
false
}
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