WIP: allow operator to run both in- and out- of cluster.
This commit is contained in:
		
							parent
							
								
									5b5a64e55d
								
							
						
					
					
						commit
						38bc9da25a
					
				| 
						 | 
				
			
			@ -0,0 +1,5 @@
 | 
			
		|||
FROM alpine
 | 
			
		||||
ADD postgres-operator /usr/local/bin
 | 
			
		||||
 | 
			
		||||
CMD ["/usr/local/bin/postgres-operator"] 
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -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) {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
		Loading…
	
		Reference in New Issue