From 357ecb8217fec663d76d5ec04f48612e9240a501 Mon Sep 17 00:00:00 2001 From: Karolis Rusenas Date: Wed, 4 Apr 2018 21:26:51 +0100 Subject: [PATCH 1/6] delete delay parse tests --- types/types_test.go | 44 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/types/types_test.go b/types/types_test.go index 91abec50f..3f22ab9de 100644 --- a/types/types_test.go +++ b/types/types_test.go @@ -166,3 +166,47 @@ func TestParseEventNotificationChannels(t *testing.T) { }) } } + +func TestParsePodDeleteDelay(t *testing.T) { + type args struct { + annotations map[string]string + } + tests := []struct { + name string + args args + want int64 + }{ + { + name: "not specified", + args: args{map[string]string{}}, + want: 0, + }, + { + name: "string", + args: args{map[string]string{KeelPodDeleteDelay: "aa"}}, + want: 0, + }, + { + name: "10", + args: args{map[string]string{KeelPodDeleteDelay: "10"}}, + want: 10, + }, + { + name: "-10", + args: args{map[string]string{KeelPodDeleteDelay: "-10"}}, + want: 0, + }, + { + name: "over max", + args: args{map[string]string{KeelPodDeleteDelay: "50000"}}, + want: KeelPodMaxDelay, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := ParsePodDeleteDelay(tt.args.annotations); got != tt.want { + t.Errorf("ParsePodDeleteDelay() = %v, want %v", got, tt.want) + } + }) + } +} From abe196aa9345ca42c1b3a3eb2eff6c62fac59e9f Mon Sep 17 00:00:00 2001 From: Karolis Rusenas Date: Wed, 4 Apr 2018 21:27:18 +0100 Subject: [PATCH 2/6] sleeping seconds instead of ms, using default graceful termination if present --- provider/kubernetes/force_update.go | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/provider/kubernetes/force_update.go b/provider/kubernetes/force_update.go index 2f7193948..4a16f1062 100644 --- a/provider/kubernetes/force_update.go +++ b/provider/kubernetes/force_update.go @@ -32,16 +32,25 @@ func (p *Provider) forceUpdate(deployment *v1beta1.Deployment) (err error) { for index, pod := range podList.Items { + var gp int64 + + if pod.DeletionGracePeriodSeconds != nil { + gp = *pod.DeletionGracePeriodSeconds + } + if gracePeriod != 0 { + gp = gracePeriod + } + log.WithFields(log.Fields{ "selector": selector, "pod": pod.Name, "namespace": deployment.Namespace, "deployment": deployment.Name, - "grace_period": fmt.Sprint(gracePeriod), + "grace_period": fmt.Sprint(gp), }).Info("provider.kubernetes: deleting pod to force pull...") err = p.implementer.DeletePod(deployment.Namespace, pod.Name, &meta_v1.DeleteOptions{ - GracePeriodSeconds: &gracePeriod, + GracePeriodSeconds: &gp, }) if err != nil { log.WithFields(log.Fields{ @@ -55,7 +64,7 @@ func (p *Provider) forceUpdate(deployment *v1beta1.Deployment) (err error) { // sleep between pod restarts but not if there aren't more left if index < len(podList.Items)-1 { - time.Sleep(time.Duration(podDeleteDelay)) + time.Sleep(time.Duration(podDeleteDelay) * time.Second) } } From 11344c200121ba6d36a7caa2eaf6615c723fcb45 Mon Sep 17 00:00:00 2001 From: Karolis Rusenas Date: Wed, 4 Apr 2018 21:27:32 +0100 Subject: [PATCH 3/6] force update with delay tests --- provider/kubernetes/force_update_test.go | 60 ++++++++++++++++++++++++ 1 file changed, 60 insertions(+) diff --git a/provider/kubernetes/force_update_test.go b/provider/kubernetes/force_update_test.go index 1ee98beee..f0f2b3f64 100644 --- a/provider/kubernetes/force_update_test.go +++ b/provider/kubernetes/force_update_test.go @@ -2,6 +2,7 @@ package kubernetes import ( "testing" + "time" "github.com/keel-hq/keel/types" "k8s.io/api/core/v1" @@ -69,3 +70,62 @@ func TestForceUpdate(t *testing.T) { t.Errorf("wrong name: %s", fp.deletedPods[1].Name) } } + +func TestForceUpdateDelay(t *testing.T) { + + fp := &fakeImplementer{} + + dep := &v1beta1.Deployment{ + meta_v1.TypeMeta{}, + meta_v1.ObjectMeta{ + Name: "deployment-1", + Namespace: "xx", + Labels: map[string]string{types.KeelPolicyLabel: "all"}, + Annotations: map[string]string{types.KeelPodDeleteDelay: "300"}, + }, + v1beta1.DeploymentSpec{}, + v1beta1.DeploymentStatus{}, + } + + fp.podList = &v1.PodList{ + Items: []v1.Pod{ + v1.Pod{ + ObjectMeta: meta_v1.ObjectMeta{ + Name: "1", + Namespace: "xx", + }, + }, + v1.Pod{ + ObjectMeta: meta_v1.ObjectMeta{ + Name: "2", + Namespace: "xx", + }, + }, + }, + } + + provider, err := NewProvider(fp, &fakeSender{}, approver()) + if err != nil { + t.Fatalf("failed to get provider: %s", err) + } + + go func() { + err = provider.forceUpdate(dep) + if err != nil { + t.Fatalf("failed to force update: %s", err) + } + }() + + time.Sleep(100 * time.Millisecond) + + if len(fp.deletedPods) != 1 { + t.Errorf("expected to get 1 deleted pods, another one should be delayed") + } + + if fp.deletedPods[0].Namespace != "xx" { + t.Errorf("wrong namespace: %s", fp.deletedPods[0].Namespace) + } + if fp.deletedPods[0].Name != "1" { + t.Errorf("wrong name: %s", fp.deletedPods[0].Name) + } +} From d5ce30bb7aeffd60957c6cbe4b21448915ad7093 Mon Sep 17 00:00:00 2001 From: Karolis Rusenas Date: Wed, 4 Apr 2018 21:27:38 +0100 Subject: [PATCH 4/6] max val --- types/types.go | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/types/types.go b/types/types.go index fc1f2129f..176174bbb 100644 --- a/types/types.go +++ b/types/types.go @@ -51,6 +51,9 @@ const KeelApprovalDeadlineDefault = 24 // during force deploy const KeelPodDeleteDelay = "keel.sh/forceDelay" +//KeelPodMaxDelay defines maximum delay in seconds between deleting pods +const KeelPodMaxDelay int64 = 600 + // KeelPodTerminationGracePeriod - optional grace period during // pod termination const KeelPodTerminationGracePeriod = "keel.sh/gracePeriod" @@ -218,19 +221,24 @@ func ParsePodDeleteDelay(annotations map[string]string) int64 { return delay } delayStr, ok := annotations[KeelPodDeleteDelay] - if ok { + if !ok { + return delay + } - g, err := strconv.Atoi(delayStr) - if err != nil { - return delay - } + g, err := strconv.Atoi(delayStr) + if err != nil { + return delay + } - if g > 0 && g < 600 { - return int64(g) - } + if g < 1 { + return delay + } + + if int64(g) > KeelPodMaxDelay { + return KeelPodMaxDelay } + return int64(g) - return delay } // ParsePodTerminationGracePeriod - parses pod termination time in seconds From 92220d6c5c3d456336c55f656bef37bdcf781842 Mon Sep 17 00:00:00 2001 From: Karolis Rusenas Date: Wed, 4 Apr 2018 21:27:45 +0100 Subject: [PATCH 5/6] more tests on metadata check --- util/version/version_test.go | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/util/version/version_test.go b/util/version/version_test.go index f97f37141..c91cc3175 100644 --- a/util/version/version_test.go +++ b/util/version/version_test.go @@ -203,6 +203,26 @@ func TestShouldUpdate(t *testing.T) { want: false, wantErr: false, }, + { + name: "parsed prerelease patch increase, policy minor, no prerelease", + args: args{ + current: MustParse("v1.0.0"), + new: MustParse("v1.0.1-metadata"), + policy: types.PolicyTypeMinor, + }, + want: false, + wantErr: false, + }, + { + name: "parsed prerelease minor increase, policy minor, both have metadata", + args: args{ + current: MustParse("v1.0.0-metadata"), + new: MustParse("v1.0.1-metadata"), + policy: types.PolicyTypeMinor, + }, + want: true, + wantErr: false, + }, { name: "prerelease patch increase, policy minor", args: args{ From 84e3cf8084151028d4609a587a7c89c721ee151c Mon Sep 17 00:00:00 2001 From: Karolis Rusenas Date: Wed, 4 Apr 2018 21:50:52 +0100 Subject: [PATCH 6/6] dev guide --- readme.md | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/readme.md b/readme.md index 4fb178304..6fcc305d5 100644 --- a/readme.md +++ b/readme.md @@ -85,4 +85,12 @@ Before starting to work on some big or medium features - raise an issue [here](h ### Developing Keel -If you wish to work on Keel itself, you will need Go 1.8+ installed. Make sure you put Keel into correct Gopath and `go build` (dependency management is done through [dep](https://github.com/golang/dep)). +If you wish to work on Keel itself, you will need Go 1.9+ installed. Make sure you put Keel into correct Gopath and `go build` (dependency management is done through [dep](https://github.com/golang/dep)). + +To test Keel while developing: + +1. Launch a Kubernetes cluster like Minikube or Docker for Mac with Kubernetes. +2. Change config to use it: `kubectl config use-context docker-for-desktop` +3. Build Keel from `cmd/keel` directory. +4. Start Keel with: `keel --no-incluster`. This will use Kubeconfig from your home. +