mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-08-01 07:47:56 +00:00
add status subresource for deployment
This commit is contained in:
parent
0884214fe0
commit
8acf01d620
@ -34,8 +34,9 @@ type DeploymentInterface interface {
|
|||||||
List(label labels.Selector, field fields.Selector) (*extensions.DeploymentList, error)
|
List(label labels.Selector, field fields.Selector) (*extensions.DeploymentList, error)
|
||||||
Get(name string) (*extensions.Deployment, error)
|
Get(name string) (*extensions.Deployment, error)
|
||||||
Delete(name string, options *api.DeleteOptions) error
|
Delete(name string, options *api.DeleteOptions) error
|
||||||
Create(Deployment *extensions.Deployment) (*extensions.Deployment, error)
|
Create(*extensions.Deployment) (*extensions.Deployment, error)
|
||||||
Update(Deployment *extensions.Deployment) (*extensions.Deployment, error)
|
Update(*extensions.Deployment) (*extensions.Deployment, error)
|
||||||
|
UpdateStatus(*extensions.Deployment) (*extensions.Deployment, error)
|
||||||
Watch(label labels.Selector, field fields.Selector, opts api.ListOptions) (watch.Interface, error)
|
Watch(label labels.Selector, field fields.Selector, opts api.ListOptions) (watch.Interface, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -93,6 +94,12 @@ func (c *deployments) Update(deployment *extensions.Deployment) (result *extensi
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *deployments) UpdateStatus(deployment *extensions.Deployment) (result *extensions.Deployment, err error) {
|
||||||
|
result = &extensions.Deployment{}
|
||||||
|
err = c.client.Put().Namespace(c.ns).Resource("deployments").Name(deployment.Name).SubResource("status").Body(deployment).Do().Into(result)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// Watch returns a watch.Interface that watches the requested deployments.
|
// Watch returns a watch.Interface that watches the requested deployments.
|
||||||
func (c *deployments) Watch(label labels.Selector, field fields.Selector, opts api.ListOptions) (watch.Interface, error) {
|
func (c *deployments) Watch(label labels.Selector, field fields.Selector, opts api.ListOptions) (watch.Interface, error) {
|
||||||
return c.client.Get().
|
return c.client.Get().
|
||||||
|
@ -124,6 +124,27 @@ func TestDeploymentUpdate(t *testing.T) {
|
|||||||
c.Validate(t, response, err)
|
c.Validate(t, response, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestDeploymentUpdateStatus(t *testing.T) {
|
||||||
|
ns := api.NamespaceDefault
|
||||||
|
deployment := &extensions.Deployment{
|
||||||
|
ObjectMeta: api.ObjectMeta{
|
||||||
|
Name: "abc",
|
||||||
|
Namespace: ns,
|
||||||
|
ResourceVersion: "1",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
c := &testClient{
|
||||||
|
Request: testRequest{
|
||||||
|
Method: "PUT",
|
||||||
|
Path: testapi.Extensions.ResourcePath(getDeploymentsResoureName(), ns, "abc") + "/status",
|
||||||
|
Query: buildQueryValues(nil),
|
||||||
|
},
|
||||||
|
Response: Response{StatusCode: 200, Body: deployment},
|
||||||
|
}
|
||||||
|
response, err := c.Setup(t).Deployments(ns).UpdateStatus(deployment)
|
||||||
|
c.Validate(t, response, err)
|
||||||
|
}
|
||||||
|
|
||||||
func TestDeploymentDelete(t *testing.T) {
|
func TestDeploymentDelete(t *testing.T) {
|
||||||
ns := api.NamespaceDefault
|
ns := api.NamespaceDefault
|
||||||
c := &testClient{
|
c := &testClient{
|
||||||
|
@ -72,6 +72,15 @@ func (c *FakeDeployments) Update(deployment *extensions.Deployment) (*extensions
|
|||||||
return obj.(*extensions.Deployment), err
|
return obj.(*extensions.Deployment), err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *FakeDeployments) UpdateStatus(deployment *extensions.Deployment) (*extensions.Deployment, error) {
|
||||||
|
obj, err := c.Fake.Invokes(NewUpdateSubresourceAction("deployments", "status", c.Namespace, deployment), deployment)
|
||||||
|
if obj == nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return obj.(*extensions.Deployment), err
|
||||||
|
}
|
||||||
|
|
||||||
func (c *FakeDeployments) Delete(name string, options *api.DeleteOptions) error {
|
func (c *FakeDeployments) Delete(name string, options *api.DeleteOptions) error {
|
||||||
_, err := c.Fake.Invokes(NewDeleteAction("deployments", c.Namespace, name), &extensions.Deployment{})
|
_, err := c.Fake.Invokes(NewDeleteAction("deployments", c.Namespace, name), &extensions.Deployment{})
|
||||||
return err
|
return err
|
||||||
|
@ -251,7 +251,7 @@ func (d *DeploymentController) updateDeploymentStatus(allRCs []*api.ReplicationC
|
|||||||
Replicas: totalReplicas,
|
Replicas: totalReplicas,
|
||||||
UpdatedReplicas: updatedReplicas,
|
UpdatedReplicas: updatedReplicas,
|
||||||
}
|
}
|
||||||
_, err := d.updateDeployment(&newDeployment)
|
_, err := d.client.Extensions().Deployments(deployment.ObjectMeta.Namespace).UpdateStatus(&newDeployment)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1081,6 +1081,7 @@ func (m *Master) experimental(c *Config) *apiserver.APIGroupVersion {
|
|||||||
if isEnabled("deployments") {
|
if isEnabled("deployments") {
|
||||||
deploymentStorage := deploymentetcd.NewStorage(dbClient("deployments"))
|
deploymentStorage := deploymentetcd.NewStorage(dbClient("deployments"))
|
||||||
storage["deployments"] = deploymentStorage.Deployment
|
storage["deployments"] = deploymentStorage.Deployment
|
||||||
|
storage["deployments/status"] = deploymentStorage.Status
|
||||||
storage["deployments/scale"] = deploymentStorage.Scale
|
storage["deployments/scale"] = deploymentStorage.Scale
|
||||||
}
|
}
|
||||||
if isEnabled("jobs") {
|
if isEnabled("jobs") {
|
||||||
|
@ -35,15 +35,17 @@ import (
|
|||||||
// DeploymentStorage includes dummy storage for Deployments and for Scale subresource.
|
// DeploymentStorage includes dummy storage for Deployments and for Scale subresource.
|
||||||
type DeploymentStorage struct {
|
type DeploymentStorage struct {
|
||||||
Deployment *REST
|
Deployment *REST
|
||||||
|
Status *StatusREST
|
||||||
Scale *ScaleREST
|
Scale *ScaleREST
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewStorage(s storage.Interface) DeploymentStorage {
|
func NewStorage(s storage.Interface) DeploymentStorage {
|
||||||
deploymentRest := NewREST(s)
|
deploymentRest, deploymentStatusRest := NewREST(s)
|
||||||
deploymentRegistry := deployment.NewRegistry(deploymentRest)
|
deploymentRegistry := deployment.NewRegistry(deploymentRest)
|
||||||
|
|
||||||
return DeploymentStorage{
|
return DeploymentStorage{
|
||||||
Deployment: deploymentRest,
|
Deployment: deploymentRest,
|
||||||
|
Status: deploymentStatusRest,
|
||||||
Scale: &ScaleREST{registry: &deploymentRegistry},
|
Scale: &ScaleREST{registry: &deploymentRegistry},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -53,7 +55,7 @@ type REST struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// NewREST returns a RESTStorage object that will work against deployments.
|
// NewREST returns a RESTStorage object that will work against deployments.
|
||||||
func NewREST(s storage.Interface) *REST {
|
func NewREST(s storage.Interface) (*REST, *StatusREST) {
|
||||||
prefix := "/deployments"
|
prefix := "/deployments"
|
||||||
store := &etcdgeneric.Etcd{
|
store := &etcdgeneric.Etcd{
|
||||||
NewFunc: func() runtime.Object { return &extensions.Deployment{} },
|
NewFunc: func() runtime.Object { return &extensions.Deployment{} },
|
||||||
@ -87,7 +89,23 @@ func NewREST(s storage.Interface) *REST {
|
|||||||
|
|
||||||
Storage: s,
|
Storage: s,
|
||||||
}
|
}
|
||||||
return &REST{store}
|
statusStore := *store
|
||||||
|
statusStore.UpdateStrategy = deployment.StatusStrategy
|
||||||
|
return &REST{store}, &StatusREST{store: &statusStore}
|
||||||
|
}
|
||||||
|
|
||||||
|
// StatusREST implements the REST endpoint for changing the status of a deployment
|
||||||
|
type StatusREST struct {
|
||||||
|
store *etcdgeneric.Etcd
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *StatusREST) New() runtime.Object {
|
||||||
|
return &extensions.Deployment{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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)
|
||||||
}
|
}
|
||||||
|
|
||||||
type ScaleREST struct {
|
type ScaleREST struct {
|
||||||
|
@ -236,3 +236,39 @@ func TestScaleUpdate(t *testing.T) {
|
|||||||
t.Errorf("wrong replicas count expected: %d got: %d", replicas, deployment.Spec.Replicas)
|
t.Errorf("wrong replicas count expected: %d got: %d", replicas, deployment.Spec.Replicas)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestStatusUpdate(t *testing.T) {
|
||||||
|
storage, fakeClient := newStorage(t)
|
||||||
|
|
||||||
|
ctx := api.WithNamespace(api.NewContext(), namespace)
|
||||||
|
key := etcdtest.AddPrefix("/deployments/" + namespace + "/" + name)
|
||||||
|
if _, err := fakeClient.Set(key, runtime.EncodeOrDie(testapi.Extensions.Codec(), &validDeployment), 0); err != nil {
|
||||||
|
t.Fatalf("unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
update := extensions.Deployment{
|
||||||
|
ObjectMeta: validDeployment.ObjectMeta,
|
||||||
|
Spec: extensions.DeploymentSpec{
|
||||||
|
Replicas: 100,
|
||||||
|
},
|
||||||
|
Status: extensions.DeploymentStatus{
|
||||||
|
Replicas: 100,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, _, err := storage.Status.Update(ctx, &update); err != nil {
|
||||||
|
t.Fatalf("unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
response, err := fakeClient.Get(key, false, false)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var deployment extensions.Deployment
|
||||||
|
testapi.Extensions.Codec().DecodeInto([]byte(response.Node.Value), &deployment)
|
||||||
|
if deployment.Spec.Replicas != 7 {
|
||||||
|
t.Errorf("we expected .spec.replicas to not be updated but it was updated to %v", deployment.Spec.Replicas)
|
||||||
|
}
|
||||||
|
if deployment.Status.Replicas != 100 {
|
||||||
|
t.Errorf("we expected .status.replicas to be updated to 100 but it was %v", deployment.Status.Replicas)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -46,6 +46,8 @@ func (deploymentStrategy) NamespaceScoped() bool {
|
|||||||
|
|
||||||
// PrepareForCreate clears fields that are not allowed to be set by end users on creation.
|
// PrepareForCreate clears fields that are not allowed to be set by end users on creation.
|
||||||
func (deploymentStrategy) PrepareForCreate(obj runtime.Object) {
|
func (deploymentStrategy) PrepareForCreate(obj runtime.Object) {
|
||||||
|
deployment := obj.(*extensions.Deployment)
|
||||||
|
deployment.Status = extensions.DeploymentStatus{}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Validate validates a new deployment.
|
// Validate validates a new deployment.
|
||||||
@ -61,6 +63,9 @@ func (deploymentStrategy) AllowCreateOnUpdate() bool {
|
|||||||
|
|
||||||
// PrepareForUpdate clears fields that are not allowed to be set by end users on update.
|
// PrepareForUpdate clears fields that are not allowed to be set by end users on update.
|
||||||
func (deploymentStrategy) PrepareForUpdate(obj, old runtime.Object) {
|
func (deploymentStrategy) PrepareForUpdate(obj, old runtime.Object) {
|
||||||
|
newDeployment := obj.(*extensions.Deployment)
|
||||||
|
oldDeployment := old.(*extensions.Deployment)
|
||||||
|
newDeployment.Status = oldDeployment.Status
|
||||||
}
|
}
|
||||||
|
|
||||||
// ValidateUpdate is the default update validation for an end user.
|
// ValidateUpdate is the default update validation for an end user.
|
||||||
@ -72,6 +77,24 @@ func (deploymentStrategy) AllowUnconditionalUpdate() bool {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type deploymentStatusStrategy struct {
|
||||||
|
deploymentStrategy
|
||||||
|
}
|
||||||
|
|
||||||
|
var StatusStrategy = deploymentStatusStrategy{Strategy}
|
||||||
|
|
||||||
|
// PrepareForUpdate clears fields that are not allowed to be set by end users on update of status
|
||||||
|
func (deploymentStatusStrategy) PrepareForUpdate(obj, old runtime.Object) {
|
||||||
|
newDeployment := obj.(*extensions.Deployment)
|
||||||
|
oldDeployment := old.(*extensions.Deployment)
|
||||||
|
newDeployment.Spec = oldDeployment.Spec
|
||||||
|
}
|
||||||
|
|
||||||
|
// ValidateUpdate is the default update validation for an end user updating status
|
||||||
|
func (deploymentStatusStrategy) ValidateUpdate(ctx api.Context, obj, old runtime.Object) errs.ValidationErrorList {
|
||||||
|
return validation.ValidateDeploymentUpdate(old.(*extensions.Deployment), obj.(*extensions.Deployment))
|
||||||
|
}
|
||||||
|
|
||||||
// DeploymentToSelectableFields returns a field set that represents the object.
|
// DeploymentToSelectableFields returns a field set that represents the object.
|
||||||
func DeploymentToSelectableFields(deployment *extensions.Deployment) fields.Set {
|
func DeploymentToSelectableFields(deployment *extensions.Deployment) fields.Set {
|
||||||
return generic.ObjectMetaFieldsSet(deployment.ObjectMeta)
|
return generic.ObjectMetaFieldsSet(deployment.ObjectMeta)
|
||||||
|
Loading…
Reference in New Issue
Block a user