mirror of https://github.com/docker/compose.git
add uninstall cmd and restructure compose pkg
Signed-off-by: aiordache <anca.iordache@docker.com>
This commit is contained in:
parent
898b7d4666
commit
896b9fd47e
|
@ -1,28 +1,9 @@
|
||||||
package compose
|
package compose
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"log"
|
"os"
|
||||||
|
|
||||||
chartloader "helm.sh/helm/v3/pkg/chart/loader"
|
internal "github.com/docker/helm-prototype/pkg/compose/internal"
|
||||||
|
|
||||||
"github.com/compose-spec/compose-go/loader"
|
|
||||||
"github.com/compose-spec/compose-go/types"
|
|
||||||
"github.com/docker/helm-prototype/pkg/compose/internal/convert"
|
|
||||||
"github.com/docker/helm-prototype/pkg/compose/internal/helm"
|
|
||||||
utils "github.com/docker/helm-prototype/pkg/compose/internal/utils"
|
|
||||||
"helm.sh/helm/v3/pkg/action"
|
|
||||||
env "helm.sh/helm/v3/pkg/cli"
|
|
||||||
k "helm.sh/helm/v3/pkg/kube"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Orchestrator is "kubernetes" or "swarm"
|
|
||||||
type Orchestrator string
|
|
||||||
|
|
||||||
const (
|
|
||||||
// Kubernetes specifies to use kubernetes.
|
|
||||||
Kubernetes Orchestrator = "kubernetes"
|
|
||||||
// Swarm specifies to use Docker swarm.
|
|
||||||
Swarm Orchestrator = "swarm"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type ProjectOptions struct {
|
type ProjectOptions struct {
|
||||||
|
@ -30,107 +11,48 @@ type ProjectOptions struct {
|
||||||
Name string
|
Name string
|
||||||
}
|
}
|
||||||
|
|
||||||
type Project struct {
|
var Settings = internal.GetDefault()
|
||||||
Config *types.Config
|
|
||||||
ProjectDir string
|
|
||||||
Name string `yaml:"-" json:"-"`
|
|
||||||
Orchestrator Orchestrator
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewProject(config types.ConfigDetails, name string) (*Project, error) {
|
type ComposeAPI struct {
|
||||||
model, err := loader.Load(config)
|
project *internal.Project
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
p := Project{
|
|
||||||
Config: model,
|
|
||||||
ProjectDir: config.WorkingDir,
|
|
||||||
Name: name,
|
|
||||||
}
|
|
||||||
return &p, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// projectFromOptions load a compose project based on command line options
|
// projectFromOptions load a compose project based on command line options
|
||||||
func ProjectFromOptions(options *ProjectOptions) (*Project, error) {
|
func ProjectFromOptions(options *ProjectOptions) (*ComposeAPI, error) {
|
||||||
|
if options == nil {
|
||||||
|
options = &ProjectOptions{
|
||||||
|
ConfigPaths: []string{},
|
||||||
|
Name: "docker-compose",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if options.Name == "" {
|
if options.Name == "" {
|
||||||
options.Name = "docker-compose"
|
options.Name = "docker-compose"
|
||||||
}
|
}
|
||||||
|
|
||||||
workingDir, configs, err := utils.GetConfigs(
|
project, err := internal.GetProject(options.Name, options.ConfigPaths)
|
||||||
options.Name,
|
|
||||||
options.ConfigPaths,
|
|
||||||
)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return NewProject(types.ConfigDetails{
|
return &ComposeAPI{project: project}, nil
|
||||||
WorkingDir: workingDir,
|
|
||||||
ConfigFiles: configs,
|
|
||||||
Environment: utils.Environment(),
|
|
||||||
}, options.Name)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Project) GenerateChart(path string) error {
|
func (c *ComposeAPI) GenerateChart(dirname string) error {
|
||||||
objects, err := convert.MapToKubernetesObjects(p.Config, p.Name)
|
return c.project.ExportToCharts(dirname)
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
err = helm.Write(p.Name, objects, path)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Project) InstallChart(n, path string) error {
|
func (c *ComposeAPI) Install(name, path string) error {
|
||||||
|
|
||||||
if path == "" {
|
if path == "" {
|
||||||
err := p.GenerateChart(path)
|
cwd, err := os.Getwd()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
path = cwd
|
||||||
}
|
}
|
||||||
|
return c.project.Install(name, path)
|
||||||
settings := env.New()
|
}
|
||||||
actionConfig := new(action.Configuration)
|
|
||||||
println(".......... here ............")
|
func (c *ComposeAPI) Uninstall(name string) error {
|
||||||
if err := actionConfig.Init(settings.RESTClientGetter(), settings.Namespace(), "memory", nil); err != nil {
|
return c.project.Uninstall(name)
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
println(settings.EnvVars())
|
|
||||||
client := action.NewInstall(actionConfig)
|
|
||||||
println("Original chart version:", client.Version)
|
|
||||||
client.Version = ">0.0.0-0"
|
|
||||||
|
|
||||||
name, chart, err := client.NameAndChart([]string{n, path})
|
|
||||||
if err != nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
client.ReleaseName = name
|
|
||||||
client.Namespace = settings.Namespace()
|
|
||||||
cp, err := client.ChartPathOptions.LocateChart(chart, settings)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
println("CHART PATH: ", cp)
|
|
||||||
|
|
||||||
chartRequested, err := chartloader.Load(cp)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
kclient := k.New(settings.RESTClientGetter())
|
|
||||||
println(kclient.Namespace)
|
|
||||||
if err = actionConfig.KubeClient.IsReachable(); err != nil {
|
|
||||||
println("Kube API is not reachable")
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
println("....Running.....")
|
|
||||||
println("Chart description: ", chartRequested.Metadata.Description)
|
|
||||||
release, err := client.Run(chartRequested, map[string]interface{}{})
|
|
||||||
|
|
||||||
println(release.Name)
|
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,70 @@
|
||||||
|
package helm
|
||||||
|
|
||||||
|
import (
|
||||||
|
"gopkg.in/yaml.v2"
|
||||||
|
action "helm.sh/helm/v3/pkg/action"
|
||||||
|
"helm.sh/helm/v3/pkg/chart"
|
||||||
|
loader "helm.sh/helm/v3/pkg/chart/loader"
|
||||||
|
)
|
||||||
|
|
||||||
|
type HelmChart struct {
|
||||||
|
chart *chart.Chart
|
||||||
|
actionConfig *HelmConfig
|
||||||
|
Path string
|
||||||
|
Name string
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewChart(name, chartpath string) *HelmChart {
|
||||||
|
chart, err := loader.Load(chartpath)
|
||||||
|
if err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return &HelmChart{
|
||||||
|
chart: chart,
|
||||||
|
Path: chartpath,
|
||||||
|
Name: name,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
func (chart *HelmChart) SetActionConfig(config *HelmConfig) error {
|
||||||
|
chart.actionConfig = config
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (chart *HelmChart) Validate() error {
|
||||||
|
_, err := yaml.Marshal(chart.chart.Metadata)
|
||||||
|
if err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (chart *HelmChart) Install() error {
|
||||||
|
err := chart.actionConfig.InitKubeClient()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
actInstall := action.NewInstall(chart.actionConfig.Config)
|
||||||
|
actInstall.ReleaseName = chart.Name
|
||||||
|
actInstall.Namespace = chart.actionConfig.Settings.Namespace()
|
||||||
|
|
||||||
|
release, err := actInstall.Run(chart.chart, map[string]interface{}{})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
println("Release status: ", release.Info.Status)
|
||||||
|
println("Release description: ", release.Info.Description)
|
||||||
|
return chart.actionConfig.Config.Releases.Update(release)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (chart *HelmChart) Uninstall() error {
|
||||||
|
err := chart.actionConfig.InitKubeClient()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
actUninstall := action.NewUninstall(chart.actionConfig.Config)
|
||||||
|
_, err = actUninstall.Run(chart.Name)
|
||||||
|
return err
|
||||||
|
}
|
|
@ -0,0 +1,39 @@
|
||||||
|
package helm
|
||||||
|
|
||||||
|
import (
|
||||||
|
"log"
|
||||||
|
|
||||||
|
action "helm.sh/helm/v3/pkg/action"
|
||||||
|
env "helm.sh/helm/v3/pkg/cli"
|
||||||
|
)
|
||||||
|
|
||||||
|
type HelmConfig struct {
|
||||||
|
Config *action.Configuration
|
||||||
|
Settings *env.EnvSettings
|
||||||
|
kube_conn_init bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewHelmConfig(settings *env.EnvSettings) *HelmConfig {
|
||||||
|
if settings == nil {
|
||||||
|
settings = env.New()
|
||||||
|
}
|
||||||
|
return &HelmConfig{
|
||||||
|
Config: new(action.Configuration),
|
||||||
|
Settings: settings,
|
||||||
|
kube_conn_init: false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (hc *HelmConfig) InitKubeClient() error {
|
||||||
|
if hc.kube_conn_init {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if err := hc.Config.Init(hc.Settings.RESTClientGetter(), hc.Settings.Namespace(), "memory", log.Printf); err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
if err := hc.Config.KubeClient.IsReachable(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
hc.kube_conn_init = true
|
||||||
|
return nil
|
||||||
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
package convert
|
package kube
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
|
@ -1,4 +1,4 @@
|
||||||
package convert
|
package kube
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"regexp"
|
"regexp"
|
|
@ -1,4 +1,4 @@
|
||||||
package convert
|
package kube
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"reflect"
|
"reflect"
|
|
@ -1,4 +1,4 @@
|
||||||
package convert
|
package kube
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
|
@ -1,4 +1,4 @@
|
||||||
package convert
|
package kube
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
|
@ -1,4 +1,4 @@
|
||||||
package convert
|
package kube
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
|
@ -0,0 +1,112 @@
|
||||||
|
package project
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/compose-spec/compose-go/loader"
|
||||||
|
"github.com/compose-spec/compose-go/types"
|
||||||
|
"github.com/docker/helm-prototype/pkg/compose/internal/helm"
|
||||||
|
"github.com/docker/helm-prototype/pkg/compose/internal/utils"
|
||||||
|
|
||||||
|
"github.com/docker/helm-prototype/pkg/compose/internal/kube"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Kind is "kubernetes" or "docker"
|
||||||
|
type Kind string
|
||||||
|
|
||||||
|
const (
|
||||||
|
// Kubernetes specifies to use a kubernetes cluster.
|
||||||
|
Kubernetes Kind = "kubernetes"
|
||||||
|
// Docker specifies to use Docker engine.
|
||||||
|
DockerEngine Kind = "docker"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Engine struct {
|
||||||
|
Namespace string
|
||||||
|
|
||||||
|
Kind Kind
|
||||||
|
|
||||||
|
Config string
|
||||||
|
// Context is the name of the kubeconfig/docker context.
|
||||||
|
Context string
|
||||||
|
// Token used for authentication (kubernetes)
|
||||||
|
Token string
|
||||||
|
// Kubernetes API Server Endpoint for authentication
|
||||||
|
APIServer string
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetDefault() *Engine {
|
||||||
|
return &Engine{Kind: Kubernetes}
|
||||||
|
}
|
||||||
|
|
||||||
|
type Project struct {
|
||||||
|
Config *types.Config
|
||||||
|
HelmConfig *helm.HelmConfig
|
||||||
|
HelmChart *helm.HelmChart
|
||||||
|
ProjectDir string
|
||||||
|
Name string `yaml:"-" json:"-"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewProject(config types.ConfigDetails, name string) (*Project, error) {
|
||||||
|
model, err := loader.Load(config)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
p := Project{
|
||||||
|
Config: model,
|
||||||
|
HelmConfig: helm.NewHelmConfig(nil),
|
||||||
|
HelmChart: nil,
|
||||||
|
ProjectDir: config.WorkingDir,
|
||||||
|
Name: name,
|
||||||
|
}
|
||||||
|
return &p, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetProject(name string, configPaths []string) (*Project, error) {
|
||||||
|
if name == "" {
|
||||||
|
name = "docker-compose"
|
||||||
|
}
|
||||||
|
|
||||||
|
workingDir, configs, err := utils.GetConfigs(
|
||||||
|
name,
|
||||||
|
configPaths,
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return NewProject(types.ConfigDetails{
|
||||||
|
WorkingDir: workingDir,
|
||||||
|
ConfigFiles: configs,
|
||||||
|
Environment: utils.Environment(),
|
||||||
|
}, name)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Project) ExportToCharts(path string) error {
|
||||||
|
objects, err := kube.MapToKubernetesObjects(p.Config, p.Name)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
err = helm.Write(p.Name, objects, path)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Project) Install(name, path string) error {
|
||||||
|
if p.HelmChart == nil {
|
||||||
|
chart := helm.NewChart(name, path)
|
||||||
|
chart.SetActionConfig(p.HelmConfig)
|
||||||
|
p.HelmChart = chart
|
||||||
|
}
|
||||||
|
return p.HelmChart.Install()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Project) Uninstall(name string) error {
|
||||||
|
if p.HelmChart == nil {
|
||||||
|
p.HelmChart = helm.NewChart(name, "")
|
||||||
|
p.HelmChart.SetActionConfig(p.HelmConfig)
|
||||||
|
}
|
||||||
|
return p.HelmChart.Uninstall()
|
||||||
|
}
|
|
@ -20,13 +20,11 @@ func GetConfigs(name string, configPaths []string) (string, []types.ConfigFile,
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", nil, err
|
return "", nil, err
|
||||||
}
|
}
|
||||||
|
workingDir := filepath.Dir(configPath[0])
|
||||||
|
|
||||||
if name == "" {
|
if name == "" {
|
||||||
name = os.Getenv("COMPOSE_PROJECT_NAME")
|
name = os.Getenv("COMPOSE_PROJECT_NAME")
|
||||||
}
|
}
|
||||||
|
|
||||||
workingDir := filepath.Dir(configPath[0])
|
|
||||||
|
|
||||||
if name == "" {
|
if name == "" {
|
||||||
r := regexp.MustCompile(`[^a-z0-9\\-_]+`)
|
r := regexp.MustCompile(`[^a-z0-9\\-_]+`)
|
||||||
name = r.ReplaceAllString(strings.ToLower(filepath.Base(workingDir)), "")
|
name = r.ReplaceAllString(strings.ToLower(filepath.Base(workingDir)), "")
|
||||||
|
|
|
@ -6,15 +6,11 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
func Environment() map[string]string {
|
func Environment() map[string]string {
|
||||||
return getAsEqualsMap(os.Environ())
|
vars := make(map[string]string)
|
||||||
}
|
env := os.Environ()
|
||||||
|
for _, v := range env {
|
||||||
// getAsEqualsMap split key=value formatted strings into a key : value map
|
k := strings.SplitN(v, "=", 2)
|
||||||
func getAsEqualsMap(em []string) map[string]string {
|
vars[k[0]] = k[1]
|
||||||
m := make(map[string]string)
|
|
||||||
for _, v := range em {
|
|
||||||
kv := strings.SplitN(v, "=", 2)
|
|
||||||
m[kv[0]] = kv[1]
|
|
||||||
}
|
}
|
||||||
return m
|
return vars
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue