diff --git a/api/compose/api.go b/api/compose/api.go index f73ead38c..f3e32bf4b 100644 --- a/api/compose/api.go +++ b/api/compose/api.go @@ -81,6 +81,8 @@ type DownOptions struct { type ConvertOptions struct { // Format define the output format used to dump converted application model (json|yaml) Format string + // Output defines the path to save the application model + Output string } // KillOptions group options of the Kill API diff --git a/cli/cmd/compose/convert.go b/cli/cmd/compose/convert.go index 16800d762..e72bea816 100644 --- a/cli/cmd/compose/convert.go +++ b/cli/cmd/compose/convert.go @@ -30,8 +30,11 @@ import ( type convertOptions struct { *projectOptions Format string + Output string } +var addFlagsFuncs []func(cmd *cobra.Command, opts *convertOptions) + func convertCommand(p *projectOptions) *cobra.Command { opts := convertOptions{ projectOptions: p, @@ -47,6 +50,10 @@ func convertCommand(p *projectOptions) *cobra.Command { flags := convertCmd.Flags() flags.StringVar(&opts.Format, "format", "yaml", "Format the output. Values: [yaml | json]") + // add flags for hidden backends + for _, f := range addFlagsFuncs { + f(convertCmd, &opts) + } return convertCmd } @@ -64,11 +71,14 @@ func runConvert(ctx context.Context, opts convertOptions, services []string) err json, err = c.ComposeService().Convert(ctx, project, compose.ConvertOptions{ Format: opts.Format, + Output: opts.Output, }) if err != nil { return err } - + if opts.Output != "" { + fmt.Print("model saved to ") + } fmt.Println(string(json)) return nil } diff --git a/cli/cmd/compose/convert_kube.go b/cli/cmd/compose/convert_kube.go new file mode 100644 index 000000000..776800321 --- /dev/null +++ b/cli/cmd/compose/convert_kube.go @@ -0,0 +1,31 @@ +// +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 compose + +import ( + "github.com/spf13/cobra" +) + +func init() { + addFlagsFuncs = append(addFlagsFuncs, func(cmd *cobra.Command, opts *convertOptions) { + flags := cmd.Flags() + flags.StringVar(&opts.Output, "output", "", "Save to directory") + }) + +} diff --git a/kube/compose.go b/kube/compose.go index 8ea6e8455..1dd5ffd0e 100644 --- a/kube/compose.go +++ b/kube/compose.go @@ -164,10 +164,17 @@ func (s *composeService) Ps(ctx context.Context, projectName string, options com // Convert translate compose model into backend's native format func (s *composeService) Convert(ctx context.Context, project *types.Project, options compose.ConvertOptions) ([]byte, error) { + chart, err := helm.GetChartInMemory(project) if err != nil { return nil, err } + + if options.Output != "" { + fullpath, err := helm.SaveChart(chart, options.Output) + return []byte(fullpath), err + } + buff := []byte{} for _, f := range chart.Raw { header := "\n" + f.Name + "\n" + strings.Repeat("-", len(f.Name)) + "\n" diff --git a/kube/helm/chart.go b/kube/helm/chart.go index 912de9880..52a4362dc 100644 --- a/kube/helm/chart.go +++ b/kube/helm/chart.go @@ -22,16 +22,17 @@ import ( "bytes" "encoding/json" "html/template" + "os" "path/filepath" "strings" "github.com/compose-spec/compose-go/types" "github.com/docker/compose-cli/kube/resources" + "github.com/pkg/errors" "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" ) @@ -130,22 +131,38 @@ func GetChartInMemory(project *types.Project) (*chart.Chart, error) { 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) +// SaveChart saves the chart to directory +func SaveChart(c *chart.Chart, dest string) (string, error) { + dir, err := filepath.Abs(dest) if err != nil { - return err + return "", err } - return util.SaveDir(chart, dest) -} + for _, file := range c.Raw { + filename := filepath.Join(dir, file.Name) + filedir := filepath.Dir(filename) -// 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] + stat, err := os.Stat(filedir) + + if err != nil { + if os.IsNotExist(err) { + if err2 := os.MkdirAll(filedir, 0755); err2 != nil { + return "", err2 + } + } else { + return "", err + } + } else if !stat.IsDir() { + return "", errors.Errorf("%s: not a directory", dest) + } + + f, err := os.Create(filename) + if err != nil { + return "", err + } + _, err = f.Write(file.Data) + if err != nil { + return "", err + } } - - dirname = filepath.Dir(dirname) - return SaveChart(project, dirname) + return dir, nil }