Use TPR object namespace while creating its objects

This commit is contained in:
Murat Kabilov 2017-02-20 11:23:31 +01:00
parent 9169808133
commit dfde075c66
6 changed files with 58 additions and 47 deletions

View File

@ -16,7 +16,7 @@ import (
var ( var (
KubeConfigFile string KubeConfigFile string
Namespace string podNamespace string
OutOfCluster bool OutOfCluster bool
version string version string
) )
@ -26,9 +26,9 @@ func init() {
flag.BoolVar(&OutOfCluster, "outofcluster", false, "Whether the operator runs in- our outside of the Kubernetes cluster.") flag.BoolVar(&OutOfCluster, "outofcluster", false, "Whether the operator runs in- our outside of the Kubernetes cluster.")
flag.Parse() flag.Parse()
Namespace = os.Getenv("MY_POD_NAMESPACE") podNamespace = os.Getenv("MY_POD_NAMESPACE")
if len(Namespace) == 0 { if len(podNamespace) == 0 {
Namespace = "default" podNamespace = "default"
} }
} }
@ -47,7 +47,7 @@ func ControllerConfig() *controller.Config {
teamsApi := teams.NewTeamsAPI(constants.TeamsAPIUrl) teamsApi := teams.NewTeamsAPI(constants.TeamsAPIUrl)
return &controller.Config{ return &controller.Config{
Namespace: Namespace, PodNamespace: podNamespace,
KubeClient: client, KubeClient: client,
RestClient: restClient, RestClient: restClient,
TeamsAPIClient: teamsApi, TeamsAPIClient: teamsApi,

View File

@ -2,6 +2,7 @@ apiVersion: extensions/v1beta1
kind: Deployment kind: Deployment
metadata: metadata:
name: postgres-operator name: postgres-operator
namespace: acid
spec: spec:
replicas: 1 replicas: 1
template: template:

View File

@ -3,6 +3,7 @@ kind: "Postgresql"
metadata: metadata:
name: testcluster name: testcluster
namespace: acid
spec: spec:
teamId: "50051320" teamId: "50051320"

View File

@ -33,11 +33,11 @@ var (
//TODO: remove struct duplication //TODO: remove struct duplication
type Config struct { type Config struct {
Namespace string ControllerNamespace string
KubeClient *kubernetes.Clientset //TODO: move clients to the better place? KubeClient *kubernetes.Clientset //TODO: move clients to the better place?
RestClient *rest.RESTClient RestClient *rest.RESTClient
EtcdClient etcdclient.KeysAPI EtcdClient etcdclient.KeysAPI
TeamsAPIClient *teams.TeamsAPI TeamsAPIClient *teams.TeamsAPI
} }
type pgUser struct { type pgUser struct {
@ -74,7 +74,8 @@ func New(cfg Config, spec *spec.Postgresql) *Cluster {
} }
func (c *Cluster) getReadonlyToken() (string, error) { func (c *Cluster) getReadonlyToken() (string, error) {
credentialsSecret, err := c.config.KubeClient.Secrets(c.config.Namespace).Get("postgresql-operator") // for some reason PlatformCredentialsSet creates secrets only in the default namespace
credentialsSecret, err := c.config.KubeClient.Secrets(v1.NamespaceDefault).Get("postgresql-operator")
if err != nil { if err != nil {
return "", fmt.Errorf("Can't get credentials secret: %s", err) return "", fmt.Errorf("Can't get credentials secret: %s", err)
@ -198,7 +199,7 @@ func (c *Cluster) waitPodDelete() error {
return retryutil.Retry( return retryutil.Retry(
constants.ResourceCheckInterval, int(constants.ResourceCheckTimeout/constants.ResourceCheckInterval), constants.ResourceCheckInterval, int(constants.ResourceCheckTimeout/constants.ResourceCheckInterval),
func() (bool, error) { func() (bool, error) {
pods, err := c.config.KubeClient.Pods(c.config.Namespace).List(listOptions) pods, err := c.config.KubeClient.Pods((*c.cluster).Metadata.Namespace).List(listOptions)
if err != nil { if err != nil {
return false, err return false, err
} }
@ -213,7 +214,7 @@ func (c *Cluster) waitStatefulsetReady() error {
listOptions := v1.ListOptions{ listOptions := v1.ListOptions{
LabelSelector: c.labelsSet().String(), LabelSelector: c.labelsSet().String(),
} }
ss, err := c.config.KubeClient.StatefulSets(c.config.Namespace).List(listOptions) ss, err := c.config.KubeClient.StatefulSets((*c.cluster).Metadata.Namespace).List(listOptions)
if err != nil { if err != nil {
return false, err return false, err
} }
@ -228,6 +229,7 @@ func (c *Cluster) waitStatefulsetReady() error {
func (c *Cluster) waitPodLabelsReady() error { func (c *Cluster) waitPodLabelsReady() error {
ls := c.labelsSet() ls := c.labelsSet()
namespace := (*c.cluster).Metadata.Namespace
listOptions := v1.ListOptions{ listOptions := v1.ListOptions{
LabelSelector: ls.String(), LabelSelector: ls.String(),
@ -238,7 +240,7 @@ func (c *Cluster) waitPodLabelsReady() error {
replicaListOption := v1.ListOptions{ replicaListOption := v1.ListOptions{
LabelSelector: labels.Merge(ls, labels.Set{"spilo-role": "replica"}).String(), LabelSelector: labels.Merge(ls, labels.Set{"spilo-role": "replica"}).String(),
} }
pods, err := c.config.KubeClient.Pods(c.config.Namespace).List(listOptions) pods, err := c.config.KubeClient.Pods(namespace).List(listOptions)
if err != nil { if err != nil {
return err return err
} }
@ -247,11 +249,11 @@ func (c *Cluster) waitPodLabelsReady() error {
return retryutil.Retry( return retryutil.Retry(
constants.ResourceCheckInterval, int(constants.ResourceCheckTimeout/constants.ResourceCheckInterval), constants.ResourceCheckInterval, int(constants.ResourceCheckTimeout/constants.ResourceCheckInterval),
func() (bool, error) { func() (bool, error) {
masterPods, err := c.config.KubeClient.Pods(c.config.Namespace).List(masterListOption) masterPods, err := c.config.KubeClient.Pods(namespace).List(masterListOption)
if err != nil { if err != nil {
return false, err return false, err
} }
replicaPods, err := c.config.KubeClient.Pods(c.config.Namespace).List(replicaListOption) replicaPods, err := c.config.KubeClient.Pods(namespace).List(replicaListOption)
if err != nil { if err != nil {
return false, err return false, err
} }
@ -305,7 +307,7 @@ func (c *Cluster) waitClusterReady() error {
func (c *Cluster) Delete() error { func (c *Cluster) Delete() error {
clusterName := (*c.cluster).Metadata.Name clusterName := (*c.cluster).Metadata.Name
namespace := c.config.Namespace namespace := (*c.cluster).Metadata.Namespace
orphanDependents := false orphanDependents := false
deleteOptions := &v1.DeleteOptions{ deleteOptions := &v1.DeleteOptions{
OrphanDependents: &orphanDependents, OrphanDependents: &orphanDependents,

View File

@ -22,12 +22,12 @@ END;
$$` $$`
func (c *Cluster) createStatefulSet() { func (c *Cluster) createStatefulSet() {
clusterName := (*c.cluster).Metadata.Name meta := (*c.cluster).Metadata
envVars := []v1.EnvVar{ envVars := []v1.EnvVar{
{ {
Name: "SCOPE", Name: "SCOPE",
Value: clusterName, Value: meta.Name,
}, },
{ {
Name: "PGROOT", Name: "PGROOT",
@ -114,7 +114,7 @@ bootstrap:
} }
container := v1.Container{ container := v1.Container{
Name: clusterName, Name: meta.Name,
Image: c.dockerImage, Image: c.dockerImage,
ImagePullPolicy: v1.PullAlways, ImagePullPolicy: v1.PullAlways,
Resources: v1.ResourceRequirements{ Resources: v1.ResourceRequirements{
@ -155,6 +155,7 @@ bootstrap:
template := v1.PodTemplateSpec{ template := v1.PodTemplateSpec{
ObjectMeta: v1.ObjectMeta{ ObjectMeta: v1.ObjectMeta{
Labels: c.labelsSet(), Labels: c.labelsSet(),
Namespace: meta.Namespace,
Annotations: map[string]string{"pod.alpha.kubernetes.io/initialized": "true"}, Annotations: map[string]string{"pod.alpha.kubernetes.io/initialized": "true"},
}, },
Spec: podSpec, Spec: podSpec,
@ -162,17 +163,18 @@ bootstrap:
statefulSet := &v1beta1.StatefulSet{ statefulSet := &v1beta1.StatefulSet{
ObjectMeta: v1.ObjectMeta{ ObjectMeta: v1.ObjectMeta{
Name: clusterName, Name: meta.Name,
Labels: c.labelsSet(), Namespace: meta.Namespace,
Labels: c.labelsSet(),
}, },
Spec: v1beta1.StatefulSetSpec{ Spec: v1beta1.StatefulSetSpec{
Replicas: &c.cluster.Spec.NumberOfInstances, Replicas: &c.cluster.Spec.NumberOfInstances,
ServiceName: clusterName, ServiceName: meta.Name,
Template: template, Template: template,
}, },
} }
_, err := c.config.KubeClient.StatefulSets(c.config.Namespace).Create(statefulSet) _, err := c.config.KubeClient.StatefulSets(meta.Namespace).Create(statefulSet)
if err != nil { if err != nil {
c.logger.Errorf("Can't create statefulset: %s", err) c.logger.Errorf("Can't create statefulset: %s", err)
} else { } else {
@ -182,6 +184,7 @@ bootstrap:
func (c *Cluster) applySecrets() { func (c *Cluster) applySecrets() {
var err error var err error
namespace := (*c.cluster).Metadata.Namespace
for username, pgUser := range c.pgUsers { for username, pgUser := range c.pgUsers {
//Skip users with no password i.e. human users (they'll be authenticated using pam) //Skip users with no password i.e. human users (they'll be authenticated using pam)
if pgUser.password == "" { if pgUser.password == "" {
@ -189,8 +192,9 @@ func (c *Cluster) applySecrets() {
} }
secret := v1.Secret{ secret := v1.Secret{
ObjectMeta: v1.ObjectMeta{ ObjectMeta: v1.ObjectMeta{
Name: c.credentialSecretName(username), Name: c.credentialSecretName(username),
Labels: c.labelsSet(), Namespace: namespace,
Labels: c.labelsSet(),
}, },
Type: v1.SecretTypeOpaque, Type: v1.SecretTypeOpaque,
Data: map[string][]byte{ Data: map[string][]byte{
@ -198,11 +202,11 @@ func (c *Cluster) applySecrets() {
"password": []byte(pgUser.password), "password": []byte(pgUser.password),
}, },
} }
_, err = c.config.KubeClient.Secrets(c.config.Namespace).Create(&secret) _, err = c.config.KubeClient.Secrets(namespace).Create(&secret)
if k8sutil.IsKubernetesResourceAlreadyExistError(err) { if k8sutil.IsKubernetesResourceAlreadyExistError(err) {
c.logger.Infof("Skipping update of '%s'", secret.Name) c.logger.Infof("Skipping update of '%s'", secret.Name)
curSecrets, err := c.config.KubeClient.Secrets(c.config.Namespace).Get(c.credentialSecretName(username)) curSecrets, err := c.config.KubeClient.Secrets(namespace).Get(c.credentialSecretName(username))
if err != nil { if err != nil {
c.logger.Errorf("Can't get current secret: %s", err) c.logger.Errorf("Can't get current secret: %s", err)
} }
@ -223,18 +227,19 @@ func (c *Cluster) applySecrets() {
} }
func (c *Cluster) createService() { func (c *Cluster) createService() {
clusterName := (*c.cluster).Metadata.Name meta := (*c.cluster).Metadata
_, err := c.config.KubeClient.Services(c.config.Namespace).Get(clusterName) _, err := c.config.KubeClient.Services(meta.Namespace).Get(meta.Name)
if !k8sutil.ResourceNotFound(err) { if !k8sutil.ResourceNotFound(err) {
c.logger.Infof("Service '%s' already exists", clusterName) c.logger.Infof("Service '%s' already exists", meta.Name)
return return
} }
service := v1.Service{ service := v1.Service{
ObjectMeta: v1.ObjectMeta{ ObjectMeta: v1.ObjectMeta{
Name: clusterName, Name: meta.Name,
Labels: c.labelsSet(), Namespace: meta.Namespace,
Labels: c.labelsSet(),
}, },
Spec: v1.ServiceSpec{ Spec: v1.ServiceSpec{
Type: v1.ServiceTypeLoadBalancer, Type: v1.ServiceTypeLoadBalancer,
@ -243,7 +248,7 @@ func (c *Cluster) createService() {
}, },
} }
_, err = c.config.KubeClient.Services(c.config.Namespace).Create(&service) _, err = c.config.KubeClient.Services(meta.Namespace).Create(&service)
if err != nil { if err != nil {
c.logger.Errorf("Error while creating service: %+v", err) c.logger.Errorf("Error while creating service: %+v", err)
} else { } else {
@ -252,22 +257,23 @@ func (c *Cluster) createService() {
} }
func (c *Cluster) createEndpoint() { func (c *Cluster) createEndpoint() {
clusterName := (*c.cluster).Metadata.Name meta := (*c.cluster).Metadata
_, err := c.config.KubeClient.Endpoints(c.config.Namespace).Get(clusterName) _, err := c.config.KubeClient.Endpoints(meta.Namespace).Get(meta.Name)
if !k8sutil.ResourceNotFound(err) { if !k8sutil.ResourceNotFound(err) {
c.logger.Infof("Endpoint '%s' already exists", clusterName) c.logger.Infof("Endpoint '%s' already exists", meta.Name)
return return
} }
endpoint := v1.Endpoints{ endpoint := v1.Endpoints{
ObjectMeta: v1.ObjectMeta{ ObjectMeta: v1.ObjectMeta{
Name: clusterName, Name: meta.Name,
Labels: c.labelsSet(), Namespace: meta.Namespace,
Labels: c.labelsSet(),
}, },
} }
_, err = c.config.KubeClient.Endpoints(c.config.Namespace).Create(&endpoint) _, err = c.config.KubeClient.Endpoints(meta.Namespace).Create(&endpoint)
if err != nil { if err != nil {
c.logger.Errorf("Error while creating endpoint: %+v", err) c.logger.Errorf("Error while creating endpoint: %+v", err)
} else { } else {

View File

@ -22,7 +22,7 @@ import (
) )
type Config struct { type Config struct {
Namespace string PodNamespace string
KubeClient *kubernetes.Clientset KubeClient *kubernetes.Clientset
RestClient *rest.RESTClient RestClient *rest.RESTClient
EtcdClient etcdclient.KeysAPI EtcdClient etcdclient.KeysAPI
@ -81,6 +81,7 @@ func (c *Controller) createTPR() error {
tpr := &v1beta1extensions.ThirdPartyResource{ tpr := &v1beta1extensions.ThirdPartyResource{
ObjectMeta: v1.ObjectMeta{ ObjectMeta: v1.ObjectMeta{
Name: TPRName, Name: TPRName,
//PodNamespace: c.config.PodNamespace, //ThirdPartyResources are cluster-wide
}, },
Versions: []v1beta1extensions.APIVersion{ Versions: []v1beta1extensions.APIVersion{
{Name: constants.TPRApiVersion}, {Name: constants.TPRApiVersion},
@ -101,16 +102,16 @@ func (c *Controller) createTPR() error {
restClient := c.config.RestClient restClient := c.config.RestClient
return k8sutil.WaitTPRReady(restClient, constants.TPRReadyWaitInterval, constants.TPRReadyWaitTimeout, c.config.Namespace) return k8sutil.WaitTPRReady(restClient, constants.TPRReadyWaitInterval, constants.TPRReadyWaitTimeout, c.config.PodNamespace)
} }
func (c *Controller) makeClusterConfig() cluster.Config { func (c *Controller) makeClusterConfig() cluster.Config {
return cluster.Config{ return cluster.Config{
Namespace: c.config.Namespace, ControllerNamespace: c.config.PodNamespace,
KubeClient: c.config.KubeClient, KubeClient: c.config.KubeClient,
RestClient: c.config.RestClient, RestClient: c.config.RestClient,
EtcdClient: c.config.EtcdClient, EtcdClient: c.config.EtcdClient,
TeamsAPIClient: c.config.TeamsAPIClient, TeamsAPIClient: c.config.TeamsAPIClient,
} }
} }