Skip to content

Commit

Permalink
feat(compose): Support depends_on property (#1634)
Browse files Browse the repository at this point in the history
Reviewed-by: Alexander Jung <alex@unikraft.io>
Approved-by: Alexander Jung <alex@unikraft.io>
  • Loading branch information
nderjung committed May 9, 2024
2 parents b46a3f6 + 2e1e57a commit e95202f
Show file tree
Hide file tree
Showing 7 changed files with 95 additions and 6 deletions.
82 changes: 82 additions & 0 deletions compose/project.go
Original file line number Diff line number Diff line change
Expand Up @@ -240,3 +240,85 @@ func (project *Project) AssignIPs(ctx context.Context) error {

return nil
}

// ServicesOrderedByDependencies receives a list of services and generates a
// new list ordered by dependencies. If expand is set, it will also include
// dependencies not present in the original list.
func (project *Project) ServicesOrderedByDependencies(ctx context.Context, services types.Services, expand bool) []types.ServiceConfig {
added := map[string]struct{}{}

var addDependenciesRecursevly func(service types.ServiceConfig)

orderedServices := []types.ServiceConfig{}
addDependenciesRecursevly = func(service types.ServiceConfig) {
added[service.Name] = struct{}{}
for name, dependency := range service.DependsOn {
_, ok := services[name]
if !ok && !expand {
continue
}

log.G(ctx).
WithField("service", service.Name).
WithField("on", name).
Debug("depends")

_, ok = added[name]
if !ok && dependency.Required {
addDependenciesRecursevly(project.Services[name])
}
}

orderedServices = append(orderedServices, service)
}

for _, service := range services {
_, ok := added[service.Name]
if !ok {
addDependenciesRecursevly(service)
}
}

return orderedServices
}

// ServicesReversedWithDependants receives a list of services and generates a
// new list reverse ordered by dependencies. If expand is set, it will also
// include dependendants not present in the original list.
func (project *Project) ServicesReversedByDependencies(ctx context.Context, services types.Services, expand bool) []types.ServiceConfig {
added := map[string]struct{}{}

var addDependantsRecursevly func(service types.ServiceConfig)

reversedServices := []types.ServiceConfig{}
addDependantsRecursevly = func(service types.ServiceConfig) {
added[service.Name] = struct{}{}
for _, name := range service.GetDependents(project.Project) {
_, ok := services[name]
if !ok && !expand {
continue
}

log.G(ctx).
WithField("service", name).
WithField("on", service.Name).
Debug("depends")

_, ok = added[name]
if !ok && project.Services[name].DependsOn[service.Name].Required {
addDependantsRecursevly(project.Services[name])
}
}

reversedServices = append(reversedServices, service)
}

for _, service := range services {
_, ok := added[service.Name]
if !ok {
addDependantsRecursevly(service)
}
}

return reversedServices
}
4 changes: 3 additions & 1 deletion internal/cli/kraft/compose/create/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -274,7 +274,9 @@ func (opts *CreateOptions) Run(ctx context.Context, args []string) error {
return err
}

for _, service := range services {
orderedServices := project.ServicesOrderedByDependencies(ctx, services, true)
for _, service := range orderedServices {
log.G(ctx).Debugf("creating service %s...", service.Name)
alreadyCreated := false
for _, machine := range machines.Items {
if service.ContainerName != machine.Name {
Expand Down
3 changes: 2 additions & 1 deletion internal/cli/kraft/compose/down/down.go
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,8 @@ func (opts *DownOptions) Run(ctx context.Context, args []string) error {
return err
}

for _, service := range project.Services {
orderedServices := project.ServicesReversedByDependencies(ctx, project.Services, false)
for _, service := range orderedServices {
for _, machine := range machines.Items {
if service.ContainerName == machine.Name {
if err := removeService(ctx, service); err != nil {
Expand Down
3 changes: 2 additions & 1 deletion internal/cli/kraft/compose/pause/pause.go
Original file line number Diff line number Diff line change
Expand Up @@ -91,8 +91,9 @@ func (opts *PauseOptions) Run(ctx context.Context, args []string) error {
return err
}

orderedServices := project.ServicesReversedByDependencies(ctx, services, false)
machinesToPause := []string{}
for _, service := range services {
for _, service := range orderedServices {
for _, machine := range machines.Items {
if service.ContainerName == machine.Name && machine.Status.State == machineapi.MachineStateRunning {
machinesToPause = append(machinesToPause, machine.Name)
Expand Down
3 changes: 2 additions & 1 deletion internal/cli/kraft/compose/start/start.go
Original file line number Diff line number Diff line change
Expand Up @@ -91,8 +91,9 @@ func (opts *StartOptions) Run(ctx context.Context, args []string) error {
return err
}

orderedServices := project.ServicesOrderedByDependencies(ctx, services, true)
machinesToStart := []string{}
for _, service := range services {
for _, service := range orderedServices {
for _, machine := range machines.Items {
if service.ContainerName == machine.Name {
if machine.Status.State == machineapi.MachineStateCreated || machine.Status.State == machineapi.MachineStateExited {
Expand Down
3 changes: 2 additions & 1 deletion internal/cli/kraft/compose/stop/stop.go
Original file line number Diff line number Diff line change
Expand Up @@ -91,8 +91,9 @@ func (opts *StopOptions) Run(ctx context.Context, args []string) error {
return err
}

orderedServices := project.ServicesReversedByDependencies(ctx, services, false)
machinesToStop := []string{}
for _, service := range services {
for _, service := range orderedServices {
for _, machine := range machines.Items {
if service.ContainerName == machine.Name &&
(machine.Status.State == machineapi.MachineStateRunning ||
Expand Down
3 changes: 2 additions & 1 deletion internal/cli/kraft/compose/unpause/unpause.go
Original file line number Diff line number Diff line change
Expand Up @@ -91,8 +91,9 @@ func (opts *UnpauseOptions) Run(ctx context.Context, args []string) error {
return err
}

orderedServices := project.ServicesOrderedByDependencies(ctx, services, true)
machinesToUnpause := []string{}
for _, service := range services {
for _, service := range orderedServices {
for _, machine := range machines.Items {
if service.ContainerName == machine.Name {
if machine.Status.State == machineapi.MachineStatePaused {
Expand Down

0 comments on commit e95202f

Please sign in to comment.