github.com/docker/compose-on-kubernetes@v0.5.0/install/safe.go (about)

     1  package install
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  
     7  	corev1types "k8s.io/api/core/v1"
     8  	apierrors "k8s.io/apimachinery/pkg/api/errors"
     9  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    10  	"k8s.io/client-go/rest"
    11  )
    12  
    13  // Safe installs the compose features securely
    14  func Safe(ctx context.Context, config *rest.Config, options SafeOptions) error {
    15  	return Do(ctx, config, WithSafe(options))
    16  }
    17  
    18  func (c *installer) createEtcdSecret(*installerContext) error {
    19  	if c.etcdOptions == nil {
    20  		return nil
    21  	}
    22  	update := true
    23  	secret, err := c.coreClient.Secrets(c.commonOptions.Namespace).Get("compose-etcd", metav1.GetOptions{})
    24  	if apierrors.IsNotFound(err) {
    25  		update = false
    26  	} else if err != nil {
    27  		return err
    28  	}
    29  	if secret == nil {
    30  		secret = &corev1types.Secret{}
    31  	}
    32  	secret.Name = "compose-etcd"
    33  	secret.Labels = c.apiLabels
    34  	if secret.Data == nil {
    35  		secret.Data = map[string][]byte{}
    36  	}
    37  	secret.Data["servers"] = []byte(c.etcdOptions.Servers)
    38  	if c.etcdOptions.ClientTLSBundle != nil {
    39  		secret.Data["ca"] = c.etcdOptions.ClientTLSBundle.ca
    40  		secret.Data["cert"] = c.etcdOptions.ClientTLSBundle.cert
    41  		secret.Data["key"] = c.etcdOptions.ClientTLSBundle.key
    42  	}
    43  	shouldDo, err := c.objectFilter.filter(secret)
    44  	if err != nil {
    45  		return err
    46  	}
    47  	if shouldDo {
    48  		if update {
    49  			_, err := c.coreClient.Secrets(c.commonOptions.Namespace).Update(secret)
    50  			return err
    51  		}
    52  		_, err = c.coreClient.Secrets(c.commonOptions.Namespace).Create(secret)
    53  		return err
    54  	}
    55  	return nil
    56  }
    57  
    58  func (c *installer) createNetworkSecret(_ *installerContext) error {
    59  	if c.networkOptions == nil || c.networkOptions.CustomTLSBundle == nil {
    60  		return nil
    61  	}
    62  	update := true
    63  	secret, err := c.coreClient.Secrets(c.commonOptions.Namespace).Get("compose-tls", metav1.GetOptions{})
    64  	if apierrors.IsNotFound(err) {
    65  		update = false
    66  	} else if err != nil {
    67  		return err
    68  	}
    69  	if secret == nil {
    70  		secret = &corev1types.Secret{}
    71  	}
    72  	secret.Name = "compose-tls"
    73  	secret.Labels = c.apiLabels
    74  	if secret.Data == nil {
    75  		secret.Data = map[string][]byte{}
    76  	}
    77  	secret.Data["ca"] = c.networkOptions.CustomTLSBundle.ca
    78  	secret.Data["cert"] = c.networkOptions.CustomTLSBundle.cert
    79  	secret.Data["key"] = c.networkOptions.CustomTLSBundle.key
    80  
    81  	shouldDo, err := c.objectFilter.filter(secret)
    82  	if err != nil {
    83  		return err
    84  	}
    85  	if shouldDo {
    86  		if update {
    87  			_, err = c.coreClient.Secrets(c.commonOptions.Namespace).Update(secret)
    88  			return err
    89  		}
    90  		_, err = c.coreClient.Secrets(c.commonOptions.Namespace).Create(secret)
    91  		return err
    92  	}
    93  	return nil
    94  }
    95  
    96  func applyEtcdOptions(pod *corev1types.PodSpec, opts *EtcdOptions) {
    97  	if opts == nil {
    98  		// unsafe case
    99  		pod.Containers[0].Args = append(pod.Containers[0].Args, "--etcd-servers=http://127.0.0.1:2379")
   100  		pod.Containers = append(pod.Containers, corev1types.Container{
   101  			Name:            "etcd",
   102  			Image:           "quay.io/coreos/etcd:v3.3.15",
   103  			ImagePullPolicy: corev1types.PullAlways,
   104  			Args: []string{
   105  				"/usr/local/bin/etcd",
   106  				"-advertise-client-urls=http://127.0.0.1:2379",
   107  				"-listen-client-urls=http://127.0.0.1:2379",
   108  			},
   109  		})
   110  		return
   111  	}
   112  	pod.Containers[0].Args = append(pod.Containers[0].Args, "--etcd-servers="+opts.Servers)
   113  	if opts.ClientTLSBundle == nil {
   114  		return
   115  	}
   116  	svs := &corev1types.SecretVolumeSource{
   117  		SecretName: "compose-etcd",
   118  	}
   119  	if opts.ClientTLSBundle.ca != nil {
   120  		svs.Items = append(svs.Items, corev1types.KeyToPath{
   121  			Key:  "ca",
   122  			Path: "ca.crt",
   123  		})
   124  		pod.Containers[0].Args = append(pod.Containers[0].Args, "--etcd-cafile=/etc/docker-compose/etcd/ca.crt")
   125  	}
   126  	if opts.ClientTLSBundle.cert != nil {
   127  		svs.Items = append(svs.Items, corev1types.KeyToPath{
   128  			Key:  "cert",
   129  			Path: "client.crt",
   130  		})
   131  		pod.Containers[0].Args = append(pod.Containers[0].Args, "--etcd-certfile=/etc/docker-compose/etcd/client.crt")
   132  	}
   133  	if opts.ClientTLSBundle.key != nil {
   134  		svs.Items = append(svs.Items, corev1types.KeyToPath{
   135  			Key:  "key",
   136  			Path: "client.key",
   137  		})
   138  		pod.Containers[0].Args = append(pod.Containers[0].Args, "--etcd-keyfile=/etc/docker-compose/etcd/client.key")
   139  	}
   140  	pod.Volumes = append(pod.Volumes, corev1types.Volume{
   141  		Name:         "etcd-secret",
   142  		VolumeSource: corev1types.VolumeSource{Secret: svs},
   143  	})
   144  	pod.Containers[0].VolumeMounts = append(pod.Containers[0].VolumeMounts, corev1types.VolumeMount{
   145  		Name:      "etcd-secret",
   146  		MountPath: "/etc/docker-compose/etcd",
   147  		ReadOnly:  true,
   148  	})
   149  }
   150  
   151  func applyNetworkOptions(pod *corev1types.PodSpec, opts *NetworkOptions) {
   152  	if opts == nil {
   153  		pod.Containers[0].Ports = append(pod.Containers[0].Ports, corev1types.ContainerPort{
   154  			Name:          "api",
   155  			ContainerPort: 9443,
   156  		})
   157  		pod.Containers[0].Args = append(pod.Containers[0].Args, "--secure-port", "9443")
   158  		return
   159  	}
   160  
   161  	if opts.Port == 0 {
   162  		opts.Port = 9443
   163  	}
   164  	if opts.ShouldUseHost {
   165  		pod.HostNetwork = true
   166  	} else {
   167  		pod.Containers[0].Ports = append(pod.Containers[0].Ports, corev1types.ContainerPort{
   168  			Name:          "api",
   169  			ContainerPort: opts.Port,
   170  		})
   171  	}
   172  	pod.Containers[0].Args = append(pod.Containers[0].Args, fmt.Sprintf("--secure-port=%v", opts.Port))
   173  
   174  	if opts.CustomTLSBundle == nil {
   175  		return
   176  	}
   177  	svs := &corev1types.SecretVolumeSource{
   178  		SecretName: "compose-tls",
   179  		Items: []corev1types.KeyToPath{
   180  			{
   181  				Key:  "ca",
   182  				Path: "ca.crt",
   183  			},
   184  			{
   185  				Key:  "cert",
   186  				Path: "server.crt",
   187  			},
   188  			{
   189  				Key:  "key",
   190  				Path: "server.key",
   191  			},
   192  		},
   193  	}
   194  	pod.Volumes = append(pod.Volumes, corev1types.Volume{
   195  		Name:         "tls-secret",
   196  		VolumeSource: corev1types.VolumeSource{Secret: svs},
   197  	})
   198  	pod.Containers[0].VolumeMounts = append(pod.Containers[0].VolumeMounts, corev1types.VolumeMount{
   199  		Name:      "tls-secret",
   200  		MountPath: "/etc/docker-compose/tls",
   201  		ReadOnly:  true,
   202  	})
   203  	pod.Containers[0].Args = append(pod.Containers[0].Args,
   204  		"--tls-cert-file=/etc/docker-compose/tls/server.crt",
   205  		"--tls-private-key-file=/etc/docker-compose/tls/server.key",
   206  		"--ca-bundle-file=/etc/docker-compose/tls/ca.crt",
   207  	)
   208  
   209  }