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
e3abcf71
Commit
e3abcf71
authored
Sep 25, 2015
by
Brian Grant
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #14535 from derekwaynecarr/daemon_sets_status
DaemonSets adds a Status subresource
parents
1455c7b5
aead9d32
Hide whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
179 additions
and
22 deletions
+179
-22
validation.go
pkg/apis/experimental/validation/validation.go
+20
-10
validation_test.go
pkg/apis/experimental/validation/validation_test.go
+64
-0
daemon_sets.go
pkg/client/unversioned/daemon_sets.go
+8
-0
daemon_sets_test.go
pkg/client/unversioned/daemon_sets_test.go
+28
-0
fake_daemon_sets.go
pkg/client/unversioned/testclient/fake_daemon_sets.go
+8
-0
controller.go
pkg/controller/daemon/controller.go
+1
-1
master.go
pkg/master/master.go
+2
-1
etcd.go
pkg/registry/daemonset/etcd/etcd.go
+18
-2
etcd_test.go
pkg/registry/daemonset/etcd/etcd_test.go
+11
-8
strategy.go
pkg/registry/daemonset/strategy.go
+19
-0
No files found.
pkg/apis/experimental/validation/validation.go
View file @
e3abcf71
...
...
@@ -114,6 +114,23 @@ func ValidateDaemonSetUpdate(oldController, controller *experimental.DaemonSet)
return
allErrs
}
// validateDaemonSetStatus validates a DaemonSetStatus
func
validateDaemonSetStatus
(
status
*
experimental
.
DaemonSetStatus
)
errs
.
ValidationErrorList
{
allErrs
:=
errs
.
ValidationErrorList
{}
allErrs
=
append
(
allErrs
,
apivalidation
.
ValidatePositiveField
(
int64
(
status
.
CurrentNumberScheduled
),
"currentNumberScheduled"
)
...
)
allErrs
=
append
(
allErrs
,
apivalidation
.
ValidatePositiveField
(
int64
(
status
.
NumberMisscheduled
),
"numberMisscheduled"
)
...
)
allErrs
=
append
(
allErrs
,
apivalidation
.
ValidatePositiveField
(
int64
(
status
.
DesiredNumberScheduled
),
"desiredNumberScheduled"
)
...
)
return
allErrs
}
// ValidateDaemonSetStatus validates tests if required fields in the DaemonSet Status section
func
ValidateDaemonSetStatusUpdate
(
controller
,
oldController
*
experimental
.
DaemonSet
)
errs
.
ValidationErrorList
{
allErrs
:=
errs
.
ValidationErrorList
{}
allErrs
=
append
(
allErrs
,
apivalidation
.
ValidateObjectMetaUpdate
(
&
controller
.
ObjectMeta
,
&
oldController
.
ObjectMeta
)
.
Prefix
(
"metadata"
)
...
)
allErrs
=
append
(
allErrs
,
validateDaemonSetStatus
(
&
controller
.
Status
)
...
)
return
allErrs
}
// ValidateDaemonSetTemplateUpdate tests that certain fields in the daemon set's pod template are not updated.
func
ValidateDaemonSetTemplateUpdate
(
oldPodTemplate
,
podTemplate
*
api
.
PodTemplateSpec
)
errs
.
ValidationErrorList
{
allErrs
:=
errs
.
ValidationErrorList
{}
...
...
@@ -314,16 +331,9 @@ func ValidateJobSpec(spec *experimental.JobSpec) errs.ValidationErrorList {
func
ValidateJobStatus
(
status
*
experimental
.
JobStatus
)
errs
.
ValidationErrorList
{
allErrs
:=
errs
.
ValidationErrorList
{}
if
status
.
Active
<
0
{
allErrs
=
append
(
allErrs
,
errs
.
NewFieldInvalid
(
"active"
,
status
.
Active
,
isNegativeErrorMsg
))
}
if
status
.
Successful
<
0
{
allErrs
=
append
(
allErrs
,
errs
.
NewFieldInvalid
(
"successful"
,
status
.
Successful
,
isNegativeErrorMsg
))
}
if
status
.
Unsuccessful
<
0
{
allErrs
=
append
(
allErrs
,
errs
.
NewFieldInvalid
(
"unsuccessful"
,
status
.
Unsuccessful
,
isNegativeErrorMsg
))
}
allErrs
=
append
(
allErrs
,
apivalidation
.
ValidatePositiveField
(
int64
(
status
.
Active
),
"active"
)
...
)
allErrs
=
append
(
allErrs
,
apivalidation
.
ValidatePositiveField
(
int64
(
status
.
Successful
),
"successful"
)
...
)
allErrs
=
append
(
allErrs
,
apivalidation
.
ValidatePositiveField
(
int64
(
status
.
Unsuccessful
),
"unsuccessful"
)
...
)
return
allErrs
}
...
...
pkg/apis/experimental/validation/validation_test.go
View file @
e3abcf71
...
...
@@ -130,6 +130,70 @@ func TestValidateHorizontalPodAutoscaler(t *testing.T) {
}
}
func
TestValidateDaemonSetStatusUpdate
(
t
*
testing
.
T
)
{
type
dsUpdateTest
struct
{
old
experimental
.
DaemonSet
update
experimental
.
DaemonSet
}
successCases
:=
[]
dsUpdateTest
{
{
old
:
experimental
.
DaemonSet
{
ObjectMeta
:
api
.
ObjectMeta
{
Name
:
"abc"
,
Namespace
:
api
.
NamespaceDefault
},
Status
:
experimental
.
DaemonSetStatus
{
CurrentNumberScheduled
:
1
,
NumberMisscheduled
:
2
,
DesiredNumberScheduled
:
3
,
},
},
update
:
experimental
.
DaemonSet
{
ObjectMeta
:
api
.
ObjectMeta
{
Name
:
"abc"
,
Namespace
:
api
.
NamespaceDefault
},
Status
:
experimental
.
DaemonSetStatus
{
CurrentNumberScheduled
:
1
,
NumberMisscheduled
:
1
,
DesiredNumberScheduled
:
3
,
},
},
},
}
for
_
,
successCase
:=
range
successCases
{
successCase
.
old
.
ObjectMeta
.
ResourceVersion
=
"1"
successCase
.
update
.
ObjectMeta
.
ResourceVersion
=
"1"
if
errs
:=
ValidateDaemonSetStatusUpdate
(
&
successCase
.
update
,
&
successCase
.
old
);
len
(
errs
)
!=
0
{
t
.
Errorf
(
"expected success: %v"
,
errs
)
}
}
errorCases
:=
map
[
string
]
dsUpdateTest
{
"negative values"
:
{
old
:
experimental
.
DaemonSet
{
ObjectMeta
:
api
.
ObjectMeta
{
Name
:
"abc"
,
Namespace
:
api
.
NamespaceDefault
},
Status
:
experimental
.
DaemonSetStatus
{
CurrentNumberScheduled
:
1
,
NumberMisscheduled
:
2
,
DesiredNumberScheduled
:
3
,
},
},
update
:
experimental
.
DaemonSet
{
ObjectMeta
:
api
.
ObjectMeta
{
Name
:
"abc"
,
Namespace
:
api
.
NamespaceDefault
},
Status
:
experimental
.
DaemonSetStatus
{
CurrentNumberScheduled
:
-
1
,
NumberMisscheduled
:
-
1
,
DesiredNumberScheduled
:
-
3
,
},
},
},
}
for
testName
,
errorCase
:=
range
errorCases
{
if
errs
:=
ValidateDaemonSetStatusUpdate
(
&
errorCase
.
old
,
&
errorCase
.
update
);
len
(
errs
)
==
0
{
t
.
Errorf
(
"expected failure: %s"
,
testName
)
}
}
}
func
TestValidateDaemonSetUpdate
(
t
*
testing
.
T
)
{
validSelector
:=
map
[
string
]
string
{
"a"
:
"b"
}
validSelector2
:=
map
[
string
]
string
{
"c"
:
"d"
}
...
...
pkg/client/unversioned/daemon_sets.go
View file @
e3abcf71
...
...
@@ -33,6 +33,7 @@ type DaemonSetInterface interface {
Get
(
name
string
)
(
*
experimental
.
DaemonSet
,
error
)
Create
(
ctrl
*
experimental
.
DaemonSet
)
(
*
experimental
.
DaemonSet
,
error
)
Update
(
ctrl
*
experimental
.
DaemonSet
)
(
*
experimental
.
DaemonSet
,
error
)
UpdateStatus
(
ctrl
*
experimental
.
DaemonSet
)
(
*
experimental
.
DaemonSet
,
error
)
Delete
(
name
string
)
error
Watch
(
label
labels
.
Selector
,
field
fields
.
Selector
,
resourceVersion
string
)
(
watch
.
Interface
,
error
)
}
...
...
@@ -77,6 +78,13 @@ func (c *daemonSets) Update(daemon *experimental.DaemonSet) (result *experimenta
return
}
// UpdateStatus updates an existing daemon set status
func
(
c
*
daemonSets
)
UpdateStatus
(
daemon
*
experimental
.
DaemonSet
)
(
result
*
experimental
.
DaemonSet
,
err
error
)
{
result
=
&
experimental
.
DaemonSet
{}
err
=
c
.
r
.
Put
()
.
Namespace
(
c
.
ns
)
.
Resource
(
"daemonsets"
)
.
Name
(
daemon
.
Name
)
.
SubResource
(
"status"
)
.
Body
(
daemon
)
.
Do
()
.
Into
(
result
)
return
}
// Delete deletes an existing daemon set.
func
(
c
*
daemonSets
)
Delete
(
name
string
)
error
{
return
c
.
r
.
Delete
()
.
Namespace
(
c
.
ns
)
.
Resource
(
"daemonsets"
)
.
Name
(
name
)
.
Do
()
.
Error
()
...
...
pkg/client/unversioned/daemon_sets_test.go
View file @
e3abcf71
...
...
@@ -122,6 +122,34 @@ func TestUpdateDaemonSet(t *testing.T) {
c
.
Validate
(
t
,
receivedDaemonSet
,
err
)
}
func
TestUpdateDaemonSetUpdateStatus
(
t
*
testing
.
T
)
{
ns
:=
api
.
NamespaceDefault
requestDaemonSet
:=
&
experimental
.
DaemonSet
{
ObjectMeta
:
api
.
ObjectMeta
{
Name
:
"foo"
,
ResourceVersion
:
"1"
},
}
c
:=
&
testClient
{
Request
:
testRequest
{
Method
:
"PUT"
,
Path
:
testapi
.
Experimental
.
ResourcePath
(
getDSResourceName
(),
ns
,
"foo"
)
+
"/status"
,
Query
:
buildQueryValues
(
nil
)},
Response
:
Response
{
StatusCode
:
200
,
Body
:
&
experimental
.
DaemonSet
{
ObjectMeta
:
api
.
ObjectMeta
{
Name
:
"foo"
,
Labels
:
map
[
string
]
string
{
"foo"
:
"bar"
,
"name"
:
"baz"
,
},
},
Spec
:
experimental
.
DaemonSetSpec
{
Template
:
&
api
.
PodTemplateSpec
{},
},
Status
:
experimental
.
DaemonSetStatus
{},
},
},
}
receivedDaemonSet
,
err
:=
c
.
Setup
(
t
)
.
Experimental
()
.
DaemonSets
(
ns
)
.
UpdateStatus
(
requestDaemonSet
)
c
.
Validate
(
t
,
receivedDaemonSet
,
err
)
}
func
TestDeleteDaemon
(
t
*
testing
.
T
)
{
ns
:=
api
.
NamespaceDefault
c
:=
&
testClient
{
...
...
pkg/client/unversioned/testclient/fake_daemon_sets.go
View file @
e3abcf71
...
...
@@ -66,6 +66,14 @@ func (c *FakeDaemonSets) Update(daemon *experimental.DaemonSet) (*experimental.D
return
obj
.
(
*
experimental
.
DaemonSet
),
err
}
func
(
c
*
FakeDaemonSets
)
UpdateStatus
(
daemon
*
experimental
.
DaemonSet
)
(
*
experimental
.
DaemonSet
,
error
)
{
obj
,
err
:=
c
.
Fake
.
Invokes
(
NewUpdateSubresourceAction
(
"daemonsets"
,
"status"
,
c
.
Namespace
,
daemon
),
&
experimental
.
DaemonSet
{})
if
obj
==
nil
{
return
nil
,
err
}
return
obj
.
(
*
experimental
.
DaemonSet
),
err
}
func
(
c
*
FakeDaemonSets
)
Delete
(
name
string
)
error
{
_
,
err
:=
c
.
Fake
.
Invokes
(
NewDeleteAction
(
"daemonsets"
,
c
.
Namespace
,
name
),
&
experimental
.
DaemonSet
{})
return
err
...
...
pkg/controller/daemon/controller.go
View file @
e3abcf71
...
...
@@ -400,7 +400,7 @@ func storeDaemonSetStatus(dsClient client.DaemonSetInterface, ds *experimental.D
ds
.
Status
.
DesiredNumberScheduled
=
desiredNumberScheduled
ds
.
Status
.
CurrentNumberScheduled
=
currentNumberScheduled
ds
.
Status
.
NumberMisscheduled
=
numberMisscheduled
_
,
updateErr
=
dsClient
.
Update
(
ds
)
_
,
updateErr
=
dsClient
.
Update
Status
(
ds
)
if
updateErr
==
nil
{
// successful update
return
nil
...
...
pkg/master/master.go
View file @
e3abcf71
...
...
@@ -958,7 +958,7 @@ func (m *Master) experimental(c *Config) *apiserver.APIGroupVersion {
controllerStorage
:=
expcontrolleretcd
.
NewStorage
(
c
.
ExpDatabaseStorage
)
autoscalerStorage
:=
horizontalpodautoscaleretcd
.
NewREST
(
c
.
ExpDatabaseStorage
)
thirdPartyResourceStorage
:=
thirdpartyresourceetcd
.
NewREST
(
c
.
ExpDatabaseStorage
)
daemonSetStorage
:=
daemonetcd
.
NewREST
(
c
.
ExpDatabaseStorage
)
daemonSetStorage
,
daemonSetStatusStorage
:=
daemonetcd
.
NewREST
(
c
.
ExpDatabaseStorage
)
deploymentStorage
:=
deploymentetcd
.
NewStorage
(
c
.
ExpDatabaseStorage
)
jobStorage
,
jobStatusStorage
:=
jobetcd
.
NewREST
(
c
.
ExpDatabaseStorage
)
...
...
@@ -979,6 +979,7 @@ func (m *Master) experimental(c *Config) *apiserver.APIGroupVersion {
strings
.
ToLower
(
"horizontalpodautoscalers"
)
:
autoscalerStorage
,
strings
.
ToLower
(
"thirdpartyresources"
)
:
thirdPartyResourceStorage
,
strings
.
ToLower
(
"daemonsets"
)
:
daemonSetStorage
,
strings
.
ToLower
(
"daemonsets/status"
)
:
daemonSetStatusStorage
,
strings
.
ToLower
(
"deployments"
)
:
deploymentStorage
.
Deployment
,
strings
.
ToLower
(
"deployments/scale"
)
:
deploymentStorage
.
Scale
,
strings
.
ToLower
(
"jobs"
)
:
jobStorage
,
...
...
pkg/registry/daemonset/etcd/etcd.go
View file @
e3abcf71
...
...
@@ -37,7 +37,7 @@ type REST struct {
var
daemonPrefix
=
"/daemonsets"
// NewREST returns a RESTStorage object that will work against DaemonSets.
func
NewREST
(
s
storage
.
Interface
)
*
REST
{
func
NewREST
(
s
storage
.
Interface
)
(
*
REST
,
*
StatusREST
)
{
store
:=
&
etcdgeneric
.
Etcd
{
NewFunc
:
func
()
runtime
.
Object
{
return
&
experimental
.
DaemonSet
{}
},
...
...
@@ -71,6 +71,22 @@ func NewREST(s storage.Interface) *REST {
Storage
:
s
,
}
statusStore
:=
*
store
statusStore
.
UpdateStrategy
=
daemonset
.
StatusStrategy
return
&
REST
{
store
}
return
&
REST
{
store
},
&
StatusREST
{
store
:
&
statusStore
}
}
// StatusREST implements the REST endpoint for changing the status of a daemonset
type
StatusREST
struct
{
store
*
etcdgeneric
.
Etcd
}
func
(
r
*
StatusREST
)
New
()
runtime
.
Object
{
return
&
experimental
.
DaemonSet
{}
}
// Update alters the status subset of an object.
func
(
r
*
StatusREST
)
Update
(
ctx
api
.
Context
,
obj
runtime
.
Object
)
(
runtime
.
Object
,
bool
,
error
)
{
return
r
.
store
.
Update
(
ctx
,
obj
)
}
pkg/registry/daemonset/etcd/etcd_test.go
View file @
e3abcf71
...
...
@@ -28,9 +28,10 @@ import (
"k8s.io/kubernetes/pkg/tools"
)
func
newStorage
(
t
*
testing
.
T
)
(
*
REST
,
*
tools
.
FakeEtcdClient
)
{
func
newStorage
(
t
*
testing
.
T
)
(
*
REST
,
*
StatusREST
,
*
tools
.
FakeEtcdClient
)
{
etcdStorage
,
fakeClient
:=
registrytest
.
NewEtcdStorage
(
t
,
"experimental"
)
return
NewREST
(
etcdStorage
),
fakeClient
storage
,
statusStorage
:=
NewREST
(
etcdStorage
)
return
storage
,
statusStorage
,
fakeClient
}
func
newValidDaemonSet
()
*
experimental
.
DaemonSet
{
...
...
@@ -64,7 +65,7 @@ func newValidDaemonSet() *experimental.DaemonSet {
var
validDaemonSet
=
newValidDaemonSet
()
func
TestCreate
(
t
*
testing
.
T
)
{
storage
,
fakeClient
:=
newStorage
(
t
)
storage
,
_
,
fakeClient
:=
newStorage
(
t
)
test
:=
registrytest
.
New
(
t
,
fakeClient
,
storage
.
Etcd
)
ds
:=
newValidDaemonSet
()
ds
.
ObjectMeta
=
api
.
ObjectMeta
{}
...
...
@@ -82,7 +83,7 @@ func TestCreate(t *testing.T) {
}
func
TestUpdate
(
t
*
testing
.
T
)
{
storage
,
fakeClient
:=
newStorage
(
t
)
storage
,
_
,
fakeClient
:=
newStorage
(
t
)
test
:=
registrytest
.
New
(
t
,
fakeClient
,
storage
.
Etcd
)
test
.
TestUpdate
(
// valid
...
...
@@ -118,25 +119,25 @@ func TestUpdate(t *testing.T) {
}
func
TestDelete
(
t
*
testing
.
T
)
{
storage
,
fakeClient
:=
newStorage
(
t
)
storage
,
_
,
fakeClient
:=
newStorage
(
t
)
test
:=
registrytest
.
New
(
t
,
fakeClient
,
storage
.
Etcd
)
test
.
TestDelete
(
newValidDaemonSet
())
}
func
TestGet
(
t
*
testing
.
T
)
{
storage
,
fakeClient
:=
newStorage
(
t
)
storage
,
_
,
fakeClient
:=
newStorage
(
t
)
test
:=
registrytest
.
New
(
t
,
fakeClient
,
storage
.
Etcd
)
test
.
TestGet
(
newValidDaemonSet
())
}
func
TestList
(
t
*
testing
.
T
)
{
storage
,
fakeClient
:=
newStorage
(
t
)
storage
,
_
,
fakeClient
:=
newStorage
(
t
)
test
:=
registrytest
.
New
(
t
,
fakeClient
,
storage
.
Etcd
)
test
.
TestList
(
newValidDaemonSet
())
}
func
TestWatch
(
t
*
testing
.
T
)
{
storage
,
fakeClient
:=
newStorage
(
t
)
storage
,
_
,
fakeClient
:=
newStorage
(
t
)
test
:=
registrytest
.
New
(
t
,
fakeClient
,
storage
.
Etcd
)
test
.
TestWatch
(
validDaemonSet
,
...
...
@@ -160,3 +161,5 @@ func TestWatch(t *testing.T) {
},
)
}
// TODO TestUpdateStatus
pkg/registry/daemonset/strategy.go
View file @
e3abcf71
...
...
@@ -57,6 +57,9 @@ func (daemonSetStrategy) PrepareForUpdate(obj, old runtime.Object) {
newDaemonSet
:=
obj
.
(
*
experimental
.
DaemonSet
)
oldDaemonSet
:=
old
.
(
*
experimental
.
DaemonSet
)
// update is not allowed to set status
newDaemonSet
.
Status
=
oldDaemonSet
.
Status
// Any changes to the spec increment the generation number, any changes to the
// status should reflect the generation number of the corresponding object. We push
// the burden of managing the status onto the clients because we can't (in general)
...
...
@@ -120,3 +123,19 @@ func MatchDaemonSet(label labels.Selector, field fields.Selector) generic.Matche
},
}
}
type
daemonSetStatusStrategy
struct
{
daemonSetStrategy
}
var
StatusStrategy
=
daemonSetStatusStrategy
{
Strategy
}
func
(
daemonSetStatusStrategy
)
PrepareForUpdate
(
obj
,
old
runtime
.
Object
)
{
newDaemonSet
:=
obj
.
(
*
experimental
.
DaemonSet
)
oldDaemonSet
:=
old
.
(
*
experimental
.
DaemonSet
)
newDaemonSet
.
Spec
=
oldDaemonSet
.
Spec
}
func
(
daemonSetStatusStrategy
)
ValidateUpdate
(
ctx
api
.
Context
,
obj
,
old
runtime
.
Object
)
fielderrors
.
ValidationErrorList
{
return
validation
.
ValidateDaemonSetStatusUpdate
(
obj
.
(
*
experimental
.
DaemonSet
),
old
.
(
*
experimental
.
DaemonSet
))
}
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