From dd79fcd03683eabaf4ff5f6655aebb6917241934 Mon Sep 17 00:00:00 2001 From: Dmitrii Dolgov Date: Wed, 7 Feb 2018 17:04:43 +0100 Subject: [PATCH 01/28] Tests for retry_utils One can argue about how necessary they are, but at least I remembered how to do golang. --- pkg/util/retryutil/retry_util.go | 31 ++++++++++-- pkg/util/retryutil/retry_util_test.go | 68 +++++++++++++++++++++++++++ 2 files changed, 96 insertions(+), 3 deletions(-) create mode 100644 pkg/util/retryutil/retry_util_test.go diff --git a/pkg/util/retryutil/retry_util.go b/pkg/util/retryutil/retry_util.go index 6f90353bf..1f246b466 100644 --- a/pkg/util/retryutil/retry_util.go +++ b/pkg/util/retryutil/retry_util.go @@ -5,14 +5,39 @@ import ( "time" ) -// Retry calls ConditionFunc until it returns boolean true, a timeout expires or an error occurs. +type RetryTicker interface { + Stop() + Tick() +} + +type Ticker struct { + ticker *time.Ticker +} + +func (t *Ticker) Stop() { t.ticker.Stop() } + +func (t *Ticker) Tick() { <-t.ticker.C } + +// Retry calls ConditionFunc until either: +// * it returns boolean true +// * a timeout expires +// * an error occurs func Retry(interval time.Duration, timeout time.Duration, f func() (bool, error)) error { //TODO: make the retry exponential if timeout < interval { return fmt.Errorf("timout(%s) should be greater than interval(%v)", timeout, interval) } + tick := &Ticker{time.NewTicker(interval)} + return RetryWorker(interval, timeout, f, tick) +} + +func RetryWorker( + interval time.Duration, + timeout time.Duration, + f func() (bool, error), + tick RetryTicker) error { + maxRetries := int(timeout / interval) - tick := time.NewTicker(interval) defer tick.Stop() for i := 0; ; i++ { @@ -26,7 +51,7 @@ func Retry(interval time.Duration, timeout time.Duration, f func() (bool, error) if i+1 == maxRetries { break } - <-tick.C + tick.Tick() } return fmt.Errorf("still failing after %d retries", maxRetries) } diff --git a/pkg/util/retryutil/retry_util_test.go b/pkg/util/retryutil/retry_util_test.go new file mode 100644 index 000000000..35c4756d8 --- /dev/null +++ b/pkg/util/retryutil/retry_util_test.go @@ -0,0 +1,68 @@ +package retryutil + +import ( + "errors" + "testing" +) + +type mockTicker struct { + test *testing.T + counter int +} + +func (t *mockTicker) Stop() {} + +func (t *mockTicker) Tick() { + t.counter += 1 +} + +func TestRetryWorkerSuccess(t *testing.T) { + tick := &mockTicker{t, 0} + result := RetryWorker(10, 20, func() (bool, error) { + return true, nil + }, tick) + + if result != nil { + t.Errorf("Wrong result, expected: %#v, got: %#v", nil, result) + } + + if tick.counter != 0 { + t.Errorf("Ticker was started once, but it shouldn't be") + } +} + +func TestRetryWorkerOneFalse(t *testing.T) { + var counter = 0 + + tick := &mockTicker{t, 0} + result := RetryWorker(1, 3, func() (bool, error) { + counter += 1 + + if counter <= 1 { + return false, nil + } else { + return true, nil + } + }, tick) + + if result != nil { + t.Errorf("Wrong result, expected: %#v, got: %#v", nil, result) + } + + if tick.counter != 1 { + t.Errorf("Ticker was started %#v, but supposed to be just once", tick.counter) + } +} + +func TestRetryWorkerError(t *testing.T) { + fail := errors.New("Error") + + tick := &mockTicker{t, 0} + result := RetryWorker(1, 3, func() (bool, error) { + return false, fail + }, tick) + + if result != fail { + t.Errorf("Wrong result, expected: %#v, got: %#v", fail, result) + } +} From 4c1db33c27a507709b378c738cb36bb1ceb16420 Mon Sep 17 00:00:00 2001 From: Dmitrii Dolgov Date: Thu, 8 Feb 2018 10:43:27 +0100 Subject: [PATCH 02/28] Change the order of arguments --- pkg/util/retryutil/retry_util.go | 6 +++--- pkg/util/retryutil/retry_util_test.go | 12 ++++++------ 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/pkg/util/retryutil/retry_util.go b/pkg/util/retryutil/retry_util.go index 1f246b466..4b5f3f98c 100644 --- a/pkg/util/retryutil/retry_util.go +++ b/pkg/util/retryutil/retry_util.go @@ -28,14 +28,14 @@ func Retry(interval time.Duration, timeout time.Duration, f func() (bool, error) return fmt.Errorf("timout(%s) should be greater than interval(%v)", timeout, interval) } tick := &Ticker{time.NewTicker(interval)} - return RetryWorker(interval, timeout, f, tick) + return RetryWorker(interval, timeout, tick, f) } func RetryWorker( interval time.Duration, timeout time.Duration, - f func() (bool, error), - tick RetryTicker) error { + tick RetryTicker, + f func() (bool, error)) error { maxRetries := int(timeout / interval) defer tick.Stop() diff --git a/pkg/util/retryutil/retry_util_test.go b/pkg/util/retryutil/retry_util_test.go index 35c4756d8..05ae60d4b 100644 --- a/pkg/util/retryutil/retry_util_test.go +++ b/pkg/util/retryutil/retry_util_test.go @@ -18,9 +18,9 @@ func (t *mockTicker) Tick() { func TestRetryWorkerSuccess(t *testing.T) { tick := &mockTicker{t, 0} - result := RetryWorker(10, 20, func() (bool, error) { + result := RetryWorker(10, 20, tick, func() (bool, error) { return true, nil - }, tick) + }) if result != nil { t.Errorf("Wrong result, expected: %#v, got: %#v", nil, result) @@ -35,7 +35,7 @@ func TestRetryWorkerOneFalse(t *testing.T) { var counter = 0 tick := &mockTicker{t, 0} - result := RetryWorker(1, 3, func() (bool, error) { + result := RetryWorker(1, 3, tick, func() (bool, error) { counter += 1 if counter <= 1 { @@ -43,7 +43,7 @@ func TestRetryWorkerOneFalse(t *testing.T) { } else { return true, nil } - }, tick) + }) if result != nil { t.Errorf("Wrong result, expected: %#v, got: %#v", nil, result) @@ -58,9 +58,9 @@ func TestRetryWorkerError(t *testing.T) { fail := errors.New("Error") tick := &mockTicker{t, 0} - result := RetryWorker(1, 3, func() (bool, error) { + result := RetryWorker(1, 3, tick, func() (bool, error) { return false, fail - }, tick) + }) if result != fail { t.Errorf("Wrong result, expected: %#v, got: %#v", fail, result) From 305b77be90753d11c150eabe8ded4477799e41ce Mon Sep 17 00:00:00 2001 From: Dmitrii Dolgov Date: Fri, 9 Feb 2018 11:26:37 +0100 Subject: [PATCH 03/28] Add section about unit tests --- README.md | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/README.md b/README.md index 97c1ad9aa..d4a829f0c 100644 --- a/README.md +++ b/README.md @@ -350,3 +350,27 @@ kubectl port-forward POD_NAME DLV_PORT:DLV_PORT ``` $ dlv connect 127.0.0.1:DLV_PORT ``` + +### Unit tests + +To run all unit tests, you can simply do: + +``` +go test ./... +``` + +For go 1.9 `vendor` directory would be excluded automatically. For previous +versions you can exclude it manually: + +``` +go test (glide novendor) +``` + +In case if you need to debug your unit test, it's possible to use delve: + +``` +$ dlv test ./pkg/util/retryutil/ +Type 'help' for list of commands. +(dlv) c +PASS +``` From d5af441fd97c60197a5e9ab06ad6fd8c5d99677a Mon Sep 17 00:00:00 2001 From: zerg-junior Date: Fri, 9 Feb 2018 11:27:25 +0100 Subject: [PATCH 04/28] Create separate Talks section in the README Also adds a FOSDEM 2018 talk on the operator --- README.md | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 97c1ad9aa..bb78ad9a7 100644 --- a/README.md +++ b/README.md @@ -30,10 +30,14 @@ it manages and updates them with the new docker images; afterwards, all pods fro This project is currently in active development. It is however already [used internally by Zalando](https://jobs.zalando.com/tech/blog/postgresql-in-a-time-of-kubernetes/) in order to run Postgres databases on Kubernetes in larger numbers for staging environments and a smaller number of production databases. In this environment the operator is deployed to multiple Kubernetes clusters, where users deploy manifests via our CI/CD infrastructure. -There is a talk about this project delivered by Josh Berkus on KubeCon 2017: [Kube-native Postgres](https://www.youtube.com/watch?v=Zn1vd7sQ_bc) - Please, report any issues discovered to https://github.com/zalando-incubator/postgres-operator/issues. +## Talks + +1. "Blue elephant on-demand: Postgres + Kubernetes" talk by Oleksii Kliukin and Jan Mussler, FOSDEM 2018: [video](https://fosdem.org/2018/schedule/event/blue_elephant_on_demand_postgres_kubernetes/) | [slides (pdf)](https://www.postgresql.eu/events/fosdem2018/sessions/session/1735/slides/59/FOSDEM%202018_%20Blue_Elephant_On_Demand.pdf) + +2. "Kube-Native Postgres" talk by Josh Berkus, KubeCon 2017: [video](https://www.youtube.com/watch?v=Zn1vd7sQ_bc) + ## Running and testing the operator The best way to test the operator is to run it in [minikube](https://kubernetes.io/docs/getting-started-guides/minikube/). From fa44674243f1c160d1801acb776ddf63efe60385 Mon Sep 17 00:00:00 2001 From: Dmitrii Dolgov Date: Fri, 9 Feb 2018 11:38:04 +0100 Subject: [PATCH 05/28] Add $ sign --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index d4a829f0c..4e1fa0c95 100644 --- a/README.md +++ b/README.md @@ -356,14 +356,14 @@ $ dlv connect 127.0.0.1:DLV_PORT To run all unit tests, you can simply do: ``` -go test ./... +$ go test ./... ``` For go 1.9 `vendor` directory would be excluded automatically. For previous versions you can exclude it manually: ``` -go test (glide novendor) +$ go test (glide novendor) ``` In case if you need to debug your unit test, it's possible to use delve: From 36b363b3cef5051502fa078bf0d31ec5a97e1055 Mon Sep 17 00:00:00 2001 From: Dmitrii Dolgov Date: Fri, 9 Feb 2018 13:00:35 +0100 Subject: [PATCH 06/28] Don't forget about fish vs bash differences --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 4e1fa0c95..9f87619af 100644 --- a/README.md +++ b/README.md @@ -363,7 +363,7 @@ For go 1.9 `vendor` directory would be excluded automatically. For previous versions you can exclude it manually: ``` -$ go test (glide novendor) +$ go test $(glide novendor) ``` In case if you need to debug your unit test, it's possible to use delve: From 5b0e2ea66de1a5cf453af241c950b01aed0882b9 Mon Sep 17 00:00:00 2001 From: Sergey Dudoladov Date: Tue, 13 Feb 2018 13:39:49 +0100 Subject: [PATCH 07/28] Fetch operator configmap from operator's namespace --- cmd/main.go | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/cmd/main.go b/cmd/main.go index 7bb501885..6a6fdc163 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -4,6 +4,7 @@ import ( "flag" "log" "os" + "os/exec" "os/signal" "sync" "syscall" @@ -27,13 +28,26 @@ func init() { flag.BoolVar(&config.NoTeamsAPI, "noteamsapi", false, "Disable all access to the teams API") flag.Parse() + cmd := exec.Command("cat", "/var/run/secrets/kubernetes.io/serviceaccount/namespace") + operatorNamespaceBytes, err := cmd.Output() + if err != nil { + log.Fatalf("Unable to detect operator namespace from within its pod due to %v", err) + } + configMapRawName := os.Getenv("CONFIG_MAP_NAME") if configMapRawName != "" { - err := config.ConfigMapName.Decode(configMapRawName) + + operatorNamespace := string(operatorNamespaceBytes) + namespacedConfigMapName := operatorNamespace + "/" + configMapRawName + log.Printf("Looking for the operator configmap at the same namespace the operator resides. Fully qualified configmap name: %v", namespacedConfigMapName) + + err := config.ConfigMapName.Decode(namespacedConfigMapName) if err != nil { log.Fatalf("incorrect config map name") } + } + } func main() { From dc4229e84d25f86b297c4b14daf2b9fe48435769 Mon Sep 17 00:00:00 2001 From: Sergey Dudoladov Date: Tue, 13 Feb 2018 15:51:12 +0100 Subject: [PATCH 08/28] Include review comments --- cmd/main.go | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/cmd/main.go b/cmd/main.go index 6a6fdc163..0ac5817bb 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -2,9 +2,9 @@ package main import ( "flag" + "io/ioutil" "log" "os" - "os/exec" "os/signal" "sync" "syscall" @@ -28,8 +28,7 @@ func init() { flag.BoolVar(&config.NoTeamsAPI, "noteamsapi", false, "Disable all access to the teams API") flag.Parse() - cmd := exec.Command("cat", "/var/run/secrets/kubernetes.io/serviceaccount/namespace") - operatorNamespaceBytes, err := cmd.Output() + operatorNamespaceBytes, err := ioutil.ReadFile("/var/run/secrets/kubernetes.io/serviceaccount/namespace") if err != nil { log.Fatalf("Unable to detect operator namespace from within its pod due to %v", err) } @@ -43,7 +42,7 @@ func init() { err := config.ConfigMapName.Decode(namespacedConfigMapName) if err != nil { - log.Fatalf("incorrect config map name") + log.Fatalf("incorrect config map name: %v", namespacedConfigMapName) } } From 06fd9e33f5e7a9ff8b9483729d66aa935c9653f1 Mon Sep 17 00:00:00 2001 From: Sergey Dudoladov Date: Tue, 13 Feb 2018 18:17:47 +0100 Subject: [PATCH 09/28] Watch the namespace where operator deploys to unless told otherwise --- cmd/main.go | 3 +++ pkg/controller/controller.go | 9 +++++++-- pkg/util/k8sutil/k8sutil.go | 2 ++ 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/cmd/main.go b/cmd/main.go index 0ac5817bb..0805e08b4 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -37,7 +37,10 @@ func init() { if configMapRawName != "" { operatorNamespace := string(operatorNamespaceBytes) + config.Namespace = operatorNamespace + namespacedConfigMapName := operatorNamespace + "/" + configMapRawName + log.Printf("Looking for the operator configmap at the same namespace the operator resides. Fully qualified configmap name: %v", namespacedConfigMapName) err := config.ConfigMapName.Decode(namespacedConfigMapName) diff --git a/pkg/controller/controller.go b/pkg/controller/controller.go index c697217e4..00f9bb21c 100644 --- a/pkg/controller/controller.go +++ b/pkg/controller/controller.go @@ -105,8 +105,13 @@ func (c *Controller) initOperatorConfig() { } if configMapData["watched_namespace"] == "" { - c.logger.Infoln("No namespace to watch specified. Fall back to watching the 'default' namespace.") - configMapData["watched_namespace"] = v1.NamespaceDefault + c.logger.Infof("No namespace to watch specified. By convention, the operator falls back to watching the namespace it is deployed to: '%v' \n", c.config.Namespace) + configMapData["watched_namespace"] = c.config.Namespace + } + + _, err := c.KubeClient.ServiceAccounts(configMapData["watched_namespace"]).Get("operator", metav1.GetOptions{}) + if err != nil { + c.logger.Warnf("Cannot find the 'operator' service account in the watched namepsace %q. Pods will not be able to start. Error: %v", c.opConfig.WatchedNamespace, err) } if c.config.NoDatabaseAccess { diff --git a/pkg/util/k8sutil/k8sutil.go b/pkg/util/k8sutil/k8sutil.go index 1b4dc9a00..5db47c76b 100644 --- a/pkg/util/k8sutil/k8sutil.go +++ b/pkg/util/k8sutil/k8sutil.go @@ -32,6 +32,7 @@ type KubernetesClient struct { v1core.PersistentVolumeClaimsGetter v1core.ConfigMapsGetter v1core.NodesGetter + v1core.ServiceAccountsGetter v1beta1.StatefulSetsGetter policyv1beta1.PodDisruptionBudgetsGetter apiextbeta1.CustomResourceDefinitionsGetter @@ -72,6 +73,7 @@ func NewFromConfig(cfg *rest.Config) (KubernetesClient, error) { kubeClient.ServicesGetter = client.CoreV1() kubeClient.EndpointsGetter = client.CoreV1() kubeClient.SecretsGetter = client.CoreV1() + kubeClient.ServiceAccountsGetter = client.CoreV1() kubeClient.ConfigMapsGetter = client.CoreV1() kubeClient.PersistentVolumeClaimsGetter = client.CoreV1() kubeClient.PersistentVolumesGetter = client.CoreV1() From 5837015b3c2c981e4005021494aeedc6da847a11 Mon Sep 17 00:00:00 2001 From: Sergey Dudoladov Date: Wed, 14 Feb 2018 11:43:09 +0100 Subject: [PATCH 10/28] Add the fileWithNamespace const --- cmd/main.go | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/cmd/main.go b/cmd/main.go index 0805e08b4..d398ada11 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -14,6 +14,11 @@ import ( "github.com/zalando-incubator/postgres-operator/pkg/util/k8sutil" ) +const ( + // assumes serviceaccount secret is mounted by kubernetes + fileWithNamespace = "/var/run/secrets/kubernetes.io/serviceaccount/namespace" +) + var ( kubeConfigFile string outOfCluster bool @@ -28,7 +33,7 @@ func init() { flag.BoolVar(&config.NoTeamsAPI, "noteamsapi", false, "Disable all access to the teams API") flag.Parse() - operatorNamespaceBytes, err := ioutil.ReadFile("/var/run/secrets/kubernetes.io/serviceaccount/namespace") + operatorNamespaceBytes, err := ioutil.ReadFile(fileWithNamespace) if err != nil { log.Fatalf("Unable to detect operator namespace from within its pod due to %v", err) } From 6b9c1fe317c350be819bb7baa9f79f86a30eef82 Mon Sep 17 00:00:00 2001 From: Dmitrii Dolgov Date: Wed, 14 Feb 2018 13:08:53 +0100 Subject: [PATCH 11/28] Add a new step to run unit tests --- delivery.yaml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/delivery.yaml b/delivery.yaml index 9878a2ad5..647341ab4 100644 --- a/delivery.yaml +++ b/delivery.yaml @@ -19,6 +19,11 @@ build_steps: export OPERATOR_TOP_DIR=$GOPATH/src/github.com/zalando-incubator mkdir -p $OPERATOR_TOP_DIR ln -s $(pwd) $OPERATOR_TOP_DIR/postgres-operator + - desc: 'Run unit tests' + cmd: | + export PATH=$PATH:$HOME/go/bin + export GOPATH=$HOME/go + go test ./... - desc: 'Build & push docker image' cmd: | export PATH=$PATH:$HOME/go/bin From c54fb7b4c8e92e76fe805ba90d05a9ed203d38eb Mon Sep 17 00:00:00 2001 From: Dmitrii Dolgov Date: Wed, 14 Feb 2018 13:24:43 +0100 Subject: [PATCH 12/28] Build before actually test --- delivery.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/delivery.yaml b/delivery.yaml index 647341ab4..942b27c14 100644 --- a/delivery.yaml +++ b/delivery.yaml @@ -23,6 +23,7 @@ build_steps: cmd: | export PATH=$PATH:$HOME/go/bin export GOPATH=$HOME/go + make tools deps go test ./... - desc: 'Build & push docker image' cmd: | From 4513334d1b6a5612cc7ff87b09efd61fb3c81b3a Mon Sep 17 00:00:00 2001 From: Dmitrii Dolgov Date: Wed, 14 Feb 2018 13:28:16 +0100 Subject: [PATCH 13/28] Change order of the steps --- delivery.yaml | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/delivery.yaml b/delivery.yaml index 942b27c14..8fdd75570 100644 --- a/delivery.yaml +++ b/delivery.yaml @@ -19,12 +19,6 @@ build_steps: export OPERATOR_TOP_DIR=$GOPATH/src/github.com/zalando-incubator mkdir -p $OPERATOR_TOP_DIR ln -s $(pwd) $OPERATOR_TOP_DIR/postgres-operator - - desc: 'Run unit tests' - cmd: | - export PATH=$PATH:$HOME/go/bin - export GOPATH=$HOME/go - make tools deps - go test ./... - desc: 'Build & push docker image' cmd: | export PATH=$PATH:$HOME/go/bin @@ -37,3 +31,8 @@ build_steps: fi export IMAGE make tools deps docker push + - desc: 'Run unit tests' + cmd: | + export PATH=$PATH:$HOME/go/bin + export GOPATH=$HOME/go + go test ./... From eb2283aa437139fa7dcf1c3860f86289cb47caf6 Mon Sep 17 00:00:00 2001 From: Dmitrii Dolgov Date: Wed, 14 Feb 2018 13:51:55 +0100 Subject: [PATCH 14/28] Change current directory for tests --- delivery.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/delivery.yaml b/delivery.yaml index 8fdd75570..f77c28e74 100644 --- a/delivery.yaml +++ b/delivery.yaml @@ -35,4 +35,5 @@ build_steps: cmd: | export PATH=$PATH:$HOME/go/bin export GOPATH=$HOME/go + cd $OPERATOR_TOP_DIR/postgres-operator go test ./... From c21136c151ca6d9127dca7cf5311fec7945041a8 Mon Sep 17 00:00:00 2001 From: Dmitrii Dolgov Date: Wed, 14 Feb 2018 13:56:35 +0100 Subject: [PATCH 15/28] Forgotten env var --- delivery.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/delivery.yaml b/delivery.yaml index f77c28e74..f5272b7c1 100644 --- a/delivery.yaml +++ b/delivery.yaml @@ -35,5 +35,6 @@ build_steps: cmd: | export PATH=$PATH:$HOME/go/bin export GOPATH=$HOME/go + export OPERATOR_TOP_DIR=$GOPATH/src/github.com/zalando-incubator cd $OPERATOR_TOP_DIR/postgres-operator go test ./... From d61b87a07d00c70b5a17b53839563a6c0c2af29f Mon Sep 17 00:00:00 2001 From: Dmitrii Dolgov Date: Wed, 14 Feb 2018 14:07:53 +0100 Subject: [PATCH 16/28] Separate image build & push Move out some variables on top --- delivery.yaml | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/delivery.yaml b/delivery.yaml index f5272b7c1..7219a652b 100644 --- a/delivery.yaml +++ b/delivery.yaml @@ -1,4 +1,8 @@ build_steps: + env: + GOPATH: /root/go + OPERATOR_TOP_DIR: /root/go/src/github.com/zalando-incubator + - desc: 'Install required build software' cmd: | apt-get install -y make git apt-transport-https ca-certificates curl @@ -15,11 +19,9 @@ build_steps: curl -sSL https://get.docker.com/ | sh - desc: 'Symlink sources into the GOPATH' cmd: | - export GOPATH=$HOME/go - export OPERATOR_TOP_DIR=$GOPATH/src/github.com/zalando-incubator mkdir -p $OPERATOR_TOP_DIR ln -s $(pwd) $OPERATOR_TOP_DIR/postgres-operator - - desc: 'Build & push docker image' + - desc: 'Build docker image' cmd: | export PATH=$PATH:$HOME/go/bin IS_PR_BUILD=${CDP_PULL_REQUEST_NUMBER+"true"} @@ -30,11 +32,21 @@ build_steps: IMAGE=registry-write.opensource.zalan.do/acid/postgres-operator-test fi export IMAGE - make tools deps docker push + make tools deps docker - desc: 'Run unit tests' cmd: | export PATH=$PATH:$HOME/go/bin - export GOPATH=$HOME/go - export OPERATOR_TOP_DIR=$GOPATH/src/github.com/zalando-incubator cd $OPERATOR_TOP_DIR/postgres-operator go test ./... + - desc: 'Push docker image' + cmd: | + export PATH=$PATH:$HOME/go/bin + IS_PR_BUILD=${CDP_PULL_REQUEST_NUMBER+"true"} + if [[ ${CDP_TARGET_BRANCH} == "master" && ${IS_PR_BUILD} != "true" ]] + then + IMAGE=registry-write.opensource.zalan.do/acid/postgres-operator + else + IMAGE=registry-write.opensource.zalan.do/acid/postgres-operator-test + fi + export IMAGE + make push From 7b9428bb8158c746d9e582a3086435f1648fa495 Mon Sep 17 00:00:00 2001 From: Dmitrii Dolgov Date: Wed, 14 Feb 2018 14:10:48 +0100 Subject: [PATCH 17/28] Switch to the new format --- delivery.yaml | 107 ++++++++++++++++++++++++++------------------------ 1 file changed, 55 insertions(+), 52 deletions(-) diff --git a/delivery.yaml b/delivery.yaml index 7219a652b..0a301bb11 100644 --- a/delivery.yaml +++ b/delivery.yaml @@ -1,52 +1,55 @@ -build_steps: - env: - GOPATH: /root/go - OPERATOR_TOP_DIR: /root/go/src/github.com/zalando-incubator - - - desc: 'Install required build software' - cmd: | - apt-get install -y make git apt-transport-https ca-certificates curl - - desc: 'Install go' - cmd: | - cd /tmp - wget -q https://storage.googleapis.com/golang/go1.9.linux-amd64.tar.gz -O go.tar.gz - tar -xf go.tar.gz - mv go /usr/local - ln -s /usr/local/go/bin/go /usr/bin/go - go version - - desc: 'Install Docker' - cmd: | - curl -sSL https://get.docker.com/ | sh - - desc: 'Symlink sources into the GOPATH' - cmd: | - mkdir -p $OPERATOR_TOP_DIR - ln -s $(pwd) $OPERATOR_TOP_DIR/postgres-operator - - desc: 'Build docker image' - cmd: | - export PATH=$PATH:$HOME/go/bin - IS_PR_BUILD=${CDP_PULL_REQUEST_NUMBER+"true"} - if [[ ${CDP_TARGET_BRANCH} == "master" && ${IS_PR_BUILD} != "true" ]] - then - IMAGE=registry-write.opensource.zalan.do/acid/postgres-operator - else - IMAGE=registry-write.opensource.zalan.do/acid/postgres-operator-test - fi - export IMAGE - make tools deps docker - - desc: 'Run unit tests' - cmd: | - export PATH=$PATH:$HOME/go/bin - cd $OPERATOR_TOP_DIR/postgres-operator - go test ./... - - desc: 'Push docker image' - cmd: | - export PATH=$PATH:$HOME/go/bin - IS_PR_BUILD=${CDP_PULL_REQUEST_NUMBER+"true"} - if [[ ${CDP_TARGET_BRANCH} == "master" && ${IS_PR_BUILD} != "true" ]] - then - IMAGE=registry-write.opensource.zalan.do/acid/postgres-operator - else - IMAGE=registry-write.opensource.zalan.do/acid/postgres-operator-test - fi - export IMAGE - make push +version: "2017-09-20" +pipeline: + - id: "Build postgres operator" + type: script + env: + GOPATH: /root/go + OPERATOR_TOP_DIR: /root/go/src/github.com/zalando-incubator + commands: + - desc: 'Install required build software' + cmd: | + apt-get install -y make git apt-transport-https ca-certificates curl + - desc: 'Install go' + cmd: | + cd /tmp + wget -q https://storage.googleapis.com/golang/go1.9.linux-amd64.tar.gz -O go.tar.gz + tar -xf go.tar.gz + mv go /usr/local + ln -s /usr/local/go/bin/go /usr/bin/go + go version + - desc: 'Install Docker' + cmd: | + curl -sSL https://get.docker.com/ | sh + - desc: 'Symlink sources into the GOPATH' + cmd: | + mkdir -p $OPERATOR_TOP_DIR + ln -s $(pwd) $OPERATOR_TOP_DIR/postgres-operator + - desc: 'Build docker image' + cmd: | + export PATH=$PATH:$HOME/go/bin + IS_PR_BUILD=${CDP_PULL_REQUEST_NUMBER+"true"} + if [[ ${CDP_TARGET_BRANCH} == "master" && ${IS_PR_BUILD} != "true" ]] + then + IMAGE=registry-write.opensource.zalan.do/acid/postgres-operator + else + IMAGE=registry-write.opensource.zalan.do/acid/postgres-operator-test + fi + export IMAGE + make tools deps docker + - desc: 'Run unit tests' + cmd: | + export PATH=$PATH:$HOME/go/bin + cd $OPERATOR_TOP_DIR/postgres-operator + go test ./... + - desc: 'Push docker image' + cmd: | + export PATH=$PATH:$HOME/go/bin + IS_PR_BUILD=${CDP_PULL_REQUEST_NUMBER+"true"} + if [[ ${CDP_TARGET_BRANCH} == "master" && ${IS_PR_BUILD} != "true" ]] + then + IMAGE=registry-write.opensource.zalan.do/acid/postgres-operator + else + IMAGE=registry-write.opensource.zalan.do/acid/postgres-operator-test + fi + export IMAGE + make push From b6ae3e0262f556eb193616f8a7c329fb080b72da Mon Sep 17 00:00:00 2001 From: Dmitrii Dolgov Date: Wed, 14 Feb 2018 14:11:56 +0100 Subject: [PATCH 18/28] Change build id --- delivery.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/delivery.yaml b/delivery.yaml index 0a301bb11..b4cb5b844 100644 --- a/delivery.yaml +++ b/delivery.yaml @@ -1,6 +1,6 @@ version: "2017-09-20" pipeline: - - id: "Build postgres operator" + - id: Build postgres operator type: script env: GOPATH: /root/go From f6b213535119c384d24f9c401e21a7953d4e8655 Mon Sep 17 00:00:00 2001 From: Dmitrii Dolgov Date: Wed, 14 Feb 2018 14:12:39 +0100 Subject: [PATCH 19/28] Change build id --- delivery.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/delivery.yaml b/delivery.yaml index b4cb5b844..d2b176234 100644 --- a/delivery.yaml +++ b/delivery.yaml @@ -1,6 +1,6 @@ version: "2017-09-20" pipeline: - - id: Build postgres operator + - id: build-postgres-operator type: script env: GOPATH: /root/go From d5d15b7546e3a030ac2dadf42771b064d89b95d4 Mon Sep 17 00:00:00 2001 From: Sergey Dudoladov Date: Wed, 14 Feb 2018 15:37:30 +0100 Subject: [PATCH 20/28] Look for secrets in the deployed namespace --- README.md | 17 +++++++++++++++++ cmd/main.go | 13 +------------ pkg/controller/controller.go | 19 +++++++++++++------ pkg/spec/types.go | 22 +++++++++++++++++++--- 4 files changed, 50 insertions(+), 21 deletions(-) diff --git a/README.md b/README.md index aba0bd183..de68f03ac 100644 --- a/README.md +++ b/README.md @@ -61,6 +61,23 @@ to test your that your setup is working. Note: if you use multiple Kubernetes clusters, you can switch to Minikube with `kubectl config use-context minikube` +### Select the namespace to deploy to + +The operator can run in a namespace other than `default`. For example, to deploy it to the `test` namespace, run the following: + + kubectl create namespace test + kubectl config set-context minikube --namespace=test + +All subsequent `kubectl` commands will work with the `test` namespace. The operator will run in this namespace and look up needed resources - such as its config map - there. + +### Specify the namespace to watch + +Watching a namespace for an operator means tracking requests to change Postgresql clusters in the namespace such as "increase the number of Postgresql replicas to 5" and reacting to the requests, in this example by actually scaling up. + +By default, the operator watches the namespace it is deployed to. You can change this by altering the `WATCHED_NAMESPACE` env var in the operator deployment manifest or the `watched_namespace` field in the operator configmap. In the case both are set, the env var takes the preference. + +Note that for an operator to create pods in the watched namespace, one needs to create the `operator` service account in the namespace. + ### Create ConfigMap ConfigMap is used to store the configuration of the operator diff --git a/cmd/main.go b/cmd/main.go index d398ada11..bdfdf862c 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -2,7 +2,6 @@ package main import ( "flag" - "io/ioutil" "log" "os" "os/signal" @@ -14,11 +13,6 @@ import ( "github.com/zalando-incubator/postgres-operator/pkg/util/k8sutil" ) -const ( - // assumes serviceaccount secret is mounted by kubernetes - fileWithNamespace = "/var/run/secrets/kubernetes.io/serviceaccount/namespace" -) - var ( kubeConfigFile string outOfCluster bool @@ -33,15 +27,10 @@ func init() { flag.BoolVar(&config.NoTeamsAPI, "noteamsapi", false, "Disable all access to the teams API") flag.Parse() - operatorNamespaceBytes, err := ioutil.ReadFile(fileWithNamespace) - if err != nil { - log.Fatalf("Unable to detect operator namespace from within its pod due to %v", err) - } - configMapRawName := os.Getenv("CONFIG_MAP_NAME") if configMapRawName != "" { - operatorNamespace := string(operatorNamespaceBytes) + operatorNamespace := spec.GetOperatorNamespace() config.Namespace = operatorNamespace namespacedConfigMapName := operatorNamespace + "/" + configMapRawName diff --git a/pkg/controller/controller.go b/pkg/controller/controller.go index 00f9bb21c..b697ce42c 100644 --- a/pkg/controller/controller.go +++ b/pkg/controller/controller.go @@ -105,15 +105,10 @@ func (c *Controller) initOperatorConfig() { } if configMapData["watched_namespace"] == "" { - c.logger.Infof("No namespace to watch specified. By convention, the operator falls back to watching the namespace it is deployed to: '%v' \n", c.config.Namespace) + c.logger.Infof("No namespace to watch specified. By convention, the operator falls back to watching the namespace it is deployed to: '%v' \n", c.config.Namespace) configMapData["watched_namespace"] = c.config.Namespace } - _, err := c.KubeClient.ServiceAccounts(configMapData["watched_namespace"]).Get("operator", metav1.GetOptions{}) - if err != nil { - c.logger.Warnf("Cannot find the 'operator' service account in the watched namepsace %q. Pods will not be able to start. Error: %v", c.opConfig.WatchedNamespace, err) - } - if c.config.NoDatabaseAccess { configMapData["enable_database_access"] = "false" } @@ -136,6 +131,11 @@ func (c *Controller) initController() { c.logger.Infof("config: %s", c.opConfig.MustMarshal()) + c.mustHaveOperatorServiceAccountInNamespace(c.config.Namespace) + if c.config.Namespace != c.opConfig.WatchedNamespace { + c.mustHaveOperatorServiceAccountInNamespace(c.opConfig.WatchedNamespace) + } + if c.opConfig.DebugLogging { c.logger.Logger.Level = logrus.DebugLevel } @@ -261,3 +261,10 @@ func (c *Controller) kubeNodesInformer(stopCh <-chan struct{}, wg *sync.WaitGrou c.nodesInformer.Run(stopCh) } + +func (c *Controller) mustHaveOperatorServiceAccountInNamespace(namespace string) { + _, err := c.KubeClient.ServiceAccounts(namespace).Get(c.opConfig.ServiceAccountName, metav1.GetOptions{}) + if err != nil { + c.logger.Warnf("Cannot find the '%v' service account in the namepsace %q. Pods will not be able to start. Error: %v", c.opConfig.ServiceAccountName, namespace, err) + } +} diff --git a/pkg/spec/types.go b/pkg/spec/types.go index 3eb6e7fa7..7694e4ca2 100644 --- a/pkg/spec/types.go +++ b/pkg/spec/types.go @@ -3,6 +3,8 @@ package spec import ( "database/sql" "fmt" + "io/ioutil" + "log" "strings" "time" @@ -26,6 +28,8 @@ const ( EventUpdate EventType = "UPDATE" EventDelete EventType = "DELETE" EventSync EventType = "SYNC" + + fileWithNamespace = "/var/run/secrets/kubernetes.io/serviceaccount/namespace" ) // ClusterEvent carries the payload of the Cluster TPR events. @@ -165,16 +169,28 @@ func (n *NamespacedName) Decode(value string) error { if strings.Trim(value, string(types.Separator)) != "" && name == (types.NamespacedName{}) { name.Name = value - name.Namespace = v1.NamespaceDefault + name.Namespace = GetOperatorNamespace() } else if name.Namespace == "" { - name.Namespace = v1.NamespaceDefault + name.Namespace = GetOperatorNamespace() } if name.Name == "" { - return fmt.Errorf("incorrect namespaced name") + return fmt.Errorf("incorrect namespaced name: %v", value) } *n = NamespacedName(name) return nil } + +// GetOperatorNamespace assumes serviceaccount secret is mounted by kubernetes +// Placing this func here instead of pgk/util avoids circular import +func GetOperatorNamespace() string { + + operatorNamespaceBytes, err := ioutil.ReadFile(fileWithNamespace) + if err != nil { + log.Fatalf("Unable to detect operator namespace from within its pod due to: %v", err) + } + + return string(operatorNamespaceBytes) +} From fab1e3418289485595149cfad4d2f783d4671178 Mon Sep 17 00:00:00 2001 From: Sergey Dudoladov Date: Thu, 15 Feb 2018 10:43:06 +0100 Subject: [PATCH 21/28] Respond to code review comments --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index de68f03ac..517db4cb9 100644 --- a/README.md +++ b/README.md @@ -63,7 +63,7 @@ Note: if you use multiple Kubernetes clusters, you can switch to Minikube with ` ### Select the namespace to deploy to -The operator can run in a namespace other than `default`. For example, to deploy it to the `test` namespace, run the following: +The operator can run in a namespace other than `default`. For example, to use the `test` namespace, run the following before deploying the operator's manifests: kubectl create namespace test kubectl config set-context minikube --namespace=test @@ -74,7 +74,7 @@ All subsequent `kubectl` commands will work with the `test` namespace. The opera Watching a namespace for an operator means tracking requests to change Postgresql clusters in the namespace such as "increase the number of Postgresql replicas to 5" and reacting to the requests, in this example by actually scaling up. -By default, the operator watches the namespace it is deployed to. You can change this by altering the `WATCHED_NAMESPACE` env var in the operator deployment manifest or the `watched_namespace` field in the operator configmap. In the case both are set, the env var takes the preference. +By default, the operator watches the namespace it is deployed to. You can change this by altering the `WATCHED_NAMESPACE` env var in the operator deployment manifest or the `watched_namespace` field in the operator configmap. In the case both are set, the env var takes the precedence. Note that for an operator to create pods in the watched namespace, one needs to create the `operator` service account in the namespace. From 155ae8d50ff791998bc397812f7d56e504e1fcd7 Mon Sep 17 00:00:00 2001 From: Sergey Dudoladov Date: Thu, 15 Feb 2018 11:14:13 +0100 Subject: [PATCH 22/28] Rename the function that checks service account existence --- pkg/controller/controller.go | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/pkg/controller/controller.go b/pkg/controller/controller.go index b697ce42c..2abc4a6c6 100644 --- a/pkg/controller/controller.go +++ b/pkg/controller/controller.go @@ -131,9 +131,9 @@ func (c *Controller) initController() { c.logger.Infof("config: %s", c.opConfig.MustMarshal()) - c.mustHaveOperatorServiceAccountInNamespace(c.config.Namespace) + c.checkOperatorServiceAccount(c.config.Namespace) if c.config.Namespace != c.opConfig.WatchedNamespace { - c.mustHaveOperatorServiceAccountInNamespace(c.opConfig.WatchedNamespace) + c.checkOperatorServiceAccount(c.opConfig.WatchedNamespace) } if c.opConfig.DebugLogging { @@ -262,9 +262,10 @@ func (c *Controller) kubeNodesInformer(stopCh <-chan struct{}, wg *sync.WaitGrou c.nodesInformer.Run(stopCh) } -func (c *Controller) mustHaveOperatorServiceAccountInNamespace(namespace string) { +// Check that a namespace has the service account that the operator needs +func (c *Controller) checkOperatorServiceAccount(namespace string) { _, err := c.KubeClient.ServiceAccounts(namespace).Get(c.opConfig.ServiceAccountName, metav1.GetOptions{}) if err != nil { - c.logger.Warnf("Cannot find the '%v' service account in the namepsace %q. Pods will not be able to start. Error: %v", c.opConfig.ServiceAccountName, namespace, err) + c.logger.Warnf("Cannot find the '%v' service account needed for operator in the namespace %q. Pods will not be able to start. Error: %v", c.opConfig.ServiceAccountName, namespace, err) } } From 44a2812f5a5f58e938e380d5e04ec534de78963c Mon Sep 17 00:00:00 2001 From: Sergey Dudoladov Date: Thu, 15 Feb 2018 15:48:35 +0100 Subject: [PATCH 23/28] Update docs to clarify different service accounts --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 517db4cb9..fdb9ec708 100644 --- a/README.md +++ b/README.md @@ -76,7 +76,7 @@ Watching a namespace for an operator means tracking requests to change Postgresq By default, the operator watches the namespace it is deployed to. You can change this by altering the `WATCHED_NAMESPACE` env var in the operator deployment manifest or the `watched_namespace` field in the operator configmap. In the case both are set, the env var takes the precedence. -Note that for an operator to create pods in the watched namespace, one needs to create the `operator` service account in the namespace. +Note that for an operator to manage pods in the watched namespace, the operator's service account (as specified in the operator deployment manifest) has to have appropriate privileges to access the watched namespace. The watched namespace also needs to have a (possibly different) service account that allows database pods to talk to the Kubernetes API. ### Create ConfigMap From 5e9a21456ec3a3922f78c287e284aafd9bb3f91a Mon Sep 17 00:00:00 2001 From: Sergey Dudoladov Date: Thu, 15 Feb 2018 16:33:53 +0100 Subject: [PATCH 24/28] Remove the incorrect service account check --- pkg/controller/controller.go | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/pkg/controller/controller.go b/pkg/controller/controller.go index 2abc4a6c6..3b63b068b 100644 --- a/pkg/controller/controller.go +++ b/pkg/controller/controller.go @@ -131,11 +131,6 @@ func (c *Controller) initController() { c.logger.Infof("config: %s", c.opConfig.MustMarshal()) - c.checkOperatorServiceAccount(c.config.Namespace) - if c.config.Namespace != c.opConfig.WatchedNamespace { - c.checkOperatorServiceAccount(c.opConfig.WatchedNamespace) - } - if c.opConfig.DebugLogging { c.logger.Logger.Level = logrus.DebugLevel } @@ -261,11 +256,3 @@ func (c *Controller) kubeNodesInformer(stopCh <-chan struct{}, wg *sync.WaitGrou c.nodesInformer.Run(stopCh) } - -// Check that a namespace has the service account that the operator needs -func (c *Controller) checkOperatorServiceAccount(namespace string) { - _, err := c.KubeClient.ServiceAccounts(namespace).Get(c.opConfig.ServiceAccountName, metav1.GetOptions{}) - if err != nil { - c.logger.Warnf("Cannot find the '%v' service account needed for operator in the namespace %q. Pods will not be able to start. Error: %v", c.opConfig.ServiceAccountName, namespace, err) - } -} From 0a9e6bd8d218b4753354dbcf9ae75e2e6b955373 Mon Sep 17 00:00:00 2001 From: Sergey Dudoladov Date: Thu, 15 Feb 2018 16:40:07 +0100 Subject: [PATCH 25/28] Clarify when a separate account for database pods may be needed --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index fdb9ec708..27cb2e5b3 100644 --- a/README.md +++ b/README.md @@ -76,7 +76,7 @@ Watching a namespace for an operator means tracking requests to change Postgresq By default, the operator watches the namespace it is deployed to. You can change this by altering the `WATCHED_NAMESPACE` env var in the operator deployment manifest or the `watched_namespace` field in the operator configmap. In the case both are set, the env var takes the precedence. -Note that for an operator to manage pods in the watched namespace, the operator's service account (as specified in the operator deployment manifest) has to have appropriate privileges to access the watched namespace. The watched namespace also needs to have a (possibly different) service account that allows database pods to talk to the Kubernetes API. +Note that for an operator to manage pods in the watched namespace, the operator's service account (as specified in the operator deployment manifest) has to have appropriate privileges to access the watched namespace. The watched namespace also needs to have a (possibly different) service account in the case database pods need to talk to the Kubernetes API (e.g. when using Kubernetes-native configuration of Patroni). ### Create ConfigMap From bbe2801d6985a7140c1e8235275edd6140b93630 Mon Sep 17 00:00:00 2001 From: Sergey Dudoladov Date: Fri, 16 Feb 2018 11:13:08 +0100 Subject: [PATCH 26/28] Adjust unit tests for namespace decoding --- pkg/spec/types.go | 10 ++++++++-- pkg/spec/types_test.go | 16 +++++++++++----- 2 files changed, 19 insertions(+), 7 deletions(-) diff --git a/pkg/spec/types.go b/pkg/spec/types.go index 7694e4ca2..7a3078674 100644 --- a/pkg/spec/types.go +++ b/pkg/spec/types.go @@ -165,13 +165,19 @@ func (n NamespacedName) MarshalJSON() ([]byte, error) { // Decode converts a (possibly unqualified) string into the namespaced name object. func (n *NamespacedName) Decode(value string) error { + return n.DecodeWorker(value, GetOperatorNamespace()) +} + +// DecodeWorker separates the decode logic to (unit) test +// from obtaining the operator namespace that depends on k8s mounting files at runtime +func (n *NamespacedName) DecodeWorker(value, operatorNamespace string) error { name := types.NewNamespacedNameFromString(value) if strings.Trim(value, string(types.Separator)) != "" && name == (types.NamespacedName{}) { name.Name = value - name.Namespace = GetOperatorNamespace() + name.Namespace = operatorNamespace } else if name.Namespace == "" { - name.Namespace = GetOperatorNamespace() + name.Namespace = operatorNamespace } if name.Name == "" { diff --git a/pkg/spec/types_test.go b/pkg/spec/types_test.go index 05045445b..7611501ad 100644 --- a/pkg/spec/types_test.go +++ b/pkg/spec/types_test.go @@ -5,22 +5,27 @@ import ( "testing" ) +const ( + mockOperatorNamespace = "acid" +) + var nnTests = []struct { s string expected NamespacedName expectedMarshal []byte }{ - {`acid/cluster`, NamespacedName{Namespace: "acid", Name: "cluster"}, []byte(`"acid/cluster"`)}, - {`/name`, NamespacedName{Namespace: "default", Name: "name"}, []byte(`"default/name"`)}, - {`test`, NamespacedName{Namespace: "default", Name: "test"}, []byte(`"default/test"`)}, + {`acid/cluster`, NamespacedName{Namespace: mockOperatorNamespace, Name: "cluster"}, []byte(`"acid/cluster"`)}, + {`/name`, NamespacedName{Namespace: mockOperatorNamespace, Name: "name"}, []byte(`"acid/name"`)}, + {`test`, NamespacedName{Namespace: mockOperatorNamespace, Name: "test"}, []byte(`"acid/test"`)}, } var nnErr = []string{"test/", "/", "", "//"} func TestNamespacedNameDecode(t *testing.T) { + for _, tt := range nnTests { var actual NamespacedName - err := actual.Decode(tt.s) + err := actual.DecodeWorker(tt.s, mockOperatorNamespace) if err != nil { t.Errorf("decode error: %v", err) } @@ -28,6 +33,7 @@ func TestNamespacedNameDecode(t *testing.T) { t.Errorf("expected: %v, got %#v", tt.expected, actual) } } + } func TestNamespacedNameMarshal(t *testing.T) { @@ -47,7 +53,7 @@ func TestNamespacedNameMarshal(t *testing.T) { func TestNamespacedNameError(t *testing.T) { for _, tt := range nnErr { var actual NamespacedName - err := actual.Decode(tt) + err := actual.DecodeWorker(tt, mockOperatorNamespace) if err == nil { t.Errorf("error expected for %q, got: %#v", tt, actual) } From b412a831d67df76cbd1489968479483a00c1fa36 Mon Sep 17 00:00:00 2001 From: Sergey Dudoladov Date: Fri, 16 Feb 2018 12:30:07 +0100 Subject: [PATCH 27/28] Remove the second namespace prefix from the operator configmap name --- cmd/main.go | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/cmd/main.go b/cmd/main.go index bdfdf862c..5c8aadd8f 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -30,20 +30,14 @@ func init() { configMapRawName := os.Getenv("CONFIG_MAP_NAME") if configMapRawName != "" { - operatorNamespace := spec.GetOperatorNamespace() - config.Namespace = operatorNamespace - - namespacedConfigMapName := operatorNamespace + "/" + configMapRawName - - log.Printf("Looking for the operator configmap at the same namespace the operator resides. Fully qualified configmap name: %v", namespacedConfigMapName) - - err := config.ConfigMapName.Decode(namespacedConfigMapName) + err := config.ConfigMapName.Decode(configMapRawName) if err != nil { - log.Fatalf("incorrect config map name: %v", namespacedConfigMapName) + log.Fatalf("incorrect config map name: %v", configMapRawName) } - } + log.Printf("Fully qualified configmap name: %v", config.ConfigMapName) + } } func main() { From ec7de38f9b8d6541291cd8cbbb9034ad756c9ae5 Mon Sep 17 00:00:00 2001 From: Sergey Dudoladov Date: Fri, 16 Feb 2018 14:22:38 +0100 Subject: [PATCH 28/28] Make operator watch its own namespace instead of controller's one --- pkg/controller/controller.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkg/controller/controller.go b/pkg/controller/controller.go index 3b63b068b..ac58db342 100644 --- a/pkg/controller/controller.go +++ b/pkg/controller/controller.go @@ -105,8 +105,8 @@ func (c *Controller) initOperatorConfig() { } if configMapData["watched_namespace"] == "" { - c.logger.Infof("No namespace to watch specified. By convention, the operator falls back to watching the namespace it is deployed to: '%v' \n", c.config.Namespace) - configMapData["watched_namespace"] = c.config.Namespace + c.logger.Infof("No namespace to watch specified. By convention, the operator falls back to watching the namespace it is deployed to: '%v' \n", spec.GetOperatorNamespace()) + configMapData["watched_namespace"] = spec.GetOperatorNamespace() } if c.config.NoDatabaseAccess {