mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-29 22:46:12 +00:00
extensions: support paused deployments
This commit adds support for paused deployments so a user can choose when to run a deployment that exists in the system instead of having the deployment controller automatically reconciling it after every change or sync interval.
This commit is contained in:
parent
a14d0fd641
commit
436d2677f9
@ -228,6 +228,10 @@ type DeploymentSpec struct {
|
||||
// Value of this key is hash of DeploymentSpec.PodTemplateSpec.
|
||||
// No label is added if this is set to empty string.
|
||||
UniqueLabelKey string `json:"uniqueLabelKey,omitempty"`
|
||||
|
||||
// Indicates that the deployment is paused and will not be processed by the
|
||||
// deployment controller.
|
||||
Paused bool `json:"paused,omitempty"`
|
||||
}
|
||||
|
||||
const (
|
||||
|
@ -262,6 +262,7 @@ func Convert_extensions_DeploymentSpec_To_v1beta1_DeploymentSpec(in *extensions.
|
||||
}
|
||||
out.UniqueLabelKey = new(string)
|
||||
*out.UniqueLabelKey = in.UniqueLabelKey
|
||||
out.Paused = in.Paused
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -289,6 +290,7 @@ func Convert_v1beta1_DeploymentSpec_To_extensions_DeploymentSpec(in *DeploymentS
|
||||
if in.UniqueLabelKey != nil {
|
||||
out.UniqueLabelKey = *in.UniqueLabelKey
|
||||
}
|
||||
out.Paused = in.Paused
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -213,6 +213,10 @@ type DeploymentSpec struct {
|
||||
// Value of this key is hash of DeploymentSpec.PodTemplateSpec.
|
||||
// No label is added if this is set to empty string.
|
||||
UniqueLabelKey *string `json:"uniqueLabelKey,omitempty"`
|
||||
|
||||
// Indicates that the deployment is paused and will not be processed by the
|
||||
// deployment controller.
|
||||
Paused bool `json:"paused,omitempty"`
|
||||
}
|
||||
|
||||
const (
|
||||
|
@ -410,6 +410,11 @@ func (dc *DeploymentController) syncDeployment(key string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
if d.Spec.Paused {
|
||||
// Ignore paused deployments
|
||||
glog.V(4).Infof("Ignoring paused deployment %s/%s", d.Namespace, d.Name)
|
||||
return nil
|
||||
}
|
||||
switch d.Spec.Strategy.Type {
|
||||
case extensions.RecreateDeploymentStrategyType:
|
||||
return dc.syncRecreateDeployment(d)
|
||||
|
@ -75,21 +75,6 @@ func validNewDeployment() *extensions.Deployment {
|
||||
|
||||
var validDeployment = *validNewDeployment()
|
||||
|
||||
func validNewScale() *extensions.Scale {
|
||||
return &extensions.Scale{
|
||||
ObjectMeta: api.ObjectMeta{Name: name, Namespace: namespace},
|
||||
Spec: extensions.ScaleSpec{
|
||||
Replicas: validDeployment.Spec.Replicas,
|
||||
},
|
||||
Status: extensions.ScaleStatus{
|
||||
Replicas: validDeployment.Status.Replicas,
|
||||
Selector: validDeployment.Spec.Template.Labels,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
var validScale = *validNewScale()
|
||||
|
||||
func TestCreate(t *testing.T) {
|
||||
storage, server := newStorage(t)
|
||||
defer server.Terminate(t)
|
||||
@ -192,6 +177,21 @@ func TestWatch(t *testing.T) {
|
||||
)
|
||||
}
|
||||
|
||||
func validNewScale() *extensions.Scale {
|
||||
return &extensions.Scale{
|
||||
ObjectMeta: api.ObjectMeta{Name: name, Namespace: namespace},
|
||||
Spec: extensions.ScaleSpec{
|
||||
Replicas: validDeployment.Spec.Replicas,
|
||||
},
|
||||
Status: extensions.ScaleStatus{
|
||||
Replicas: validDeployment.Status.Replicas,
|
||||
Selector: validDeployment.Spec.Template.Labels,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
var validScale = *validNewScale()
|
||||
|
||||
func TestScaleGet(t *testing.T) {
|
||||
storage, server := newStorage(t)
|
||||
defer server.Terminate(t)
|
||||
@ -204,10 +204,10 @@ func TestScaleGet(t *testing.T) {
|
||||
|
||||
expect := &validScale
|
||||
obj, err := storage.Scale.Get(ctx, name)
|
||||
scale := obj.(*extensions.Scale)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
scale := obj.(*extensions.Scale)
|
||||
if e, a := expect, scale; !api.Semantic.DeepDerivative(e, a) {
|
||||
t.Errorf("unexpected scale: %s", util.ObjectDiff(e, a))
|
||||
}
|
||||
@ -216,6 +216,7 @@ func TestScaleGet(t *testing.T) {
|
||||
func TestScaleUpdate(t *testing.T) {
|
||||
storage, server := newStorage(t)
|
||||
defer server.Terminate(t)
|
||||
|
||||
ctx := api.WithNamespace(api.NewContext(), namespace)
|
||||
key := etcdtest.AddPrefix("/deployments/" + namespace + "/" + name)
|
||||
if err := storage.Deployment.Storage.Set(ctx, key, &validDeployment, nil, 0); err != nil {
|
||||
@ -232,12 +233,11 @@ func TestScaleUpdate(t *testing.T) {
|
||||
if _, _, err := storage.Scale.Update(ctx, &update); err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
obj, err := storage.Scale.Get(ctx, name)
|
||||
obj, err := storage.Deployment.Get(ctx, name)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
|
||||
deployment := obj.(*extensions.Scale)
|
||||
deployment := obj.(*extensions.Deployment)
|
||||
if deployment.Spec.Replicas != replicas {
|
||||
t.Errorf("wrong replicas count expected: %d got: %d", replicas, deployment.Spec.Replicas)
|
||||
}
|
||||
|
@ -18,9 +18,11 @@ package e2e
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
"k8s.io/kubernetes/pkg/apis/extensions"
|
||||
"k8s.io/kubernetes/pkg/labels"
|
||||
deploymentutil "k8s.io/kubernetes/pkg/util/deployment"
|
||||
"k8s.io/kubernetes/pkg/util/intstr"
|
||||
|
||||
@ -46,6 +48,9 @@ var _ = Describe("Deployment", func() {
|
||||
It("deployment should support rollover [Flaky]", func() {
|
||||
testRolloverDeployment(f)
|
||||
})
|
||||
It("paused deployment should be ignored by the controller", func() {
|
||||
testPausedDeployment(f)
|
||||
})
|
||||
})
|
||||
|
||||
func newRC(rcName string, replicas int, rcPodLabels map[string]string, imageName string, image string) *api.ReplicationController {
|
||||
@ -390,3 +395,74 @@ func testRolloverDeployment(f *Framework) {
|
||||
newRC, err = deploymentutil.GetNewRC(*deployment, c)
|
||||
Expect(newRC.Spec.Template.Spec.Containers[0].Image).Should(Equal(updatedDeploymentImage))
|
||||
}
|
||||
|
||||
func testPausedDeployment(f *Framework) {
|
||||
ns := f.Namespace.Name
|
||||
c := f.Client
|
||||
deploymentName := "nginx"
|
||||
podLabels := map[string]string{"name": "nginx"}
|
||||
d := newDeployment(deploymentName, 1, podLabels, "nginx", "nginx", extensions.RollingUpdateDeploymentStrategyType)
|
||||
d.Spec.Paused = true
|
||||
Logf("Creating paused deployment %s", deploymentName)
|
||||
_, err := c.Deployments(ns).Create(d)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
defer func() {
|
||||
_, err := c.Deployments(ns).Get(deploymentName)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Logf("deleting deployment %s", deploymentName)
|
||||
Expect(c.Deployments(ns).Delete(deploymentName, nil)).NotTo(HaveOccurred())
|
||||
}()
|
||||
// Check that deployment is created fine.
|
||||
deployment, err := c.Deployments(ns).Get(deploymentName)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
// Verify that there is no latest state realized for the new deployment.
|
||||
rc, err := deploymentutil.GetNewRC(*deployment, c)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
if rc != nil {
|
||||
err = fmt.Errorf("unexpected new rc/%s for deployment/%s", rc.Name, deployment.Name)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
}
|
||||
|
||||
// Update the deployment to run
|
||||
deployment.Spec.Paused = false
|
||||
deployment, err = c.Deployments(ns).Update(deployment)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
opts := api.ListOptions{LabelSelector: labels.Set(deployment.Spec.Selector).AsSelector()}
|
||||
w, err := c.ReplicationControllers(ns).Watch(opts)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
select {
|
||||
case <-w.ResultChan():
|
||||
// this is it
|
||||
case <-time.After(time.Minute):
|
||||
err = fmt.Errorf("expected a new rc to be created")
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
}
|
||||
|
||||
// Pause the deployment and delete the replication controller.
|
||||
// The paused deployment shouldn't recreate a new one.
|
||||
deployment.Spec.Paused = true
|
||||
deployment.ResourceVersion = ""
|
||||
deployment, err = c.Deployments(ns).Update(deployment)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
newRC, err := deploymentutil.GetNewRC(*deployment, c)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(c.ReplicationControllers(ns).Delete(newRC.Name)).NotTo(HaveOccurred())
|
||||
|
||||
deployment, err = c.Deployments(ns).Get(deploymentName)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
|
||||
if !deployment.Spec.Paused {
|
||||
err = fmt.Errorf("deployment %q should be paused", deployment.Name)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
}
|
||||
shouldBeNil, err := deploymentutil.GetNewRC(*deployment, c)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
if shouldBeNil != nil {
|
||||
err = fmt.Errorf("deployment %q shouldn't have a rc but there is %q", deployment.Name, shouldBeNil.Name)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user