mirror of https://github.com/docker/compose.git
Merge pull request #1189 from aiordache/kube_compose_up
Kube backend: Target the cluster referenced by the docker context
This commit is contained in:
commit
166db3fa4d
1
go.mod
1
go.mod
|
@ -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
|
||||
)
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue