Merge pull request #1189 from aiordache/kube_compose_up

Kube backend: Target the cluster referenced by the docker context
This commit is contained in:
Guillaume Tardif 2021-01-29 15:49:53 +01:00 committed by GitHub
commit 166db3fa4d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 101 additions and 91 deletions

1
go.mod
View File

@ -64,6 +64,7 @@ require (
helm.sh/helm/v3 v3.5.0
k8s.io/api v0.20.1
k8s.io/apimachinery v0.20.1
k8s.io/cli-runtime v0.20.1
k8s.io/client-go v0.20.1
sigs.k8s.io/kustomize/kyaml v0.10.5
)

View File

@ -25,7 +25,6 @@ import (
"github.com/docker/compose-cli/api/cloud"
"github.com/docker/compose-cli/api/compose"
"github.com/docker/compose-cli/api/containers"
apicontext "github.com/docker/compose-cli/api/context"
"github.com/docker/compose-cli/api/context/store"
"github.com/docker/compose-cli/api/resources"
"github.com/docker/compose-cli/api/secrets"
@ -35,7 +34,6 @@ import (
const backendType = store.KubeContextType
type kubeAPIService struct {
ctx store.KubeContext
composeService compose.Service
}
@ -44,20 +42,11 @@ func init() {
}
func service(ctx context.Context) (backend.Service, error) {
contextStore := store.ContextStore(ctx)
currentContext := apicontext.CurrentContext(ctx)
var kubeContext store.KubeContext
if err := contextStore.GetEndpoint(currentContext, &kubeContext); err != nil {
return nil, err
}
s, err := NewComposeService(kubeContext)
s, err := NewComposeService(ctx)
if err != nil {
return nil, err
}
return &kubeAPIService{
ctx: kubeContext,
composeService: s,
}, nil
}

View File

@ -19,31 +19,46 @@
package charts
import (
"os"
"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"
helmenv "helm.sh/helm/v3/pkg/cli"
)
//SDK chart SDK
type SDK struct {
h *helm.Actions
environment map[string]string
action *helm.Actions
}
// NewSDK new chart SDK
func NewSDK(ctx store.KubeContext) (SDK, error) {
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{
environment: environment(),
h: helm.NewHelmActions(nil),
action: actions,
}, nil
}
@ -53,22 +68,17 @@ func (s SDK) Install(project *types.Project) error {
if err != nil {
return err
}
return s.h.InstallChart(project.Name, chart)
return s.action.InstallChart(project.Name, chart)
}
// Uninstall removes a runnign compose stack
func (s SDK) Uninstall(projectName string) error {
return s.h.Uninstall(projectName)
return s.action.Uninstall(projectName)
}
// List returns a list of compose stacks
func (s SDK) List() ([]compose.Stack, error) {
return s.h.ListReleases()
}
// GetDefaultEnv initializes Helm EnvSettings
func (s SDK) GetDefaultEnv() *helmenv.EnvSettings {
return helmenv.New()
return s.action.ListReleases()
}
// GetChartInMemory get memory representation of helm chart
@ -108,13 +118,3 @@ func (s SDK) GenerateChart(project *types.Project, dirname string) error {
dirname = filepath.Dir(dirname)
return s.SaveChart(project, dirname)
}
func environment() map[string]string {
vars := make(map[string]string)
env := os.Environ()
for _, v := range env {
k := strings.SplitN(v, "=", 2)
vars[k[0]] = k[1]
}
return vars
}

View File

@ -19,6 +19,7 @@
package helm
import (
"context"
"errors"
"log"
@ -28,44 +29,38 @@ import (
loader "helm.sh/helm/v3/pkg/chart/loader"
env "helm.sh/helm/v3/pkg/cli"
"helm.sh/helm/v3/pkg/release"
"k8s.io/cli-runtime/pkg/genericclioptions"
)
// Actions helm actions
type Actions struct {
Config *action.Configuration
Settings *env.EnvSettings
kubeConnInit bool
Config *action.Configuration
Namespace string
}
// NewHelmActions new helm action
func NewHelmActions(settings *env.EnvSettings) *Actions {
if settings == nil {
settings = env.New()
func NewHelmActions(ctx context.Context, getter genericclioptions.RESTClientGetter) (*Actions, error) {
if getter == nil {
settings := env.New()
getter = settings.RESTClientGetter()
}
return &Actions{
Config: new(action.Configuration),
Settings: settings,
kubeConnInit: false,
}
}
func (hc *Actions) initKubeClient() error {
if hc.kubeConnInit {
return nil
namespace := "default"
if ns, _, err := getter.ToRawKubeConfigLoader().Namespace(); err == nil {
namespace = ns
}
if err := hc.Config.Init(
hc.Settings.RESTClientGetter(),
hc.Settings.Namespace(),
"configmap",
log.Printf,
); err != nil {
log.Fatal(err)
actions := &Actions{
Config: &action.Configuration{
RESTClientGetter: getter,
},
Namespace: namespace,
}
if err := hc.Config.KubeClient.IsReachable(); err != nil {
return err
err := actions.Config.Init(getter, namespace, "configmap", log.Printf)
if err != nil {
return nil, err
}
hc.kubeConnInit = true
return nil
return actions, actions.Config.KubeClient.IsReachable()
}
//InstallChartFromDir install from dir
@ -79,14 +74,9 @@ func (hc *Actions) InstallChartFromDir(name string, chartpath string) error {
// InstallChart instal chart
func (hc *Actions) InstallChart(name string, chart *chart.Chart) error {
err := hc.initKubeClient()
if err != nil {
return err
}
actInstall := action.NewInstall(hc.Config)
actInstall.ReleaseName = name
actInstall.Namespace = hc.Settings.Namespace()
actInstall.Namespace = hc.Namespace
release, err := actInstall.Run(chart, map[string]interface{}{})
if err != nil {
@ -99,11 +89,6 @@ func (hc *Actions) InstallChart(name string, chart *chart.Chart) error {
// Uninstall uninstall chart
func (hc *Actions) Uninstall(name string) error {
err := hc.initKubeClient()
if err != nil {
return err
}
release, err := hc.Get(name)
if err != nil {
return err
@ -122,20 +107,12 @@ func (hc *Actions) Uninstall(name string) error {
// Get get released object for a named chart
func (hc *Actions) Get(name string) (*release.Release, error) {
err := hc.initKubeClient()
if err != nil {
return nil, err
}
actGet := action.NewGet(hc.Config)
return actGet.Run(name)
}
// ListReleases lists chart releases
func (hc *Actions) ListReleases() ([]compose.Stack, error) {
err := hc.initKubeClient()
if err != nil {
return nil, err
}
actList := action.NewList(hc.Config)
releases, err := actList.Run()
if err != nil {

View File

@ -22,11 +22,61 @@ import (
"fmt"
"os"
"github.com/docker/compose-cli/api/context/store"
"k8s.io/cli-runtime/pkg/genericclioptions"
"k8s.io/client-go/tools/clientcmd"
"k8s.io/client-go/tools/clientcmd/api"
)
// ListAvailableKubeConfigContexts list kube contexts
func ListAvailableKubeConfigContexts(kubeconfig string) ([]string, error) {
config, err := getKubeConfig(kubeconfig)
if err != nil {
return nil, err
}
contexts := []string{}
for k := range config.Contexts {
contexts = append(contexts, k)
}
return contexts, nil
}
// LoadConfig returns kubeconfig data referenced in the docker context
func LoadConfig(ctx store.KubeContext) (*genericclioptions.ConfigFlags, error) {
if ctx.FromEnvironment {
return nil, nil
}
config, err := getKubeConfig(ctx.KubeconfigPath)
if err != nil {
return nil, err
}
contextName := ctx.ContextName
if contextName == "" {
contextName = config.CurrentContext
}
context, ok := config.Contexts[contextName]
if !ok {
return nil, fmt.Errorf("context name %s not found in kubeconfig", contextName)
}
cluster, ok := config.Clusters[context.Cluster]
if !ok {
return nil, fmt.Errorf("cluster %s not found for context %s", context.Cluster, contextName)
}
// bind to kubernetes config flags
return &genericclioptions.ConfigFlags{
Context: &ctx.ContextName,
KubeConfig: &ctx.KubeconfigPath,
Namespace: &context.Namespace,
ClusterName: &context.Cluster,
APIServer: &cluster.Server,
CAFile: &cluster.CertificateAuthority,
}, nil
}
func getKubeConfig(kubeconfig string) (*api.Config, error) {
config, err := clientcmd.NewDefaultPathOptions().GetStartingConfig()
if err != nil {
return nil, err
@ -43,9 +93,5 @@ func ListAvailableKubeConfigContexts(kubeconfig string) ([]string, error) {
config = clientcmd.GetConfigFromFileOrDie(kubeconfig)
}
contexts := []string{}
for k := range config.Contexts {
contexts = append(contexts, k)
}
return contexts, nil
return config, nil
}

View File

@ -24,25 +24,22 @@ import (
"github.com/compose-spec/compose-go/types"
"github.com/docker/compose-cli/api/compose"
"github.com/docker/compose-cli/api/context/store"
"github.com/docker/compose-cli/api/errdefs"
"github.com/docker/compose-cli/kube/charts"
)
// NewComposeService create a kubernetes implementation of the compose.Service API
func NewComposeService(ctx store.KubeContext) (compose.Service, error) {
func NewComposeService(ctx context.Context) (compose.Service, error) {
chartsAPI, err := charts.NewSDK(ctx)
if err != nil {
return nil, err
}
return &composeService{
ctx: ctx,
sdk: chartsAPI,
}, nil
}
type composeService struct {
ctx store.KubeContext
sdk charts.SDK
}