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
678958a7
Commit
678958a7
authored
Feb 12, 2016
by
k8s-merge-robot
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #19868 from jsafrane/devel/syncclaim-twice
Auto commit by PR queue bot
parents
817d0f25
1edf34a4
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
81 additions
and
5 deletions
+81
-5
persistentvolume_claim_binder_controller.go
...sistentvolume/persistentvolume_claim_binder_controller.go
+9
-1
persistentvolume_claim_binder_controller_test.go
...ntvolume/persistentvolume_claim_binder_controller_test.go
+14
-1
persistentvolume_provisioner_controller.go
...rsistentvolume/persistentvolume_provisioner_controller.go
+14
-0
persistentvolume_provisioner_controller_test.go
...entvolume/persistentvolume_provisioner_controller_test.go
+39
-0
persistent_volumes_test.go
test/integration/persistent_volumes_test.go
+5
-3
No files found.
pkg/controller/persistentvolume/persistentvolume_claim_binder_controller.go
View file @
678958a7
...
@@ -335,7 +335,15 @@ func syncVolume(volumeIndex *persistentVolumeOrderedIndex, binderClient binderCl
...
@@ -335,7 +335,15 @@ func syncVolume(volumeIndex *persistentVolumeOrderedIndex, binderClient binderCl
}
}
func
syncClaim
(
volumeIndex
*
persistentVolumeOrderedIndex
,
binderClient
binderClient
,
claim
*
api
.
PersistentVolumeClaim
)
(
err
error
)
{
func
syncClaim
(
volumeIndex
*
persistentVolumeOrderedIndex
,
binderClient
binderClient
,
claim
*
api
.
PersistentVolumeClaim
)
(
err
error
)
{
glog
.
V
(
5
)
.
Infof
(
"Synchronizing PersistentVolumeClaim[%s]
\n
"
,
claim
.
Name
)
glog
.
V
(
5
)
.
Infof
(
"Synchronizing PersistentVolumeClaim[%s] for binding"
,
claim
.
Name
)
// The claim may have been modified by parallel call to syncClaim, load
// the current version.
newClaim
,
err
:=
binderClient
.
GetPersistentVolumeClaim
(
claim
.
Namespace
,
claim
.
Name
)
if
err
!=
nil
{
return
fmt
.
Errorf
(
"Cannot reload claim %s/%s: %v"
,
claim
.
Namespace
,
claim
.
Name
,
err
)
}
claim
=
newClaim
switch
claim
.
Status
.
Phase
{
switch
claim
.
Status
.
Phase
{
case
api
.
ClaimPending
:
case
api
.
ClaimPending
:
...
...
pkg/controller/persistentvolume/persistentvolume_claim_binder_controller_test.go
View file @
678958a7
...
@@ -123,7 +123,6 @@ func TestClaimRace(t *testing.T) {
...
@@ -123,7 +123,6 @@ func TestClaimRace(t *testing.T) {
plugMgr
:=
volume
.
VolumePluginMgr
{}
plugMgr
:=
volume
.
VolumePluginMgr
{}
plugMgr
.
InitPlugins
(
host_path
.
ProbeRecyclableVolumePlugins
(
newMockRecycler
,
volume
.
VolumeConfig
{}),
volume
.
NewFakeVolumeHost
(
tmpDir
,
nil
,
nil
))
plugMgr
.
InitPlugins
(
host_path
.
ProbeRecyclableVolumePlugins
(
newMockRecycler
,
volume
.
VolumeConfig
{}),
volume
.
NewFakeVolumeHost
(
tmpDir
,
nil
,
nil
))
// adds the volume to the index, making the volume available
// adds the volume to the index, making the volume available
syncVolume
(
volumeIndex
,
mockClient
,
v
)
syncVolume
(
volumeIndex
,
mockClient
,
v
)
if
mockClient
.
volume
.
Status
.
Phase
!=
api
.
VolumeAvailable
{
if
mockClient
.
volume
.
Status
.
Phase
!=
api
.
VolumeAvailable
{
...
@@ -133,6 +132,8 @@ func TestClaimRace(t *testing.T) {
...
@@ -133,6 +132,8 @@ func TestClaimRace(t *testing.T) {
t
.
Errorf
(
"Expected to find volume in index but it did not exist"
)
t
.
Errorf
(
"Expected to find volume in index but it did not exist"
)
}
}
// add the claim to fake API server
mockClient
.
UpdatePersistentVolumeClaim
(
c1
)
// an initial sync for a claim matches the volume
// an initial sync for a claim matches the volume
err
=
syncClaim
(
volumeIndex
,
mockClient
,
c1
)
err
=
syncClaim
(
volumeIndex
,
mockClient
,
c1
)
if
err
!=
nil
{
if
err
!=
nil
{
...
@@ -143,6 +144,8 @@ func TestClaimRace(t *testing.T) {
...
@@ -143,6 +144,8 @@ func TestClaimRace(t *testing.T) {
}
}
// before the volume gets updated w/ claimRef, a 2nd claim can attempt to bind and find the same volume
// before the volume gets updated w/ claimRef, a 2nd claim can attempt to bind and find the same volume
// add the 2nd claim to fake API server
mockClient
.
UpdatePersistentVolumeClaim
(
c2
)
err
=
syncClaim
(
volumeIndex
,
mockClient
,
c2
)
err
=
syncClaim
(
volumeIndex
,
mockClient
,
c2
)
if
err
!=
nil
{
if
err
!=
nil
{
t
.
Errorf
(
"unexpected error for unmatched claim: %v"
,
err
)
t
.
Errorf
(
"unexpected error for unmatched claim: %v"
,
err
)
...
@@ -470,6 +473,8 @@ func TestBindingWithExamples(t *testing.T) {
...
@@ -470,6 +473,8 @@ func TestBindingWithExamples(t *testing.T) {
t
.
Errorf
(
"Expected phase %s but got %s"
,
api
.
VolumeAvailable
,
mockClient
.
volume
.
Status
.
Phase
)
t
.
Errorf
(
"Expected phase %s but got %s"
,
api
.
VolumeAvailable
,
mockClient
.
volume
.
Status
.
Phase
)
}
}
// add the claim to fake API server
mockClient
.
UpdatePersistentVolumeClaim
(
claim
)
// an initial sync for a claim will bind it to an unbound volume
// an initial sync for a claim will bind it to an unbound volume
syncClaim
(
volumeIndex
,
mockClient
,
claim
)
syncClaim
(
volumeIndex
,
mockClient
,
claim
)
...
@@ -539,6 +544,14 @@ func TestCasting(t *testing.T) {
...
@@ -539,6 +544,14 @@ func TestCasting(t *testing.T) {
Status
:
api
.
PersistentVolumeClaimStatus
{
Phase
:
api
.
ClaimBound
},
Status
:
api
.
PersistentVolumeClaimStatus
{
Phase
:
api
.
ClaimBound
},
}
}
// Inject mockClient into the binder. This prevents weird errors on stderr
// as the binder wants to load PV/PVC from API server.
mockClient
:=
&
mockBinderClient
{
volume
:
pv
,
claim
:
pvc
,
}
binder
.
client
=
mockClient
// none of these should fail casting.
// none of these should fail casting.
// the real test is not failing when passed DeletedFinalStateUnknown in the deleteHandler
// the real test is not failing when passed DeletedFinalStateUnknown in the deleteHandler
binder
.
addVolume
(
pv
)
binder
.
addVolume
(
pv
)
...
...
pkg/controller/persistentvolume/persistentvolume_provisioner_controller.go
View file @
678958a7
...
@@ -153,6 +153,20 @@ func (controller *PersistentVolumeProvisionerController) handleUpdateClaim(oldOb
...
@@ -153,6 +153,20 @@ func (controller *PersistentVolumeProvisionerController) handleUpdateClaim(oldOb
}
}
func
(
controller
*
PersistentVolumeProvisionerController
)
reconcileClaim
(
claim
*
api
.
PersistentVolumeClaim
)
error
{
func
(
controller
*
PersistentVolumeProvisionerController
)
reconcileClaim
(
claim
*
api
.
PersistentVolumeClaim
)
error
{
glog
.
V
(
5
)
.
Infof
(
"Synchronizing PersistentVolumeClaim[%s] for dynamic provisioning"
,
claim
.
Name
)
// The claim may have been modified by parallel call to reconcileClaim, load
// the current version.
newClaim
,
err
:=
controller
.
client
.
GetPersistentVolumeClaim
(
claim
.
Namespace
,
claim
.
Name
)
if
err
!=
nil
{
return
fmt
.
Errorf
(
"Cannot reload claim %s/%s: %v"
,
claim
.
Namespace
,
claim
.
Name
,
err
)
}
claim
=
newClaim
err
=
controller
.
claimStore
.
Update
(
claim
)
if
err
!=
nil
{
return
fmt
.
Errorf
(
"Cannot update claim %s/%s: %v"
,
claim
.
Namespace
,
claim
.
Name
,
err
)
}
if
controller
.
provisioner
==
nil
{
if
controller
.
provisioner
==
nil
{
return
fmt
.
Errorf
(
"No provisioner configured for controller"
)
return
fmt
.
Errorf
(
"No provisioner configured for controller"
)
}
}
...
...
pkg/controller/persistentvolume/persistentvolume_provisioner_controller_test.go
View file @
678958a7
...
@@ -105,6 +105,9 @@ func TestReconcileClaim(t *testing.T) {
...
@@ -105,6 +105,9 @@ func TestReconcileClaim(t *testing.T) {
// watch would have added the claim to the store
// watch would have added the claim to the store
controller
.
claimStore
.
Add
(
pvc
)
controller
.
claimStore
.
Add
(
pvc
)
// store it in fake API server
mockClient
.
UpdatePersistentVolumeClaim
(
pvc
)
err
:=
controller
.
reconcileClaim
(
pvc
)
err
:=
controller
.
reconcileClaim
(
pvc
)
if
err
!=
nil
{
if
err
!=
nil
{
t
.
Errorf
(
"Unexpected error: %v"
,
err
)
t
.
Errorf
(
"Unexpected error: %v"
,
err
)
...
@@ -116,6 +119,8 @@ func TestReconcileClaim(t *testing.T) {
...
@@ -116,6 +119,8 @@ func TestReconcileClaim(t *testing.T) {
}
}
pvc
.
Annotations
[
qosProvisioningKey
]
=
"foo"
pvc
.
Annotations
[
qosProvisioningKey
]
=
"foo"
// store it in fake API server
mockClient
.
UpdatePersistentVolumeClaim
(
pvc
)
err
=
controller
.
reconcileClaim
(
pvc
)
err
=
controller
.
reconcileClaim
(
pvc
)
if
err
!=
nil
{
if
err
!=
nil
{
...
@@ -130,6 +135,40 @@ func TestReconcileClaim(t *testing.T) {
...
@@ -130,6 +135,40 @@ func TestReconcileClaim(t *testing.T) {
if
mockClient
.
volume
.
Spec
.
ClaimRef
.
Name
!=
pvc
.
Name
{
if
mockClient
.
volume
.
Spec
.
ClaimRef
.
Name
!=
pvc
.
Name
{
t
.
Errorf
(
"Expected PV to be bound to %s but got %s"
,
mockClient
.
volume
.
Spec
.
ClaimRef
.
Name
,
pvc
.
Name
)
t
.
Errorf
(
"Expected PV to be bound to %s but got %s"
,
mockClient
.
volume
.
Spec
.
ClaimRef
.
Name
,
pvc
.
Name
)
}
}
// the PVC should have correct annotation
if
mockClient
.
claim
.
Annotations
[
pvProvisioningRequiredAnnotationKey
]
!=
pvProvisioningCompletedAnnotationValue
{
t
.
Errorf
(
"Annotation %q not set"
,
pvProvisioningRequiredAnnotationKey
)
}
// Run the syncClaim 2nd time to simulate periodic sweep running in parallel
// to the previous syncClaim. There is a lock in handleUpdateVolume(), so
// they will be called sequentially, but the second call will have old
// version of the claim.
oldPVName
:=
mockClient
.
volume
.
Name
// Make the "old" claim
pvc2
:=
makeTestClaim
()
pvc2
.
Annotations
[
qosProvisioningKey
]
=
"foo"
// Add a dummy annotation so we recognize the claim was updated (i.e.
// stored in mockClient)
pvc2
.
Annotations
[
"test"
]
=
"test"
err
=
controller
.
reconcileClaim
(
pvc2
)
if
err
!=
nil
{
t
.
Errorf
(
"Unexpected error: %v"
,
err
)
}
// The 2nd PVC should be ignored, no new PV was created
if
val
,
found
:=
pvc2
.
Annotations
[
pvProvisioningRequiredAnnotationKey
];
found
{
t
.
Errorf
(
"2nd PVC got unexpected annotation %q: %q"
,
pvProvisioningRequiredAnnotationKey
,
val
)
}
if
mockClient
.
volume
.
Name
!=
oldPVName
{
t
.
Errorf
(
"2nd PVC unexpectedly provisioned a new volume"
)
}
if
_
,
found
:=
mockClient
.
claim
.
Annotations
[
"test"
];
found
{
t
.
Errorf
(
"2nd PVC was unexpectedly updated"
)
}
}
}
func
checkTagValue
(
t
*
testing
.
T
,
tags
map
[
string
]
string
,
tag
string
,
expectedValue
string
)
{
func
checkTagValue
(
t
*
testing
.
T
,
tags
map
[
string
]
string
,
tag
string
,
expectedValue
string
)
{
...
...
test/integration/persistent_volumes_test.go
View file @
678958a7
...
@@ -46,9 +46,11 @@ func TestPersistentVolumeRecycler(t *testing.T) {
...
@@ -46,9 +46,11 @@ func TestPersistentVolumeRecycler(t *testing.T) {
defer
s
.
Close
()
defer
s
.
Close
()
deleteAllEtcdKeys
()
deleteAllEtcdKeys
()
binderClient
:=
clientset
.
NewForConfigOrDie
(
&
client
.
Config
{
Host
:
s
.
URL
,
ContentConfig
:
client
.
ContentConfig
{
GroupVersion
:
testapi
.
Default
.
GroupVersion
()}})
// Use higher QPS and Burst, there is a test for race condition below, which
recyclerClient
:=
clientset
.
NewForConfigOrDie
(
&
client
.
Config
{
Host
:
s
.
URL
,
ContentConfig
:
client
.
ContentConfig
{
GroupVersion
:
testapi
.
Default
.
GroupVersion
()}})
// creates many claims and default values were too low.
testClient
:=
clientset
.
NewForConfigOrDie
(
&
client
.
Config
{
Host
:
s
.
URL
,
ContentConfig
:
client
.
ContentConfig
{
GroupVersion
:
testapi
.
Default
.
GroupVersion
()}})
binderClient
:=
clientset
.
NewForConfigOrDie
(
&
client
.
Config
{
Host
:
s
.
URL
,
ContentConfig
:
client
.
ContentConfig
{
GroupVersion
:
testapi
.
Default
.
GroupVersion
()},
QPS
:
1000
,
Burst
:
100000
})
recyclerClient
:=
clientset
.
NewForConfigOrDie
(
&
client
.
Config
{
Host
:
s
.
URL
,
ContentConfig
:
client
.
ContentConfig
{
GroupVersion
:
testapi
.
Default
.
GroupVersion
()},
QPS
:
1000
,
Burst
:
100000
})
testClient
:=
clientset
.
NewForConfigOrDie
(
&
client
.
Config
{
Host
:
s
.
URL
,
ContentConfig
:
client
.
ContentConfig
{
GroupVersion
:
testapi
.
Default
.
GroupVersion
()},
QPS
:
1000
,
Burst
:
100000
})
host
:=
volume
.
NewFakeVolumeHost
(
"/tmp/fake"
,
nil
,
nil
)
host
:=
volume
.
NewFakeVolumeHost
(
"/tmp/fake"
,
nil
,
nil
)
plugins
:=
[]
volume
.
VolumePlugin
{
&
volume
.
FakeVolumePlugin
{
"plugin-name"
,
host
,
volume
.
VolumeConfig
{},
volume
.
VolumeOptions
{},
0
,
0
}}
plugins
:=
[]
volume
.
VolumePlugin
{
&
volume
.
FakeVolumePlugin
{
"plugin-name"
,
host
,
volume
.
VolumeConfig
{},
volume
.
VolumeOptions
{},
0
,
0
}}
...
...
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