// Copyright (c) 2022 Alibaba Group Holding Ltd. // // 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 docker import ( "context" "io" "strings" "github.com/compose-spec/compose-go/cli" "github.com/docker/cli/cli/command" "github.com/docker/cli/cli/flags" "github.com/docker/compose/v2/cmd/formatter" "github.com/docker/compose/v2/pkg/api" "github.com/docker/compose/v2/pkg/compose" ) type Compose struct { client *api.ServiceProxy w io.Writer } func NewCompose(w io.Writer) (*Compose, error) { c := &Compose{w: w} dockerCli, err := command.NewDockerCli( command.WithCombinedStreams(c.w), // command.WithDefaultContextStoreConfig(), Deprecated, set during NewDockerCli ) if err != nil { return nil, err } opts := flags.NewClientOptions() err = dockerCli.Initialize(opts) if err != nil { return nil, err } c.client = api.NewServiceProxy().WithService(compose.NewComposeService(dockerCli)) return c, nil } func (c Compose) Up(ctx context.Context, name string, configs []string, source string, detach bool) error { pOpts, err := cli.NewProjectOptions( configs, cli.WithWorkingDirectory(source), cli.WithDefaultConfigPath, cli.WithName(name), ) if err != nil { return err } project, err := cli.ProjectFromOptions(pOpts) if err != nil { return err } for i, s := range project.Services { // TODO(WeixinX): Change from `Label` to `CustomLabels` after upgrading the dependency library github.com/compose-spec/compose-go s.Labels = map[string]string{ api.ProjectLabel: project.Name, api.ServiceLabel: s.Name, api.VersionLabel: api.ComposeVersion, api.WorkingDirLabel: project.WorkingDir, api.ConfigFilesLabel: strings.Join(project.ComposeFiles, ","), api.OneoffLabel: "False", } project.Services[i] = s } project.WithoutUnnecessaryResources() // for log var consumer api.LogConsumer if !detach { consumer = formatter.NewLogConsumer(ctx, c.w, c.w, true, true, false) } attachTo := make([]string, 0) for _, svc := range project.Services { attachTo = append(attachTo, svc.Name) } return c.client.Up(ctx, project, api.UpOptions{ Start: api.StartOptions{ Attach: consumer, AttachTo: attachTo, }, }) } func (c Compose) List(ctx context.Context) ([]api.Stack, error) { return c.client.List(ctx, api.ListOptions{}) } func (c Compose) Down(ctx context.Context, name string) error { return c.client.Down(ctx, name, api.DownOptions{}) } func (c Compose) Ps(ctx context.Context, name string) ([]api.ContainerSummary, error) { return c.client.Ps(ctx, name, api.PsOptions{}) }