Add secret support

Signed-off-by: aiordache <anca.iordache@docker.com>
This commit is contained in:
aiordache 2021-02-08 15:16:32 +01:00
parent 05c4caef95
commit d10600041d
6 changed files with 134 additions and 51 deletions

View File

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

View File

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

View File

@ -178,8 +178,8 @@ func (s *composeService) Convert(ctx context.Context, project *types.Project, op
}
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{}

View File

@ -42,6 +42,17 @@ const (
func MapToKubernetesObjects(project *types.Project) (map[string]runtime.Object, error) {
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 {
svcObject := mapToService(project, service)
if svcObject != nil {

58
kube/resources/secrets.go Normal file
View File

@ -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
}

View File

@ -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))
subPath := name
readOnly := true
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 {
return &apiv1.VolumeSource{
Secret: &apiv1.SecretVolumeSource{
SecretName: config.Source,
SecretName: topLevelConfig.Name,
Items: []apiv1.KeyToPath{
{
Key: toKey(topLevelConfig.File),