diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 000000000..4ba224022 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,5 @@ +FROM alpine +ADD postgres-operator /usr/local/bin + +CMD ["/usr/local/bin/postgres-operator"] + diff --git a/pkg/controller/operator.go b/pkg/controller/operator.go index 5ecb75cdb..eed1695fd 100644 --- a/pkg/controller/operator.go +++ b/pkg/controller/operator.go @@ -31,21 +31,23 @@ type Options struct { KubeConfig string } -func KubernetesConfig(options Options) *rest.Config { - rules := clientcmd.NewDefaultClientConfigLoadingRules() - overrides := &clientcmd.ConfigOverrides{} - - if options.KubeConfig != "" { +func KubernetesConfig(options Options) (config *rest.Config, is_in_cluster bool) { + var err error + is_in_cluster = (options.KubeConfig == "") + if !is_in_cluster { + /* out-of-cluster process */ + rules := clientcmd.NewDefaultClientConfigLoadingRules() + overrides := &clientcmd.ConfigOverrides{} rules.ExplicitPath = options.KubeConfig + config, err = clientcmd.NewNonInteractiveDeferredLoadingClientConfig(rules, overrides).ClientConfig() + } else { + /* in-cluster pod */ + config, err = rest.InClusterConfig() } - - config, err := clientcmd.NewNonInteractiveDeferredLoadingClientConfig(rules, overrides).ClientConfig() - if err != nil { log.Fatalf("Couldn't get Kubernetes default config: %s", err) } - - return config + return } func newKubernetesSpiloClient(c *rest.Config) (*rest.RESTClient, error) { diff --git a/pkg/controller/spilo.go b/pkg/controller/spilo.go index 09cc54662..26950a7a7 100644 --- a/pkg/controller/spilo.go +++ b/pkg/controller/spilo.go @@ -10,7 +10,7 @@ import ( "k8s.io/client-go/kubernetes" "k8s.io/client-go/rest" - "github.bus.zalan.do/acid/postgres-operator/pkg/etcd" + "github.bus.zalan.do/acid/postgres-operator/pkg/etcd" ) type SpiloOperator struct { @@ -19,36 +19,42 @@ type SpiloOperator struct { ClientSet *kubernetes.Clientset Client *rest.RESTClient Controller *SpiloController - EtcdClient *etcd.EtcdClient + EtcdClient *etcd.EtcdClient +} + + +func getEtcdServiceName(cls *kubernetes.Clientset, config *rest.Config, is_in_cluster bool) (etcdServiceName string) { + etcdService, _ := cls.Services("default").Get("etcd-client") + if is_in_cluster { + if len(etcdService.Spec.Ports) != 1 { + log.Fatal("Can't find Etcd service named 'etcd-client'") + } + etcdServiceName = fmt.Sprintf("%s.%s.svc.cluster.local", etcdService.Name, etcdService.Namespace) + } else { + ports := etcdService.Spec.Ports[0] + if ports.NodePort == 0 { + log.Fatal("Etcd port is not exposed\nHint: add NodePort to your Etcd service") + } + nodeurl, _ := url.Parse(config.Host) + etcdServiceName = fmt.Sprintf("http://%s:%d", strings.Split(nodeurl.Host, ":")[0], ports.NodePort) + } + return } func New(options Options) *SpiloOperator { - config := KubernetesConfig(options) - - clientSet, err := kubernetes.NewForConfig(config) - if err != nil { - log.Fatalf("Couldn't create Kubernetes client: %s", err) - } - - etcdService, _ := clientSet.Services("default").Get("etcd-client") - if len(etcdService.Spec.Ports) != 1 { - log.Fatalln("Can't find Etcd cluster") - } - ports := etcdService.Spec.Ports[0] - nodeurl, _ := url.Parse(config.Host) - - if ports.NodePort == 0 { - log.Fatalln("Etcd port is not exposed") - } - - etcdHostOutside := fmt.Sprintf("http://%s:%d", strings.Split(nodeurl.Host, ":")[0], ports.NodePort) + config, is_in_cluster := KubernetesConfig(options) spiloClient, err := newKubernetesSpiloClient(config) if err != nil { log.Fatalf("Couldn't create Spilo client: %s", err) } - etcdClient := etcd.NewEctdClient(etcdHostOutside) + clientSet, err := kubernetes.NewForConfig(config) + if err != nil { + log.Fatalf("Couldn't create Kubernetes client: %s", err) + } + + etcdClient := etcd.NewEctdClient(getEtcdServiceName(clientSet, config, is_in_cluster)) operator := &SpiloOperator{ Options: options, diff --git a/postgres-operator.yaml b/postgres-operator.yaml new file mode 100644 index 000000000..2df5afeda --- /dev/null +++ b/postgres-operator.yaml @@ -0,0 +1,19 @@ +apiVersion: extensions/v1beta1 +kind: Deployment +metadata: + name: postgres-operator +spec: + replicas: 1 + template: + metadata: + labels: + name: postgres-operator + spec: + containers: + - name: postgres-operator + image: postgres-operator:0.1 + env: + - name: MY_POD_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace