Browse Source

up should not silently ignore missing depends_on service

Signed-off-by: Nicolas De Loof <[email protected]>
Nicolas De Loof 2 năm trước cách đây
mục cha
commit
06ec06472f
5 tập tin đã thay đổi với 29 bổ sung86 xóa
  1. 1 1
      go.mod
  2. 2 2
      go.sum
  3. 6 74
      pkg/compose/create.go
  4. 19 8
      pkg/compose/dependencies.go
  5. 1 1
      pkg/compose/dependencies_test.go

+ 1 - 1
go.mod

@@ -5,7 +5,7 @@ go 1.20
 require (
 	github.com/AlecAivazis/survey/v2 v2.3.6
 	github.com/buger/goterm v1.0.4
-	github.com/compose-spec/compose-go v1.13.5
+	github.com/compose-spec/compose-go v1.14.0
 	github.com/containerd/console v1.0.3
 	github.com/containerd/containerd v1.6.21
 	github.com/cucumber/godog v0.0.0-00010101000000-000000000000 // replaced; see replace for the actual version used

+ 2 - 2
go.sum

@@ -157,8 +157,8 @@ github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWH
 github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
 github.com/cncf/xds/go v0.0.0-20211001041855-01bcc9b48dfe/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
 github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
-github.com/compose-spec/compose-go v1.13.5 h1:ogqJOGEbe3uRxMg0ZEufOoCQTpX61l8tUeyW4UQgEBk=
-github.com/compose-spec/compose-go v1.13.5/go.mod h1:m0o4G6MQDHjjz9rY7No9FpnNi+9sKic262rzrwuCqic=
+github.com/compose-spec/compose-go v1.14.0 h1:/+tQxBEPIrfsi87Qh7/VjMzcJN3BRNER/RO71ku+u6E=
+github.com/compose-spec/compose-go v1.14.0/go.mod h1:m0o4G6MQDHjjz9rY7No9FpnNi+9sKic262rzrwuCqic=
 github.com/containerd/cgroups v1.0.4 h1:jN/mbWBEaz+T1pi5OFtnkQ+8qnmEbAr1Oo1FRm5B0dA=
 github.com/containerd/console v1.0.3 h1:lIr7SlA5PxZyMV30bDW0MGbiOPXwc63yRuCP0ARubLw=
 github.com/containerd/console v1.0.3/go.mod h1:7LqA/THxQ86k76b8c/EMSiaJ3h1eZkMkXar0TQ1gf3U=

+ 6 - 74
pkg/compose/create.go

@@ -106,11 +106,6 @@ func (s *composeService) create(ctx context.Context, project *types.Project, opt
 		}
 	}
 
-	err = prepareServicesDependsOn(project)
-	if err != nil {
-		return err
-	}
-
 	return newConvergence(options.Services, observedState, s).apply(ctx, project, options)
 }
 
@@ -147,72 +142,6 @@ func prepareNetworks(project *types.Project) {
 	}
 }
 
-func prepareServicesDependsOn(p *types.Project) error {
-	allServices := types.Project{}
-	allServices.Services = p.AllServices()
-
-	for i, service := range p.Services {
-		var dependencies []string
-		networkDependency := getDependentServiceFromMode(service.NetworkMode)
-		if networkDependency != "" {
-			dependencies = append(dependencies, networkDependency)
-		}
-
-		ipcDependency := getDependentServiceFromMode(service.Ipc)
-		if ipcDependency != "" {
-			dependencies = append(dependencies, ipcDependency)
-		}
-
-		pidDependency := getDependentServiceFromMode(service.Pid)
-		if pidDependency != "" {
-			dependencies = append(dependencies, pidDependency)
-		}
-
-		for _, vol := range service.VolumesFrom {
-			spec := strings.Split(vol, ":")
-			if len(spec) == 0 {
-				continue
-			}
-			if spec[0] == "container" {
-				continue
-			}
-			dependencies = append(dependencies, spec[0])
-		}
-
-		for _, link := range service.Links {
-			dependencies = append(dependencies, strings.Split(link, ":")[0])
-		}
-
-		for d := range service.DependsOn {
-			dependencies = append(dependencies, d)
-		}
-
-		if len(dependencies) == 0 {
-			continue
-		}
-
-		// Verify dependencies exist in the project, whether disabled or not
-		deps, err := allServices.GetServices(dependencies...)
-		if err != nil {
-			return err
-		}
-
-		if service.DependsOn == nil {
-			service.DependsOn = make(types.DependsOnConfig)
-		}
-
-		for _, d := range deps {
-			if _, ok := service.DependsOn[d.Name]; !ok {
-				service.DependsOn[d.Name] = types.ServiceDependency{
-					Condition: types.ServiceConditionStarted,
-				}
-			}
-		}
-		p.Services[i] = service
-	}
-	return nil
-}
-
 func (s *composeService) ensureNetworks(ctx context.Context, networks types.Networks) error {
 	for _, network := range networks {
 		err := s.ensureNetwork(ctx, network)
@@ -640,8 +569,8 @@ func setLimits(limits *types.Resource, resources *container.Resources) {
 			resources.NanoCPUs = int64(f * 1e9)
 		}
 	}
-	if limits.PIds > 0 {
-		resources.PidsLimit = &limits.PIds
+	if limits.Pids > 0 {
+		resources.PidsLimit = &limits.Pids
 	}
 }
 
@@ -743,7 +672,10 @@ func getVolumesFrom(project *types.Project, volumesFrom []string) ([]string, []s
 }
 
 func getDependentServiceFromMode(mode string) string {
-	if strings.HasPrefix(mode, types.NetworkModeServicePrefix) {
+	if strings.HasPrefix(
+		mode,
+		types.NetworkModeServicePrefix,
+	) {
 		return mode[len(types.NetworkModeServicePrefix):]
 	}
 	return ""

+ 19 - 8
pkg/compose/dependencies.go

@@ -23,6 +23,8 @@ import (
 	"sync"
 
 	"github.com/compose-spec/compose-go/types"
+	"github.com/docker/compose/v2/pkg/api"
+	"github.com/pkg/errors"
 	"golang.org/x/sync/errgroup"
 
 	"github.com/docker/compose/v2/pkg/utils"
@@ -76,7 +78,7 @@ func downDirectionTraversal(visitorFn func(context.Context, string) error) *grap
 
 // InDependencyOrder applies the function to the services of the project taking in account the dependency order
 func InDependencyOrder(ctx context.Context, project *types.Project, fn func(context.Context, string) error, options ...func(*graphTraversal)) error {
-	graph, err := NewGraph(project.Services, ServiceStopped)
+	graph, err := NewGraph(project, ServiceStopped)
 	if err != nil {
 		return err
 	}
@@ -89,7 +91,7 @@ func InDependencyOrder(ctx context.Context, project *types.Project, fn func(cont
 
 // InReverseDependencyOrder applies the function to the services of the project in reverse order of dependencies
 func InReverseDependencyOrder(ctx context.Context, project *types.Project, fn func(context.Context, string) error, options ...func(*graphTraversal)) error {
-	graph, err := NewGraph(project.Services, ServiceStarted)
+	graph, err := NewGraph(project, ServiceStarted)
 	if err != nil {
 		return err
 	}
@@ -252,19 +254,28 @@ func (v *Vertex) GetChildren() []*Vertex {
 }
 
 // NewGraph returns the dependency graph of the services
-func NewGraph(services types.Services, initialStatus ServiceStatus) (*Graph, error) {
+func NewGraph(project *types.Project, initialStatus ServiceStatus) (*Graph, error) {
 	graph := &Graph{
 		lock:     sync.RWMutex{},
 		Vertices: map[string]*Vertex{},
 	}
 
-	for _, s := range services {
+	for _, s := range project.Services {
 		graph.AddVertex(s.Name, s.Name, initialStatus)
 	}
 
-	for _, s := range services {
+	for _, s := range project.Services {
 		for _, name := range s.GetDependencies() {
-			_ = graph.AddEdge(s.Name, name)
+			err := graph.AddEdge(s.Name, name)
+			if err != nil {
+				if api.IsNotFoundError(err) {
+					ds, err := project.GetDisabledService(name)
+					if err == nil {
+						return nil, fmt.Errorf("service %s is required by %s but is disabled. Can be enabled by profiles %s", name, s.Name, ds.Profiles)
+					}
+				}
+				return nil, err
+			}
 		}
 	}
 
@@ -304,10 +315,10 @@ func (g *Graph) AddEdge(source string, destination string) error {
 	destinationVertex := g.Vertices[destination]
 
 	if sourceVertex == nil {
-		return fmt.Errorf("could not find %s", source)
+		return errors.Wrapf(api.ErrNotFound, "could not find %s", source)
 	}
 	if destinationVertex == nil {
-		return fmt.Errorf("could not find %s", destination)
+		return errors.Wrapf(api.ErrNotFound, "could not find %s", destination)
 	}
 
 	// If they are already connected

+ 1 - 1
pkg/compose/dependencies_test.go

@@ -270,7 +270,7 @@ func TestBuildGraph(t *testing.T) {
 				Services: tC.services,
 			}
 
-			graph, err := NewGraph(project.Services, ServiceStopped)
+			graph, err := NewGraph(&project, ServiceStopped)
 			assert.NilError(t, err, fmt.Sprintf("failed to build graph for: %s", tC.desc))
 
 			for k, vertex := range graph.Vertices {