define ownership between operator and clusters via annotation (#802)
* define ownership between operator and postgres clusters * add documentation * add unit test
This commit is contained in:
parent
d666c52172
commit
cf829df1a4
|
|
@ -77,7 +77,7 @@ func main() {
|
||||||
log.Fatalf("couldn't get REST config: %v", err)
|
log.Fatalf("couldn't get REST config: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
c := controller.NewController(&config)
|
c := controller.NewController(&config, "")
|
||||||
|
|
||||||
c.Run(stop, wg)
|
c.Run(stop, wg)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -95,6 +95,34 @@ lacks access rights to any of them (except K8s system namespaces like
|
||||||
'list pods' execute at the cluster scope and fail at the first violation of
|
'list pods' execute at the cluster scope and fail at the first violation of
|
||||||
access rights.
|
access rights.
|
||||||
|
|
||||||
|
## Operators with defined ownership of certain Postgres clusters
|
||||||
|
|
||||||
|
By default, multiple operators can only run together in one K8s cluster when
|
||||||
|
isolated into their [own namespaces](administrator.md#specify-the-namespace-to-watch).
|
||||||
|
But, it is also possible to define ownership between operator instances and
|
||||||
|
Postgres clusters running all in the same namespace or K8s cluster without
|
||||||
|
interfering.
|
||||||
|
|
||||||
|
First, define the [`CONTROLLER_ID`](../../manifests/postgres-operator.yaml#L38)
|
||||||
|
environment variable in the operator deployment manifest. Then specify the ID
|
||||||
|
in every Postgres cluster manifest you want this operator to watch using the
|
||||||
|
`"acid.zalan.do/controller"` annotation:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
apiVersion: "acid.zalan.do/v1"
|
||||||
|
kind: postgresql
|
||||||
|
metadata:
|
||||||
|
name: demo-cluster
|
||||||
|
annotations:
|
||||||
|
"acid.zalan.do/controller": "second-operator"
|
||||||
|
spec:
|
||||||
|
...
|
||||||
|
```
|
||||||
|
|
||||||
|
Every other Postgres cluster which lacks the annotation will be ignored by this
|
||||||
|
operator. Conversely, operators without a defined `CONTROLLER_ID` will ignore
|
||||||
|
clusters with defined ownership of another operator.
|
||||||
|
|
||||||
## Role-based access control for the operator
|
## Role-based access control for the operator
|
||||||
|
|
||||||
The manifest [`operator-service-account-rbac.yaml`](../manifests/operator-service-account-rbac.yaml)
|
The manifest [`operator-service-account-rbac.yaml`](../manifests/operator-service-account-rbac.yaml)
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,8 @@ metadata:
|
||||||
name: acid-test-cluster
|
name: acid-test-cluster
|
||||||
# labels:
|
# labels:
|
||||||
# environment: demo
|
# environment: demo
|
||||||
|
# annotations:
|
||||||
|
# "acid.zalan.do/controller": "second-operator"
|
||||||
spec:
|
spec:
|
||||||
dockerImage: registry.opensource.zalan.do/acid/spilo-12:1.6-p2
|
dockerImage: registry.opensource.zalan.do/acid/spilo-12:1.6-p2
|
||||||
teamId: "acid"
|
teamId: "acid"
|
||||||
|
|
|
||||||
|
|
@ -35,3 +35,6 @@ spec:
|
||||||
# In order to use the CRD OperatorConfiguration instead, uncomment these lines and comment out the two lines above
|
# In order to use the CRD OperatorConfiguration instead, uncomment these lines and comment out the two lines above
|
||||||
# - name: POSTGRES_OPERATOR_CONFIGURATION_OBJECT
|
# - name: POSTGRES_OPERATOR_CONFIGURATION_OBJECT
|
||||||
# value: postgresql-operator-default-configuration
|
# value: postgresql-operator-default-configuration
|
||||||
|
# Define an ID to isolate controllers from each other
|
||||||
|
# - name: CONTROLLER_ID
|
||||||
|
# value: "second-operator"
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,7 @@ import (
|
||||||
"k8s.io/client-go/kubernetes/scheme"
|
"k8s.io/client-go/kubernetes/scheme"
|
||||||
"k8s.io/client-go/tools/cache"
|
"k8s.io/client-go/tools/cache"
|
||||||
|
|
||||||
|
acidv1 "github.com/zalando/postgres-operator/pkg/apis/acid.zalan.do/v1"
|
||||||
"github.com/zalando/postgres-operator/pkg/apiserver"
|
"github.com/zalando/postgres-operator/pkg/apiserver"
|
||||||
"github.com/zalando/postgres-operator/pkg/cluster"
|
"github.com/zalando/postgres-operator/pkg/cluster"
|
||||||
"github.com/zalando/postgres-operator/pkg/spec"
|
"github.com/zalando/postgres-operator/pkg/spec"
|
||||||
|
|
@ -36,6 +37,7 @@ type Controller struct {
|
||||||
|
|
||||||
stopCh chan struct{}
|
stopCh chan struct{}
|
||||||
|
|
||||||
|
controllerID string
|
||||||
curWorkerID uint32 //initialized with 0
|
curWorkerID uint32 //initialized with 0
|
||||||
curWorkerCluster sync.Map
|
curWorkerCluster sync.Map
|
||||||
clusterWorkers map[spec.NamespacedName]uint32
|
clusterWorkers map[spec.NamespacedName]uint32
|
||||||
|
|
@ -61,13 +63,14 @@ type Controller struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewController creates a new controller
|
// NewController creates a new controller
|
||||||
func NewController(controllerConfig *spec.ControllerConfig) *Controller {
|
func NewController(controllerConfig *spec.ControllerConfig, controllerId string) *Controller {
|
||||||
logger := logrus.New()
|
logger := logrus.New()
|
||||||
|
|
||||||
c := &Controller{
|
c := &Controller{
|
||||||
config: *controllerConfig,
|
config: *controllerConfig,
|
||||||
opConfig: &config.Config{},
|
opConfig: &config.Config{},
|
||||||
logger: logger.WithField("pkg", "controller"),
|
logger: logger.WithField("pkg", "controller"),
|
||||||
|
controllerID: controllerId,
|
||||||
curWorkerCluster: sync.Map{},
|
curWorkerCluster: sync.Map{},
|
||||||
clusterWorkers: make(map[spec.NamespacedName]uint32),
|
clusterWorkers: make(map[spec.NamespacedName]uint32),
|
||||||
clusters: make(map[spec.NamespacedName]*cluster.Cluster),
|
clusters: make(map[spec.NamespacedName]*cluster.Cluster),
|
||||||
|
|
@ -239,6 +242,7 @@ func (c *Controller) initRoleBinding() {
|
||||||
|
|
||||||
func (c *Controller) initController() {
|
func (c *Controller) initController() {
|
||||||
c.initClients()
|
c.initClients()
|
||||||
|
c.controllerID = os.Getenv("CONTROLLER_ID")
|
||||||
|
|
||||||
if configObjectName := os.Getenv("POSTGRES_OPERATOR_CONFIGURATION_OBJECT"); configObjectName != "" {
|
if configObjectName := os.Getenv("POSTGRES_OPERATOR_CONFIGURATION_OBJECT"); configObjectName != "" {
|
||||||
if err := c.createConfigurationCRD(c.opConfig.EnableCRDValidation); err != nil {
|
if err := c.createConfigurationCRD(c.opConfig.EnableCRDValidation); err != nil {
|
||||||
|
|
@ -412,3 +416,16 @@ func (c *Controller) getEffectiveNamespace(namespaceFromEnvironment, namespaceFr
|
||||||
|
|
||||||
return namespace
|
return namespace
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// hasOwnership returns true if the controller is the "owner" of the postgresql.
|
||||||
|
// Whether it's owner is determined by the value of 'acid.zalan.do/controller'
|
||||||
|
// annotation. If the value matches the controllerID then it owns it, or if the
|
||||||
|
// controllerID is "" and there's no annotation set.
|
||||||
|
func (c *Controller) hasOwnership(postgresql *acidv1.Postgresql) bool {
|
||||||
|
if postgresql.Annotations != nil {
|
||||||
|
if owner, ok := postgresql.Annotations[constants.PostgresqlControllerAnnotationKey]; ok {
|
||||||
|
return owner == c.controllerID
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return c.controllerID == ""
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/zalando/postgres-operator/pkg/spec"
|
"github.com/zalando/postgres-operator/pkg/spec"
|
||||||
"k8s.io/api/core/v1"
|
v1 "k8s.io/api/core/v1"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -13,10 +13,10 @@ const (
|
||||||
readyValue = "ready"
|
readyValue = "ready"
|
||||||
)
|
)
|
||||||
|
|
||||||
func initializeController() *Controller {
|
func newNodeTestController() *Controller {
|
||||||
var c = NewController(&spec.ControllerConfig{})
|
var controller = NewController(&spec.ControllerConfig{}, "node-test")
|
||||||
c.opConfig.NodeReadinessLabel = map[string]string{readyLabel: readyValue}
|
controller.opConfig.NodeReadinessLabel = map[string]string{readyLabel: readyValue}
|
||||||
return c
|
return controller
|
||||||
}
|
}
|
||||||
|
|
||||||
func makeNode(labels map[string]string, isSchedulable bool) *v1.Node {
|
func makeNode(labels map[string]string, isSchedulable bool) *v1.Node {
|
||||||
|
|
@ -31,7 +31,7 @@ func makeNode(labels map[string]string, isSchedulable bool) *v1.Node {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var c = initializeController()
|
var nodeTestController = newNodeTestController()
|
||||||
|
|
||||||
func TestNodeIsReady(t *testing.T) {
|
func TestNodeIsReady(t *testing.T) {
|
||||||
testName := "TestNodeIsReady"
|
testName := "TestNodeIsReady"
|
||||||
|
|
@ -57,7 +57,7 @@ func TestNodeIsReady(t *testing.T) {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
for _, tt := range testTable {
|
for _, tt := range testTable {
|
||||||
if isReady := c.nodeIsReady(tt.in); isReady != tt.out {
|
if isReady := nodeTestController.nodeIsReady(tt.in); isReady != tt.out {
|
||||||
t.Errorf("%s: expected response %t doesn't match the actual %t for the node %#v",
|
t.Errorf("%s: expected response %t doesn't match the actual %t for the node %#v",
|
||||||
testName, tt.out, isReady, tt.in)
|
testName, tt.out, isReady, tt.in)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -40,12 +40,23 @@ func (c *Controller) clusterResync(stopCh <-chan struct{}, wg *sync.WaitGroup) {
|
||||||
|
|
||||||
// clusterListFunc obtains a list of all PostgreSQL clusters
|
// clusterListFunc obtains a list of all PostgreSQL clusters
|
||||||
func (c *Controller) listClusters(options metav1.ListOptions) (*acidv1.PostgresqlList, error) {
|
func (c *Controller) listClusters(options metav1.ListOptions) (*acidv1.PostgresqlList, error) {
|
||||||
|
var pgList acidv1.PostgresqlList
|
||||||
|
|
||||||
// TODO: use the SharedInformer cache instead of quering Kubernetes API directly.
|
// TODO: use the SharedInformer cache instead of quering Kubernetes API directly.
|
||||||
list, err := c.KubeClient.AcidV1ClientSet.AcidV1().Postgresqls(c.opConfig.WatchedNamespace).List(options)
|
list, err := c.KubeClient.AcidV1ClientSet.AcidV1().Postgresqls(c.opConfig.WatchedNamespace).List(options)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.logger.Errorf("could not list postgresql objects: %v", err)
|
c.logger.Errorf("could not list postgresql objects: %v", err)
|
||||||
}
|
}
|
||||||
return list, err
|
if c.controllerID != "" {
|
||||||
|
c.logger.Debugf("watch only clusters with controllerID %q", c.controllerID)
|
||||||
|
}
|
||||||
|
for _, pg := range list.Items {
|
||||||
|
if pg.Error == "" && c.hasOwnership(&pg) {
|
||||||
|
pgList.Items = append(pgList.Items, pg)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return &pgList, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// clusterListAndSync lists all manifests and decides whether to run the sync or repair.
|
// clusterListAndSync lists all manifests and decides whether to run the sync or repair.
|
||||||
|
|
@ -455,41 +466,48 @@ func (c *Controller) queueClusterEvent(informerOldSpec, informerNewSpec *acidv1.
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Controller) postgresqlAdd(obj interface{}) {
|
func (c *Controller) postgresqlAdd(obj interface{}) {
|
||||||
pg, ok := obj.(*acidv1.Postgresql)
|
pg := c.postgresqlCheck(obj)
|
||||||
if !ok {
|
if pg != nil {
|
||||||
c.logger.Errorf("could not cast to postgresql spec")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// We will not get multiple Add events for the same cluster
|
// We will not get multiple Add events for the same cluster
|
||||||
c.queueClusterEvent(nil, pg, EventAdd)
|
c.queueClusterEvent(nil, pg, EventAdd)
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Controller) postgresqlUpdate(prev, cur interface{}) {
|
func (c *Controller) postgresqlUpdate(prev, cur interface{}) {
|
||||||
pgOld, ok := prev.(*acidv1.Postgresql)
|
pgOld := c.postgresqlCheck(prev)
|
||||||
if !ok {
|
pgNew := c.postgresqlCheck(cur)
|
||||||
c.logger.Errorf("could not cast to postgresql spec")
|
if pgOld != nil && pgNew != nil {
|
||||||
}
|
|
||||||
pgNew, ok := cur.(*acidv1.Postgresql)
|
|
||||||
if !ok {
|
|
||||||
c.logger.Errorf("could not cast to postgresql spec")
|
|
||||||
}
|
|
||||||
// Avoid the inifinite recursion for status updates
|
// Avoid the inifinite recursion for status updates
|
||||||
if reflect.DeepEqual(pgOld.Spec, pgNew.Spec) {
|
if reflect.DeepEqual(pgOld.Spec, pgNew.Spec) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
c.queueClusterEvent(pgOld, pgNew, EventUpdate)
|
c.queueClusterEvent(pgOld, pgNew, EventUpdate)
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Controller) postgresqlDelete(obj interface{}) {
|
func (c *Controller) postgresqlDelete(obj interface{}) {
|
||||||
|
pg := c.postgresqlCheck(obj)
|
||||||
|
if pg != nil {
|
||||||
|
c.queueClusterEvent(pg, nil, EventDelete)
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Controller) postgresqlCheck(obj interface{}) *acidv1.Postgresql {
|
||||||
pg, ok := obj.(*acidv1.Postgresql)
|
pg, ok := obj.(*acidv1.Postgresql)
|
||||||
if !ok {
|
if !ok {
|
||||||
c.logger.Errorf("could not cast to postgresql spec")
|
c.logger.Errorf("could not cast to postgresql spec")
|
||||||
return
|
return nil
|
||||||
}
|
}
|
||||||
|
if !c.hasOwnership(pg) {
|
||||||
c.queueClusterEvent(pg, nil, EventDelete)
|
return nil
|
||||||
|
}
|
||||||
|
return pg
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,12 @@
|
||||||
package controller
|
package controller
|
||||||
|
|
||||||
import (
|
import (
|
||||||
acidv1 "github.com/zalando/postgres-operator/pkg/apis/acid.zalan.do/v1"
|
|
||||||
"github.com/zalando/postgres-operator/pkg/spec"
|
|
||||||
"reflect"
|
"reflect"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
acidv1 "github.com/zalando/postgres-operator/pkg/apis/acid.zalan.do/v1"
|
||||||
|
"github.com/zalando/postgres-operator/pkg/spec"
|
||||||
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
|
@ -12,9 +14,55 @@ var (
|
||||||
False = false
|
False = false
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestMergeDeprecatedPostgreSQLSpecParameters(t *testing.T) {
|
func newPostgresqlTestController() *Controller {
|
||||||
c := NewController(&spec.ControllerConfig{})
|
controller := NewController(&spec.ControllerConfig{}, "postgresql-test")
|
||||||
|
return controller
|
||||||
|
}
|
||||||
|
|
||||||
|
var postgresqlTestController = newPostgresqlTestController()
|
||||||
|
|
||||||
|
func TestControllerOwnershipOnPostgresql(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
pg *acidv1.Postgresql
|
||||||
|
owned bool
|
||||||
|
error string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
"Postgres cluster with defined ownership of mocked controller",
|
||||||
|
&acidv1.Postgresql{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Annotations: map[string]string{"acid.zalan.do/controller": "postgresql-test"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
True,
|
||||||
|
"Postgres cluster should be owned by operator, but controller says no",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Postgres cluster with defined ownership of another controller",
|
||||||
|
&acidv1.Postgresql{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Annotations: map[string]string{"acid.zalan.do/controller": "stups-test"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
False,
|
||||||
|
"Postgres cluster should be owned by another operator, but controller say yes",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Test Postgres cluster without defined ownership",
|
||||||
|
&acidv1.Postgresql{},
|
||||||
|
False,
|
||||||
|
"Postgres cluster should be owned by operator with empty controller ID, but controller says yes",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
if postgresqlTestController.hasOwnership(tt.pg) != tt.owned {
|
||||||
|
t.Errorf("%s: %v", tt.name, tt.error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMergeDeprecatedPostgreSQLSpecParameters(t *testing.T) {
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
in *acidv1.PostgresSpec
|
in *acidv1.PostgresSpec
|
||||||
|
|
@ -36,7 +84,7 @@ func TestMergeDeprecatedPostgreSQLSpecParameters(t *testing.T) {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
result := c.mergeDeprecatedPostgreSQLSpecParameters(tt.in)
|
result := postgresqlTestController.mergeDeprecatedPostgreSQLSpecParameters(tt.in)
|
||||||
if !reflect.DeepEqual(result, tt.out) {
|
if !reflect.DeepEqual(result, tt.out) {
|
||||||
t.Errorf("%s: %v", tt.name, tt.error)
|
t.Errorf("%s: %v", tt.name, tt.error)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -17,8 +17,8 @@ const (
|
||||||
testInfrastructureRolesSecretName = "infrastructureroles-test"
|
testInfrastructureRolesSecretName = "infrastructureroles-test"
|
||||||
)
|
)
|
||||||
|
|
||||||
func newMockController() *Controller {
|
func newUtilTestController() *Controller {
|
||||||
controller := NewController(&spec.ControllerConfig{})
|
controller := NewController(&spec.ControllerConfig{}, "util-test")
|
||||||
controller.opConfig.ClusterNameLabel = "cluster-name"
|
controller.opConfig.ClusterNameLabel = "cluster-name"
|
||||||
controller.opConfig.InfrastructureRolesSecretName =
|
controller.opConfig.InfrastructureRolesSecretName =
|
||||||
spec.NamespacedName{Namespace: v1.NamespaceDefault, Name: testInfrastructureRolesSecretName}
|
spec.NamespacedName{Namespace: v1.NamespaceDefault, Name: testInfrastructureRolesSecretName}
|
||||||
|
|
@ -27,7 +27,7 @@ func newMockController() *Controller {
|
||||||
return controller
|
return controller
|
||||||
}
|
}
|
||||||
|
|
||||||
var mockController = newMockController()
|
var utilTestController = newUtilTestController()
|
||||||
|
|
||||||
func TestPodClusterName(t *testing.T) {
|
func TestPodClusterName(t *testing.T) {
|
||||||
var testTable = []struct {
|
var testTable = []struct {
|
||||||
|
|
@ -43,7 +43,7 @@ func TestPodClusterName(t *testing.T) {
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
Namespace: v1.NamespaceDefault,
|
Namespace: v1.NamespaceDefault,
|
||||||
Labels: map[string]string{
|
Labels: map[string]string{
|
||||||
mockController.opConfig.ClusterNameLabel: "testcluster",
|
utilTestController.opConfig.ClusterNameLabel: "testcluster",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
@ -51,7 +51,7 @@ func TestPodClusterName(t *testing.T) {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
for _, test := range testTable {
|
for _, test := range testTable {
|
||||||
resp := mockController.podClusterName(test.in)
|
resp := utilTestController.podClusterName(test.in)
|
||||||
if resp != test.expected {
|
if resp != test.expected {
|
||||||
t.Errorf("expected response %v does not match the actual %v", test.expected, resp)
|
t.Errorf("expected response %v does not match the actual %v", test.expected, resp)
|
||||||
}
|
}
|
||||||
|
|
@ -73,7 +73,7 @@ func TestClusterWorkerID(t *testing.T) {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
for _, test := range testTable {
|
for _, test := range testTable {
|
||||||
resp := mockController.clusterWorkerID(test.in)
|
resp := utilTestController.clusterWorkerID(test.in)
|
||||||
if resp != test.expected {
|
if resp != test.expected {
|
||||||
t.Errorf("expected response %v does not match the actual %v", test.expected, resp)
|
t.Errorf("expected response %v does not match the actual %v", test.expected, resp)
|
||||||
}
|
}
|
||||||
|
|
@ -116,7 +116,7 @@ func TestGetInfrastructureRoles(t *testing.T) {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
for _, test := range testTable {
|
for _, test := range testTable {
|
||||||
roles, err := mockController.getInfrastructureRoles(&test.secretName)
|
roles, err := utilTestController.getInfrastructureRoles(&test.secretName)
|
||||||
if err != test.expectedError {
|
if err != test.expectedError {
|
||||||
if err != nil && test.expectedError != nil && err.Error() == test.expectedError.Error() {
|
if err != nil && test.expectedError != nil && err.Error() == test.expectedError.Error() {
|
||||||
continue
|
continue
|
||||||
|
|
|
||||||
|
|
@ -7,4 +7,5 @@ const (
|
||||||
ElbTimeoutAnnotationValue = "3600"
|
ElbTimeoutAnnotationValue = "3600"
|
||||||
KubeIAmAnnotation = "iam.amazonaws.com/role"
|
KubeIAmAnnotation = "iam.amazonaws.com/role"
|
||||||
VolumeStorateProvisionerAnnotation = "pv.kubernetes.io/provisioned-by"
|
VolumeStorateProvisionerAnnotation = "pv.kubernetes.io/provisioned-by"
|
||||||
|
PostgresqlControllerAnnotationKey = "acid.zalan.do/controller"
|
||||||
)
|
)
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue