2023-03-28 10:52:17 +08:00
|
|
|
package docker
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
2024-02-22 15:32:07 +08:00
|
|
|
"path"
|
|
|
|
"regexp"
|
|
|
|
"strings"
|
|
|
|
"time"
|
|
|
|
|
2024-02-06 16:36:13 +08:00
|
|
|
"github.com/compose-spec/compose-go/v2/loader"
|
|
|
|
"github.com/compose-spec/compose-go/v2/types"
|
2024-02-19 13:55:27 +08:00
|
|
|
"github.com/docker/cli/cli/command"
|
|
|
|
"github.com/docker/cli/cli/flags"
|
2023-03-28 10:52:17 +08:00
|
|
|
"github.com/docker/compose/v2/pkg/api"
|
2024-02-19 13:55:27 +08:00
|
|
|
"github.com/docker/compose/v2/pkg/compose"
|
|
|
|
"github.com/docker/docker/client"
|
2023-03-28 10:52:17 +08:00
|
|
|
"github.com/joho/godotenv"
|
|
|
|
)
|
|
|
|
|
|
|
|
type ComposeService struct {
|
|
|
|
api.Service
|
|
|
|
project *types.Project
|
|
|
|
}
|
|
|
|
|
2024-02-19 13:55:27 +08:00
|
|
|
func UpComposeProject(project *types.Project) error {
|
|
|
|
for i, s := range project.Services {
|
|
|
|
s.CustomLabels = 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
|
|
|
|
}
|
2023-03-28 10:52:17 +08:00
|
|
|
|
2024-02-19 13:55:27 +08:00
|
|
|
apiClient, err := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation())
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
var ops []command.CLIOption
|
|
|
|
ops = append(ops, command.WithAPIClient(apiClient), command.WithDefaultContextStoreConfig())
|
|
|
|
cli, err := command.NewDockerCli(ops...)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
cliOp := flags.NewClientOptions()
|
|
|
|
if err = cli.Initialize(cliOp); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
service := compose.NewComposeService(cli)
|
|
|
|
composeService := ComposeService{Service: service}
|
2023-03-30 16:47:47 +08:00
|
|
|
|
2024-02-19 13:55:27 +08:00
|
|
|
return composeService.Up(context.Background(), project, api.UpOptions{
|
|
|
|
Create: api.CreateOptions{
|
|
|
|
Timeout: getComposeTimeout(),
|
|
|
|
},
|
|
|
|
Start: api.StartOptions{
|
|
|
|
WaitTimeout: *getComposeTimeout(),
|
|
|
|
Wait: true,
|
|
|
|
},
|
|
|
|
})
|
2023-07-03 21:56:14 +08:00
|
|
|
}
|
|
|
|
|
2023-04-09 22:32:12 +08:00
|
|
|
func GetComposeProject(projectName, workDir string, yml []byte, env []byte, skipNormalization bool) (*types.Project, error) {
|
2023-03-28 10:52:17 +08:00
|
|
|
var configFiles []types.ConfigFile
|
|
|
|
configFiles = append(configFiles, types.ConfigFile{
|
|
|
|
Filename: "docker-compose.yml",
|
|
|
|
Content: yml},
|
|
|
|
)
|
|
|
|
envMap, err := godotenv.UnmarshalBytes(env)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
details := types.ConfigDetails{
|
|
|
|
WorkingDir: workDir,
|
|
|
|
ConfigFiles: configFiles,
|
|
|
|
Environment: envMap,
|
|
|
|
}
|
2023-04-10 14:44:23 +08:00
|
|
|
projectName = strings.ToLower(projectName)
|
|
|
|
reg, _ := regexp.Compile(`[^a-z0-9_-]+`)
|
|
|
|
projectName = reg.ReplaceAllString(projectName, "")
|
2023-11-14 18:00:09 +08:00
|
|
|
project, err := loader.LoadWithContext(context.Background(), details, func(options *loader.Options) {
|
2023-03-28 10:52:17 +08:00
|
|
|
options.SetProjectName(projectName, true)
|
|
|
|
options.ResolvePaths = true
|
2023-04-09 22:32:12 +08:00
|
|
|
options.SkipNormalization = skipNormalization
|
2023-03-28 10:52:17 +08:00
|
|
|
})
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
2023-04-07 16:46:11 +08:00
|
|
|
project.ComposeFiles = []string{path.Join(workDir, "docker-compose.yml")}
|
2023-03-28 10:52:17 +08:00
|
|
|
return project, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func getComposeTimeout() *time.Duration {
|
|
|
|
timeout := time.Minute * time.Duration(10)
|
|
|
|
return &timeout
|
|
|
|
}
|
2023-11-14 18:00:09 +08:00
|
|
|
|
|
|
|
type ComposeProject struct {
|
|
|
|
Version string
|
|
|
|
Services map[string]Service `yaml:"services"`
|
|
|
|
}
|
|
|
|
|
|
|
|
type Service struct {
|
|
|
|
Image string `yaml:"image"`
|
|
|
|
}
|
|
|
|
|
2024-01-23 15:24:13 +08:00
|
|
|
func GetDockerComposeImages(projectName string, env, yml []byte) ([]string, error) {
|
|
|
|
var (
|
|
|
|
configFiles []types.ConfigFile
|
|
|
|
images []string
|
|
|
|
)
|
|
|
|
configFiles = append(configFiles, types.ConfigFile{
|
|
|
|
Filename: "docker-compose.yml",
|
|
|
|
Content: yml},
|
|
|
|
)
|
|
|
|
envMap, err := godotenv.UnmarshalBytes(env)
|
2023-11-14 18:00:09 +08:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
2024-01-23 15:24:13 +08:00
|
|
|
details := types.ConfigDetails{
|
|
|
|
ConfigFiles: configFiles,
|
|
|
|
Environment: envMap,
|
|
|
|
}
|
2023-11-14 18:00:09 +08:00
|
|
|
|
2024-01-23 15:24:13 +08:00
|
|
|
project, err := loader.LoadWithContext(context.Background(), details, func(options *loader.Options) {
|
|
|
|
options.SetProjectName(projectName, true)
|
|
|
|
options.ResolvePaths = true
|
|
|
|
})
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
for _, service := range project.AllServices() {
|
2023-11-14 18:00:09 +08:00
|
|
|
images = append(images, service.Image)
|
|
|
|
}
|
|
|
|
return images, nil
|
|
|
|
}
|