Skip to content

Commit

Permalink
Update compose: resource policy handling
Browse files Browse the repository at this point in the history
  • Loading branch information
daichitakahashi committed Feb 4, 2023
1 parent e13139c commit 30737ae
Show file tree
Hide file tree
Showing 3 changed files with 52 additions and 30 deletions.
8 changes: 7 additions & 1 deletion compose.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,13 @@ func Compose(ctx context.Context, configFiles []string, opts ...ComposeOption) (
}
apiClient.NegotiateAPIVersion(ctx)

composer, err := be.Load(ctx, "", configFiles, nil, "")
composer, err := be.Load(ctx, compose.LoadOptions{
ProjectDir: "",
ConfigFiles: nil,
Profiles: nil,
EnvFile: "",
Policy: compose.ResourcePolicy{},
})
if err != nil {
return nil, fmt.Errorf("compose: %w", err)
}
Expand Down
16 changes: 14 additions & 2 deletions compose/compose.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,20 @@ import (

type (
Backend interface {
// TODO: ResourcePolicy
Load(ctx context.Context, projectDir string, configFiles, profiles []string, envFile string) (Composer, error)
Load(ctx context.Context, opts LoadOptions) (Composer, error)
}

ResourcePolicy struct {
AllowReuse bool
Remove bool
Takeover bool
}
LoadOptions struct {
ProjectDir string
ConfigFiles []string
Profiles []string
EnvFile string
Policy ResourcePolicy
}

Composer interface {
Expand Down
58 changes: 31 additions & 27 deletions compose_backend.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ type (
cli *client.Client
dockerCompose func(ctx context.Context, args ...string) *exec.Cmd
proj projectConfig
policy compose.ResourcePolicy

m sync.Mutex
services map[string]bool // services launched
Expand All @@ -42,21 +43,21 @@ type (
}
)

func (b *composeBackend) Load(ctx context.Context, projectDir string, configFiles, profiles []string, envFile string) (compose.Composer, error) {
func (b *composeBackend) Load(ctx context.Context, opts compose.LoadOptions) (compose.Composer, error) {
args := []string{
"compose",
}
if projectDir != "" {
args = append(args, []string{"--project-dir", projectDir}...)
if opts.ProjectDir != "" {
args = append(args, []string{"--project-dir", opts.ProjectDir}...)
}
for _, f := range configFiles {
for _, f := range opts.ConfigFiles {
args = append(args, []string{"--file", f}...)
}
for _, p := range profiles {
for _, p := range opts.Profiles {
args = append(args, []string{"--profile", p}...)
}
if envFile != "" {
args = append(args, []string{"--env-file", envFile}...)
if opts.EnvFile != "" {
args = append(args, []string{"--env-file", opts.EnvFile}...)
}
dockerCompose := func(ctx context.Context, commandArgs ...string) *exec.Cmd {
return exec.CommandContext(ctx, "docker", append(args, commandArgs...)...)
Expand All @@ -77,6 +78,8 @@ func (b *composeBackend) Load(ctx context.Context, projectDir string, configFile
cli: b.cli,
dockerCompose: dockerCompose,
proj: config,
policy: opts.Policy,
services: map[string]bool{},
}, nil
}

Expand All @@ -103,20 +106,27 @@ func (c *composer) Up(ctx context.Context, service string, opts compose.UpOption
}

// Get existing containers of the service
list, err := c.cli.ContainerList(ctx, types.ContainerListOptions{
filter := types.ContainerListOptions{
Filters: filters.NewArgs(
filters.Arg("com.docker.compose.project", c.proj.Name),
filters.Arg("com.docker.compose.service", service),
),
})
}
list, err := c.cli.ContainerList(ctx, filter)
if err != nil {
return nil, err
}

// Check consistence of container num, if required.
if opts.ScalingStrategy == compose.ScalingStrategyConsistent &&
0 < len(list) && len(list) != requiredContainerN {
return nil, errors.New("containers already exist, but its number is inconsistent with the request")
initiate := len(list) == 0

if !initiate {
if !c.policy.AllowReuse {
return nil, fmt.Errorf("service conainter %q already exist", service)
}
// Check consistence of container num, if required.
if opts.ScalingStrategy == compose.ScalingStrategyConsistent && len(list) != requiredContainerN {
return nil, errors.New("containers already exist, but its number is inconsistent with the request")
}
}

if len(list) < requiredContainerN { // More containers are required.
Expand All @@ -135,25 +145,19 @@ func (c *composer) Up(ctx context.Context, service string, opts compose.UpOption
return nil, err
}

// Service is initiated by this op.
if len(list) == 0 {
c.m.Lock()
c.services[service] = true
c.m.Unlock()
}

list, err = c.cli.ContainerList(ctx, types.ContainerListOptions{
All: true,
Filters: filters.NewArgs(
filters.Arg("com.docker.compose.project", c.proj.Name),
filters.Arg("com.docker.compose.service", service),
),
})
list, err = c.cli.ContainerList(ctx, filter)
if err != nil {
return nil, err
}
}

// Set service as a target of cleanup.
if c.policy.Remove && (initiate || c.policy.Takeover) {
c.m.Lock()
c.services[service] = true
c.m.Unlock()
}

// Sort containers according to container number.
sort.Slice(list, func(i, j int) bool {
return list[i].Names[0] < list[j].Names[0]
Expand Down

0 comments on commit 30737ae

Please sign in to comment.