Просмотр исходного кода

Add progress writer to compose up/down
- remove intermediate compose interface

Signed-off-by: aiordache <[email protected]>

aiordache 4 лет назад
Родитель
Сommit
560014f248

+ 0 - 120
kube/charts/charts.go

@@ -1,120 +0,0 @@
-// +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 charts
-
-import (
-	"context"
-	"path/filepath"
-	"strings"
-
-	"github.com/compose-spec/compose-go/types"
-	"github.com/docker/compose-cli/api/compose"
-	apicontext "github.com/docker/compose-cli/api/context"
-	"github.com/docker/compose-cli/api/context/store"
-	"github.com/docker/compose-cli/kube/charts/helm"
-	"github.com/docker/compose-cli/kube/charts/kubernetes"
-	chart "helm.sh/helm/v3/pkg/chart"
-	util "helm.sh/helm/v3/pkg/chartutil"
-)
-
-//SDK chart SDK
-type SDK struct {
-	action *helm.Actions
-}
-
-// NewSDK new chart SDK
-func NewSDK(ctx context.Context) (SDK, error) {
-	contextStore := store.ContextStore(ctx)
-	currentContext := apicontext.CurrentContext(ctx)
-	var kubeContext store.KubeContext
-
-	if err := contextStore.GetEndpoint(currentContext, &kubeContext); err != nil {
-		return SDK{}, err
-	}
-
-	config, err := kubernetes.LoadConfig(kubeContext)
-	if err != nil {
-		return SDK{}, err
-	}
-
-	actions, err := helm.NewHelmActions(ctx, config)
-	if err != nil {
-		return SDK{}, err
-	}
-	return SDK{
-		action: actions,
-	}, nil
-}
-
-// Install deploys a Compose stack
-func (s SDK) Install(project *types.Project) error {
-	chart, err := s.GetChartInMemory(project)
-	if err != nil {
-		return err
-	}
-	return s.action.InstallChart(project.Name, chart)
-}
-
-// Uninstall removes a runnign compose stack
-func (s SDK) Uninstall(projectName string) error {
-	return s.action.Uninstall(projectName)
-}
-
-// List returns a list of compose stacks
-func (s SDK) List() ([]compose.Stack, error) {
-	return s.action.ListReleases()
-}
-
-// GetChartInMemory get memory representation of helm chart
-func (s SDK) GetChartInMemory(project *types.Project) (*chart.Chart, error) {
-	// replace _ with - in volume names
-	for k, v := range project.Volumes {
-		volumeName := strings.ReplaceAll(k, "_", "-")
-		if volumeName != k {
-			project.Volumes[volumeName] = v
-			delete(project.Volumes, k)
-		}
-	}
-	objects, err := kubernetes.MapToKubernetesObjects(project)
-	if err != nil {
-		return nil, err
-	}
-	//in memory files
-	return helm.ConvertToChart(project.Name, objects)
-}
-
-// SaveChart converts compose project to helm and saves the chart
-func (s SDK) SaveChart(project *types.Project, dest string) error {
-	chart, err := s.GetChartInMemory(project)
-	if err != nil {
-		return err
-	}
-	return util.SaveDir(chart, dest)
-}
-
-// GenerateChart generates helm chart from Compose project
-func (s SDK) GenerateChart(project *types.Project, dirname string) error {
-	if strings.Contains(dirname, ".") {
-		splits := strings.SplitN(dirname, ".", 2)
-		dirname = splits[0]
-	}
-
-	dirname = filepath.Dir(dirname)
-	return s.SaveChart(project, dirname)
-}

+ 66 - 10
kube/compose.go

@@ -20,42 +20,98 @@ package kube
 
 import (
 	"context"
+	"fmt"
+	"strings"
 
 	"github.com/compose-spec/compose-go/types"
 
 	"github.com/docker/compose-cli/api/compose"
+	apicontext "github.com/docker/compose-cli/api/context"
+	"github.com/docker/compose-cli/api/context/store"
 	"github.com/docker/compose-cli/api/errdefs"
-	"github.com/docker/compose-cli/kube/charts"
+	"github.com/docker/compose-cli/api/progress"
+	"github.com/docker/compose-cli/kube/helm"
+	"github.com/docker/compose-cli/kube/resources"
 )
 
+type composeService struct {
+	sdk *helm.Actions
+}
+
 // NewComposeService create a kubernetes implementation of the compose.Service API
 func NewComposeService(ctx context.Context) (compose.Service, error) {
-	chartsAPI, err := charts.NewSDK(ctx)
+	contextStore := store.ContextStore(ctx)
+	currentContext := apicontext.CurrentContext(ctx)
+	var kubeContext store.KubeContext
+
+	if err := contextStore.GetEndpoint(currentContext, &kubeContext); err != nil {
+		return nil, err
+	}
+	config, err := resources.LoadConfig(kubeContext)
+	if err != nil {
+		return nil, err
+	}
+	actions, err := helm.NewActions(config)
 	if err != nil {
 		return nil, err
 	}
 	return &composeService{
-		sdk: chartsAPI,
+		sdk: actions,
 	}, nil
 }
 
-type composeService struct {
-	sdk charts.SDK
-}
-
 // Up executes the equivalent to a `compose up`
 func (s *composeService) Up(ctx context.Context, project *types.Project, options compose.UpOptions) error {
-	return s.sdk.Install(project)
+	w := progress.ContextWriter(ctx)
+
+	eventName := "Convert to Helm charts"
+	w.Event(progress.CreatingEvent(eventName))
+
+	chart, err := helm.GetChartInMemory(project)
+	if err != nil {
+		return err
+	}
+	w.Event(progress.NewEvent(eventName, progress.Done, ""))
+
+	eventName = "Install Helm charts"
+	w.Event(progress.CreatingEvent(eventName))
+
+	err = s.sdk.InstallChart(project.Name, chart, func(format string, v ...interface{}) {
+		message := fmt.Sprintf(format, v...)
+		w.Event(progress.NewEvent(eventName, progress.Done, message))
+	})
+
+	w.Event(progress.NewEvent(eventName, progress.Done, ""))
+	return err
 }
 
 // Down executes the equivalent to a `compose down`
 func (s *composeService) Down(ctx context.Context, projectName string, options compose.DownOptions) error {
-	return s.sdk.Uninstall(projectName)
+	w := progress.ContextWriter(ctx)
+
+	eventName := fmt.Sprintf("Remove %s", projectName)
+	w.Event(progress.CreatingEvent(eventName))
+
+	logger := func(format string, v ...interface{}) {
+		message := fmt.Sprintf(format, v...)
+		if strings.Contains(message, "Starting delete") {
+			action := strings.Replace(message, "Starting delete for", "Delete", 1)
+
+			w.Event(progress.CreatingEvent(action))
+			w.Event(progress.NewEvent(action, progress.Done, ""))
+			return
+		}
+		w.Event(progress.NewEvent(eventName, progress.Working, message))
+	}
+	err := s.sdk.Uninstall(projectName, logger)
+	w.Event(progress.NewEvent(eventName, progress.Done, ""))
+
+	return err
 }
 
 // List executes the equivalent to a `docker stack ls`
 func (s *composeService) List(ctx context.Context) ([]compose.Stack, error) {
-	return s.sdk.List()
+	return s.sdk.ListReleases()
 }
 
 // Build executes the equivalent to a `compose build`

+ 2 - 2
kube/context.go

@@ -26,7 +26,7 @@ import (
 	"github.com/docker/compose-cli/api/errdefs"
 	"github.com/docker/compose-cli/utils/prompt"
 
-	"github.com/docker/compose-cli/kube/charts/kubernetes"
+	"github.com/docker/compose-cli/kube/resources"
 )
 
 // ContextParams options for creating a Kubernetes context
@@ -47,7 +47,7 @@ func (cp ContextParams) CreateContextData() (interface{}, string, error) {
 	}
 	user := prompt.User{}
 	selectContext := func() error {
-		contexts, err := kubernetes.ListAvailableKubeConfigContexts(cp.KubeConfigPath)
+		contexts, err := resources.ListAvailableKubeConfigContexts(cp.KubeConfigPath)
 		if err != nil {
 			return err
 		}

+ 42 - 0
kube/charts/helm/chart.go → kube/helm/chart.go

@@ -23,11 +23,15 @@ import (
 	"encoding/json"
 	"html/template"
 	"path/filepath"
+	"strings"
 
+	"github.com/compose-spec/compose-go/types"
+	"github.com/docker/compose-cli/kube/resources"
 	"gopkg.in/yaml.v3"
 
 	chart "helm.sh/helm/v3/pkg/chart"
 	loader "helm.sh/helm/v3/pkg/chart/loader"
+	util "helm.sh/helm/v3/pkg/chartutil"
 	"k8s.io/apimachinery/pkg/runtime"
 )
 
@@ -107,3 +111,41 @@ func jsonToYaml(j []byte, spaces int) ([]byte, error) {
 	}
 	return b.Bytes(), nil
 }
+
+// GetChartInMemory get memory representation of helm chart
+func GetChartInMemory(project *types.Project) (*chart.Chart, error) {
+	// replace _ with - in volume names
+	for k, v := range project.Volumes {
+		volumeName := strings.ReplaceAll(k, "_", "-")
+		if volumeName != k {
+			project.Volumes[volumeName] = v
+			delete(project.Volumes, k)
+		}
+	}
+	objects, err := resources.MapToKubernetesObjects(project)
+	if err != nil {
+		return nil, err
+	}
+	//in memory files
+	return ConvertToChart(project.Name, objects)
+}
+
+// SaveChart converts compose project to helm and saves the chart
+func SaveChart(project *types.Project, dest string) error {
+	chart, err := GetChartInMemory(project)
+	if err != nil {
+		return err
+	}
+	return util.SaveDir(chart, dest)
+}
+
+// GenerateChart generates helm chart from Compose project
+func GenerateChart(project *types.Project, dirname string) error {
+	if strings.Contains(dirname, ".") {
+		splits := strings.SplitN(dirname, ".", 2)
+		dirname = splits[0]
+	}
+
+	dirname = filepath.Dir(dirname)
+	return SaveChart(project, dirname)
+}

+ 31 - 35
kube/charts/helm/helm.go → kube/helm/helm.go

@@ -19,27 +19,25 @@
 package helm
 
 import (
-	"context"
 	"errors"
-	"log"
 
 	"github.com/docker/compose-cli/api/compose"
-	action "helm.sh/helm/v3/pkg/action"
-	chart "helm.sh/helm/v3/pkg/chart"
-	loader "helm.sh/helm/v3/pkg/chart/loader"
+	"helm.sh/helm/v3/pkg/action"
+	"helm.sh/helm/v3/pkg/chart"
 	env "helm.sh/helm/v3/pkg/cli"
 	"helm.sh/helm/v3/pkg/release"
 	"k8s.io/cli-runtime/pkg/genericclioptions"
 )
 
-// Actions helm actions
+// Actions implements charts installation management
 type Actions struct {
-	Config    *action.Configuration
-	Namespace string
+	Config     *action.Configuration
+	Namespace  string
+	initialize func(f func(format string, v ...interface{})) error
 }
 
-// NewHelmActions new helm action
-func NewHelmActions(ctx context.Context, getter genericclioptions.RESTClientGetter) (*Actions, error) {
+// NewActions new helm action
+func NewActions(getter genericclioptions.RESTClientGetter) (*Actions, error) {
 	if getter == nil {
 		settings := env.New()
 		getter = settings.RESTClientGetter()
@@ -55,40 +53,38 @@ func NewHelmActions(ctx context.Context, getter genericclioptions.RESTClientGett
 		},
 		Namespace: namespace,
 	}
-	err := actions.Config.Init(getter, namespace, "configmap", log.Printf)
-	if err != nil {
-		return nil, err
-	}
 
-	return actions, actions.Config.KubeClient.IsReachable()
+	actions.initialize = func(f func(format string, v ...interface{})) error {
+		err := actions.Config.Init(getter, namespace, "configmap", f)
+		if err != nil {
+			return err
+		}
+		return actions.Config.KubeClient.IsReachable()
+	}
+	return actions, nil
 }
 
-//InstallChartFromDir install from dir
-func (hc *Actions) InstallChartFromDir(name string, chartpath string) error {
-	chart, err := loader.Load(chartpath)
+// InstallChart installs chart
+func (hc *Actions) InstallChart(name string, chart *chart.Chart, logger func(format string, v ...interface{})) error {
+	err := hc.initialize(logger)
 	if err != nil {
 		return err
 	}
-	return hc.InstallChart(name, chart)
-}
 
-// InstallChart instal chart
-func (hc *Actions) InstallChart(name string, chart *chart.Chart) error {
 	actInstall := action.NewInstall(hc.Config)
 	actInstall.ReleaseName = name
 	actInstall.Namespace = hc.Namespace
+	_, err = actInstall.Run(chart, map[string]interface{}{})
+	return err
+}
 
-	release, err := actInstall.Run(chart, map[string]interface{}{})
+// Uninstall uninstall chart
+func (hc *Actions) Uninstall(name string, logger func(format string, v ...interface{})) error {
+	err := hc.initialize(logger)
 	if err != nil {
 		return err
 	}
-	log.Println("Release status: ", release.Info.Status)
-	log.Println(release.Info.Description)
-	return nil
-}
 
-// Uninstall uninstall chart
-func (hc *Actions) Uninstall(name string) error {
 	release, err := hc.Get(name)
 	if err != nil {
 		return err
@@ -97,12 +93,8 @@ func (hc *Actions) Uninstall(name string) error {
 		return errors.New("no release found with the name provided")
 	}
 	actUninstall := action.NewUninstall(hc.Config)
-	response, err := actUninstall.Run(name)
-	if err != nil {
-		return err
-	}
-	log.Println(response.Release.Info.Description)
-	return nil
+	_, err = actUninstall.Run(name)
+	return err
 }
 
 // Get get released object for a named chart
@@ -113,6 +105,10 @@ func (hc *Actions) Get(name string) (*release.Release, error) {
 
 // ListReleases lists chart releases
 func (hc *Actions) ListReleases() ([]compose.Stack, error) {
+	err := hc.initialize(nil)
+	if err != nil {
+		return nil, err
+	}
 	actList := action.NewList(hc.Config)
 	releases, err := actList.Run()
 	if err != nil {

+ 1 - 1
kube/charts/kubernetes/context.go → kube/resources/context.go

@@ -16,7 +16,7 @@
    limitations under the License.
 */
 
-package kubernetes
+package resources
 
 import (
 	"fmt"

+ 1 - 1
kube/charts/kubernetes/kube.go → kube/resources/kube.go

@@ -16,7 +16,7 @@
    limitations under the License.
 */
 
-package kubernetes
+package resources
 
 import (
 	"fmt"

+ 1 - 1
kube/charts/kubernetes/kube_test.go → kube/resources/kube_test.go

@@ -16,7 +16,7 @@
    limitations under the License.
 */
 
-package kubernetes
+package resources
 
 import (
 	"testing"

+ 1 - 1
kube/charts/kubernetes/placement.go → kube/resources/placement.go

@@ -16,7 +16,7 @@
    limitations under the License.
 */
 
-package kubernetes
+package resources
 
 import (
 	"regexp"

+ 1 - 1
kube/charts/kubernetes/placement_test.go → kube/resources/placement_test.go

@@ -16,7 +16,7 @@
    limitations under the License.
 */
 
-package kubernetes
+package resources
 
 import (
 	"reflect"

+ 1 - 1
kube/charts/kubernetes/pod.go → kube/resources/pod.go

@@ -16,7 +16,7 @@
    limitations under the License.
 */
 
-package kubernetes
+package resources
 
 import (
 	"fmt"

+ 1 - 1
kube/charts/kubernetes/pod_test.go → kube/resources/pod_test.go

@@ -16,7 +16,7 @@
    limitations under the License.
 */
 
-package kubernetes
+package resources
 
 import (
 	"fmt"

+ 1 - 1
kube/charts/kubernetes/volumes.go → kube/resources/volumes.go

@@ -16,7 +16,7 @@
    limitations under the License.
 */
 
-package kubernetes
+package resources
 
 import (
 	"fmt"