github.com/docker/compose-on-kubernetes@v0.5.0/cmd/installer/main.go (about)

     1  package main
     2  
     3  import (
     4  	"context"
     5  	"errors"
     6  	"flag"
     7  	"fmt"
     8  	"io/ioutil"
     9  	"os"
    10  
    11  	"github.com/docker/compose-on-kubernetes/api/constants"
    12  	"github.com/docker/compose-on-kubernetes/install"
    13  	customflags "github.com/docker/compose-on-kubernetes/internal/flags"
    14  	homedir "github.com/mitchellh/go-homedir"
    15  	log "github.com/sirupsen/logrus"
    16  	corev1types "k8s.io/api/core/v1"
    17  	_ "k8s.io/client-go/plugin/pkg/client/auth/gcp" // For Google Kubernetes Engine authentication
    18  	"k8s.io/client-go/rest"
    19  	"k8s.io/client-go/tools/clientcmd"
    20  )
    21  
    22  func main() {
    23  	if err := do(); err != nil {
    24  		fmt.Fprintf(os.Stderr, "Installation failed: %s", err)
    25  		os.Exit(1)
    26  	}
    27  }
    28  
    29  func do() error {
    30  	installerConfig, err := parseOptions()
    31  	if err != nil {
    32  		return err
    33  	}
    34  	if installerConfig.uninstall {
    35  		err := install.Uninstall(installerConfig.restConfig, installerConfig.options.Namespace, false)
    36  		if err != nil {
    37  			return err
    38  		}
    39  		return install.WaitForUninstallCompletion(context.Background(), installerConfig.restConfig, installerConfig.options.Namespace, false)
    40  	}
    41  	return install.Safe(context.Background(), installerConfig.restConfig, installerConfig.options)
    42  }
    43  
    44  type installerConfig struct {
    45  	uninstall  bool
    46  	options    install.SafeOptions
    47  	restConfig *rest.Config
    48  }
    49  
    50  func parseOptions() (installerConfig, error) {
    51  	var flags additionalFlags
    52  	var options install.SafeOptions
    53  	parseFlags(&flags, &options)
    54  	loggerLevel, err := log.ParseLevel(flags.logLevel)
    55  	if err != nil {
    56  		return installerConfig{}, err
    57  	}
    58  	log.SetLevel(loggerLevel)
    59  
    60  	pp, err := parsePullPolicy(flags.pullPolicy)
    61  	if err != nil {
    62  		return installerConfig{}, err
    63  	}
    64  	options.OptionsCommon.PullPolicy = pp
    65  
    66  	options.Etcd.ClientTLSBundle, err = flags.etcdBundle.load()
    67  	if err != nil {
    68  		return installerConfig{}, err
    69  	}
    70  	options.Network.CustomTLSBundle, err = flags.tlsBundle.load()
    71  	if err != nil {
    72  		return installerConfig{}, err
    73  	}
    74  	configFile, err := homedir.Expand(flags.kubeconfig)
    75  	if err != nil {
    76  		return installerConfig{}, err
    77  	}
    78  	config, err := clientcmd.BuildConfigFromFlags("", configFile)
    79  	if err != nil {
    80  		return installerConfig{}, err
    81  	}
    82  	if flags.skipLivenessProbes {
    83  		options.HealthzCheckPort = 0
    84  	}
    85  	if flags.apiServerReplicas != 1 {
    86  		replicas := int32(flags.apiServerReplicas)
    87  		options.APIServerReplicas = &replicas
    88  	}
    89  	return installerConfig{
    90  		options:    options,
    91  		restConfig: config,
    92  		uninstall:  flags.uninstall,
    93  	}, nil
    94  }
    95  
    96  func parsePullPolicy(pullPolicy string) (corev1types.PullPolicy, error) {
    97  	switch pp := corev1types.PullPolicy(pullPolicy); pp {
    98  	case corev1types.PullAlways, corev1types.PullNever, corev1types.PullIfNotPresent:
    99  		return pp, nil
   100  	default:
   101  		return "", fmt.Errorf("invalid pull policy: %q", pullPolicy)
   102  	}
   103  }
   104  
   105  type additionalFlags struct {
   106  	etcdBundle         certBundleSource
   107  	tlsBundle          certBundleSource
   108  	logLevel           string
   109  	pullPolicy         string
   110  	kubeconfig         string
   111  	uninstall          bool
   112  	skipLivenessProbes bool
   113  	apiServerReplicas  int
   114  }
   115  
   116  func parseFlags(customFlags *additionalFlags, options *install.SafeOptions) {
   117  	flag.BoolVar(&options.Network.ShouldUseHost, "network-host", false, "Use network host")
   118  	flag.StringVar(&options.OptionsCommon.Namespace, "namespace", "docker", "Namespace in which to deploy")
   119  	flag.DurationVar(&options.OptionsCommon.ReconciliationInterval, "reconciliation-interval", constants.DefaultFullSyncInterval, "Interval of reconciliation loop")
   120  	flag.StringVar(&options.OptionsCommon.Tag, "tag", "latest", "Image tag")
   121  	pullPolicyDescription := fmt.Sprintf("Image pull policy (%q|%q|%q)", corev1types.PullAlways, corev1types.PullNever, corev1types.PullIfNotPresent)
   122  	flag.StringVar(&customFlags.pullPolicy, "pull-policy", string(corev1types.PullAlways), pullPolicyDescription)
   123  	flag.StringVar(&options.Etcd.Servers, "etcd-servers", "", "etcd server addresses")
   124  	flag.BoolVar(&customFlags.skipLivenessProbes, "skip-liveness-probes", false, "Disable liveness probe on Controller and API server deployments. Use this when HTTPS liveness probe fails.")
   125  	flag.IntVar(&options.HealthzCheckPort, "healthz-check-port", 8080, "Defines the port used by healthz check server for api-server and controller (0 to disable it)")
   126  
   127  	flag.StringVar(&customFlags.etcdBundle.ca, "etcd-ca-file", "", "CA of etcd TLS certificate")
   128  	flag.StringVar(&customFlags.etcdBundle.cert, "etcd-cert-file", "", "TLS client certificate for accessing etcd")
   129  	flag.StringVar(&customFlags.etcdBundle.key, "etcd-key-file", "", "TLS client private key for accessing etcd")
   130  
   131  	flag.StringVar(&customFlags.tlsBundle.ca, "tls-ca-file", "", "CA used to generate the TLS certificate")
   132  	flag.StringVar(&customFlags.tlsBundle.cert, "tls-cert-file", "", "Server TLS certificate (must be valid for name compose-api.<namespace>.svc)")
   133  	flag.StringVar(&customFlags.tlsBundle.key, "tls-key-file", "", "Server TLS private key")
   134  	flag.BoolVar(&customFlags.uninstall, "uninstall", false, "Uninstall")
   135  	flag.StringVar(&customFlags.logLevel, "log-level", "info", `Set the log level ("debug"|"info"|"warn"|"error"|"fatal")`)
   136  	flag.IntVar(&customFlags.apiServerReplicas, "apiserver-replicas", 1, "Number of replicas for the API Server")
   137  	kubeconfigFlag := customflags.EnvString("kubeconfig", "~/.kube/config", "KUBECONFIG", "Path to a kubeconfig file (set to \"\" to use incluster config)")
   138  	flag.Parse()
   139  	customFlags.kubeconfig = kubeconfigFlag.String()
   140  }
   141  
   142  type certBundleSource struct {
   143  	ca, cert, key string
   144  }
   145  
   146  func (s certBundleSource) empty() bool {
   147  	return s.ca == "" && s.cert == "" && s.key == ""
   148  }
   149  
   150  func (s certBundleSource) load() (*install.TLSBundle, error) {
   151  	if s.empty() {
   152  		return nil, nil
   153  	}
   154  	if s.ca == "" || s.cert == "" || s.key == "" {
   155  		return nil, errors.New("ca-file, cert-file and key-file must be set altogether or not at all")
   156  	}
   157  	caBytes, err := ioutil.ReadFile(s.ca)
   158  	if err != nil {
   159  		return nil, err
   160  	}
   161  	certBytes, err := ioutil.ReadFile(s.cert)
   162  	if err != nil {
   163  		return nil, err
   164  	}
   165  	keyBytes, err := ioutil.ReadFile(s.key)
   166  	if err != nil {
   167  		return nil, err
   168  	}
   169  	bundle, err := install.NewTLSBundle(caBytes, certBytes, keyBytes)
   170  	if err != nil {
   171  		return nil, err
   172  	}
   173  	return bundle, nil
   174  }