Merge pull request #15809 from mikedanese/deploy
Auto commit by PR queue bot
This commit is contained in:
		| @@ -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) | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 k8s-merge-robot
					k8s-merge-robot