浏览代码

Add secret support

Signed-off-by: aiordache <[email protected]>
aiordache 4 年之前
父节点
当前提交
d10600041d
共有 6 个文件被更改,包括 125 次插入42 次删除
  1. 1 1
      cli/cmd/compose/convert.go
  2. 40 33
      kube/client/client.go
  3. 2 2
      kube/compose.go
  4. 11 0
      kube/resources/kube.go
  5. 58 0
      kube/resources/secrets.go
  6. 13 6
      kube/resources/volumes.go

+ 1 - 1
cli/cmd/compose/convert.go

@@ -116,7 +116,7 @@ func runConvert(ctx context.Context, opts convertOptions, services []string) err
 	}
 	}
 
 
 	var out io.Writer = os.Stdout
 	var out io.Writer = os.Stdout
-	if opts.Output != "" {
+	if opts.Output != "" && len(json) > 0 {
 		file, err := os.Create(opts.Output)
 		file, err := os.Create(opts.Output)
 		if err != nil {
 		if err != nil {
 			return err
 			return err

+ 40 - 33
kube/client/client.go

@@ -117,15 +117,13 @@ func (kc *KubeClient) GetLogs(ctx context.Context, projectName string, consumer
 
 
 // WaitForRunningPodState blocks until pods are in running state
 // WaitForRunningPodState blocks until pods are in running state
 func (kc KubeClient) WaitForPodState(ctx context.Context, projectName string, services []string, status string, timeout int) error {
 func (kc KubeClient) WaitForPodState(ctx context.Context, projectName string, services []string, status string, timeout int) error {
+	var t time.Duration = 60
 
 
 	if timeout > 0 {
 	if timeout > 0 {
-		var t time.Duration
 		t = time.Duration(timeout) * time.Second
 		t = time.Duration(timeout) * time.Second
-		fmt.Println("Timeout ", t)
 	}
 	}
 
 
 	selector := fmt.Sprintf("%s=%s", compose.ProjectTag, projectName)
 	selector := fmt.Sprintf("%s=%s", compose.ProjectTag, projectName)
-
 	waitingForPhase := corev1.PodRunning
 	waitingForPhase := corev1.PodRunning
 
 
 	switch status {
 	switch status {
@@ -135,49 +133,58 @@ func (kc KubeClient) WaitForPodState(ctx context.Context, projectName string, se
 		waitingForPhase = corev1.PodUnknown
 		waitingForPhase = corev1.PodUnknown
 	}
 	}
 
 
-	//fieldSelector := "status.phase=Running"
-	for {
-		time.Sleep(time.Duration(1) * time.Second)
-		timeout = timeout - 1
-		if timeout <= 0 {
-			return fmt.Errorf("Deployment time out. Pods did not reach expected state.")
-		}
+	errch := make(chan error, 1)
+	done := make(chan bool)
 
 
-		pods, err := kc.client.CoreV1().Pods(kc.namespace).List(ctx, metav1.ListOptions{
-			LabelSelector: selector,
-		})
-		if err != nil {
-			return err
-		}
+	go func() {
+		for {
+			time.Sleep(500 * time.Millisecond)
 
 
-		servicePods := 0
-		stateReached := true
-		for _, pod := range pods.Items {
+			pods, err := kc.client.CoreV1().Pods(kc.namespace).List(ctx, metav1.ListOptions{
+				LabelSelector: selector,
+			})
+			if err != nil {
+				errch <- err
+			}
 
 
-			if status == compose.REMOVING {
-				if contains(services, pod.Labels[compose.ServiceTag]) {
-					servicePods = servicePods + 1
+			servicePods := 0
+			stateReached := true
+			for _, pod := range pods.Items {
+
+				if status == compose.REMOVING {
+					if contains(services, pod.Labels[compose.ServiceTag]) {
+						servicePods = servicePods + 1
+					}
+					continue
 				}
 				}
 
 
-				continue
-			}
+				if pod.Status.Phase != waitingForPhase {
+					stateReached = false
 
 
-			if pod.Status.Phase != waitingForPhase {
-				stateReached = false
+				}
+			}
 
 
+			if status == compose.REMOVING {
+				if servicePods > 0 {
+					stateReached = false
+				}
 			}
 			}
-		}
 
 
-		if status == compose.REMOVING {
-			if len(pods.Items) > 0 {
-				continue
+			if stateReached {
+				done <- true
 			}
 			}
-			return nil
 		}
 		}
+	}()
 
 
-		if !stateReached {
-			continue
+	select {
+	case <-time.After(t):
+		return fmt.Errorf("timeout: pods did not reach expected state.")
+	case err := <-errch:
+		if err != nil {
+			return err
 		}
 		}
+	case <-done:
 		return nil
 		return nil
 	}
 	}
+	return nil
 }
 }

+ 2 - 2
kube/compose.go

@@ -178,8 +178,8 @@ func (s *composeService) Convert(ctx context.Context, project *types.Project, op
 	}
 	}
 
 
 	if options.Output != "" {
 	if options.Output != "" {
-		fullpath, err := helm.SaveChart(chart, options.Output)
-		return []byte(fullpath), err
+		_, err := helm.SaveChart(chart, options.Output)
+		return nil, err
 	}
 	}
 
 
 	buff := []byte{}
 	buff := []byte{}

+ 11 - 0
kube/resources/kube.go

@@ -42,6 +42,17 @@ const (
 func MapToKubernetesObjects(project *types.Project) (map[string]runtime.Object, error) {
 func MapToKubernetesObjects(project *types.Project) (map[string]runtime.Object, error) {
 	objects := map[string]runtime.Object{}
 	objects := map[string]runtime.Object{}
 
 
+	secrets, err := toSecretSpecs(project)
+	if err != nil {
+		return nil, err
+	}
+	if len(secrets) > 0 {
+		for _, secret := range secrets {
+			name := secret.Name[len(project.Name)+1:]
+			objects[fmt.Sprintf("%s-secret.yaml", name)] = &secret
+		}
+	}
+
 	for _, service := range project.Services {
 	for _, service := range project.Services {
 		svcObject := mapToService(project, service)
 		svcObject := mapToService(project, service)
 		if svcObject != nil {
 		if svcObject != nil {

+ 58 - 0
kube/resources/secrets.go

@@ -0,0 +1,58 @@
+// +build kube
+
+/*
+   Copyright 2020 Docker Compose CLI authors
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+*/
+
+package resources
+
+import (
+	"io/ioutil"
+	"strings"
+
+	"github.com/compose-spec/compose-go/types"
+
+	corev1 "k8s.io/api/core/v1"
+)
+
+func toSecretSpecs(project *types.Project) ([]corev1.Secret, error) {
+	var secrets []corev1.Secret
+
+	for _, s := range project.Secrets {
+		if s.External.External {
+			continue
+		}
+		name := strings.ReplaceAll(s.Name, "_", "-")
+		// load secret file content
+		sensitiveData, err := ioutil.ReadFile(s.File)
+		if err != nil {
+			return nil, err
+		}
+
+		readOnly := true
+		secret := corev1.Secret{}
+		secret.SetGroupVersionKind(corev1.SchemeGroupVersion.WithKind("Secret"))
+		secret.Name = name
+		secret.Type = "compose"
+		secret.Data = map[string][]byte{
+			name: sensitiveData,
+		}
+		secret.Immutable = &readOnly
+
+		secrets = append(secrets, secret)
+	}
+
+	return secrets, nil
+}

+ 13 - 6
kube/resources/volumes.go

@@ -84,16 +84,23 @@ func toVolumeSpecs(project *types.Project, s types.ServiceConfig) ([]volumeSpec,
 		})
 		})
 	}
 	}
 
 
-	for i, s := range s.Secrets {
-		name := fmt.Sprintf("secret-%d", i)
+	for _, s := range s.Secrets {
+		name := fmt.Sprintf("%s-%s", project.Name, s.Source)
 
 
 		target := path.Join("/run/secrets", or(s.Target, s.Source))
 		target := path.Join("/run/secrets", or(s.Target, s.Source))
-		subPath := name
 		readOnly := true
 		readOnly := true
 
 
 		specs = append(specs, volumeSpec{
 		specs = append(specs, volumeSpec{
-			source: secretVolume(s, project.Secrets[name], subPath),
-			mount:  volumeMount(name, target, readOnly, subPath),
+			source: &apiv1.VolumeSource{
+				Secret: &apiv1.SecretVolumeSource{
+					SecretName: name,
+				},
+			},
+			mount: apiv1.VolumeMount{
+				Name:      name,
+				MountPath: target,
+				ReadOnly:  readOnly,
+			},
 		})
 		})
 	}
 	}
 
 
@@ -181,7 +188,7 @@ func defaultMode(mode *uint32) *int32 {
 func secretVolume(config types.ServiceSecretConfig, topLevelConfig types.SecretConfig, subPath string) *apiv1.VolumeSource {
 func secretVolume(config types.ServiceSecretConfig, topLevelConfig types.SecretConfig, subPath string) *apiv1.VolumeSource {
 	return &apiv1.VolumeSource{
 	return &apiv1.VolumeSource{
 		Secret: &apiv1.SecretVolumeSource{
 		Secret: &apiv1.SecretVolumeSource{
-			SecretName: config.Source,
+			SecretName: topLevelConfig.Name,
 			Items: []apiv1.KeyToPath{
 			Items: []apiv1.KeyToPath{
 				{
 				{
 					Key:  toKey(topLevelConfig.File),
 					Key:  toKey(topLevelConfig.File),