Browse Source

Merge pull request #1444 from docker/config_flags

introduce config --services, --volumes, --hash for backward compatibility
Guillaume Tardif 4 năm trước cách đây
mục cha
commit
6562ec80f4

+ 64 - 4
cli/cmd/compose/convert.go

@@ -22,6 +22,7 @@ import (
 	"fmt"
 	"io"
 	"os"
+	"strings"
 
 	"github.com/cnabio/cnab-to-oci/remotes"
 	"github.com/distribution/distribution/v3/reference"
@@ -32,14 +33,18 @@ import (
 	"github.com/docker/compose-cli/api/client"
 	"github.com/docker/compose-cli/api/compose"
 	"github.com/docker/compose-cli/api/config"
+	"github.com/docker/compose-cli/utils"
 )
 
 type convertOptions struct {
 	*projectOptions
-	Format  string
-	Output  string
-	quiet   bool
-	resolve bool
+	Format   string
+	Output   string
+	quiet    bool
+	resolve  bool
+	services bool
+	volumes  bool
+	hash     string
 }
 
 var addFlagsFuncs []func(cmd *cobra.Command, opts *convertOptions)
@@ -60,6 +65,16 @@ func convertCommand(p *projectOptions) *cobra.Command {
 				}
 				os.Stdout = devnull
 			}
+			if opts.services {
+				return runServices(opts)
+			}
+			if opts.volumes {
+				return runVolumes(opts)
+			}
+			if opts.hash != "" {
+				return runHash(opts)
+			}
+
 			return runConvert(cmd.Context(), opts, args)
 		},
 	}
@@ -68,6 +83,10 @@ func convertCommand(p *projectOptions) *cobra.Command {
 	flags.BoolVar(&opts.resolve, "resolve-image-digests", false, "Pin image tags to digests.")
 	flags.BoolVarP(&opts.quiet, "quiet", "q", false, "Only validate the configuration, don't print anything.")
 
+	flags.BoolVar(&opts.services, "services", false, "Print the service names, one per line.")
+	flags.BoolVar(&opts.volumes, "volumes", false, "Print the volume names, one per line.")
+	flags.StringVar(&opts.hash, "hash", "", "Print the service config hash, one per line.")
+
 	// add flags for hidden backends
 	for _, f := range addFlagsFuncs {
 		f(cmd, &opts)
@@ -126,3 +145,44 @@ func runConvert(ctx context.Context, opts convertOptions, services []string) err
 	_, err = fmt.Fprint(out, string(json))
 	return err
 }
+
+func runServices(opts convertOptions) error {
+	project, err := opts.toProject(nil)
+	if err != nil {
+		return err
+	}
+	for _, s := range project.Services {
+		fmt.Println(s.Name)
+	}
+	return nil
+}
+
+func runVolumes(opts convertOptions) error {
+	project, err := opts.toProject(nil)
+	if err != nil {
+		return err
+	}
+	for _, v := range project.Volumes {
+		fmt.Println(v.Name)
+	}
+	return nil
+}
+
+func runHash(opts convertOptions) error {
+	var services []string
+	if opts.hash != "*" {
+		services = append(services, strings.Split(opts.hash, ",")...)
+	}
+	project, err := opts.toProject(services)
+	if err != nil {
+		return err
+	}
+	for _, s := range project.Services {
+		hash, err := utils.ServiceHash(s)
+		if err != nil {
+			return err
+		}
+		fmt.Printf("%s %s\n", s.Name, hash)
+	}
+	return nil
+}

+ 4 - 2
local/compose/containers.go

@@ -24,6 +24,8 @@ import (
 	"github.com/compose-spec/compose-go/types"
 	moby "github.com/docker/docker/api/types"
 	"github.com/docker/docker/api/types/filters"
+
+	"github.com/docker/compose-cli/utils"
 )
 
 // Containers is a set of moby Container
@@ -69,14 +71,14 @@ type containerPredicate func(c moby.Container) bool
 func isService(services ...string) containerPredicate {
 	return func(c moby.Container) bool {
 		service := c.Labels[serviceLabel]
-		return contains(services, service)
+		return utils.StringContains(services, service)
 	}
 }
 
 func isNotService(services ...string) containerPredicate {
 	return func(c moby.Container) bool {
 		service := c.Labels[serviceLabel]
-		return !contains(services, service)
+		return !utils.StringContains(services, service)
 	}
 }
 

+ 3 - 2
local/compose/convergence.go

@@ -33,6 +33,7 @@ import (
 	"github.com/docker/compose-cli/api/compose"
 	"github.com/docker/compose-cli/api/progress"
 	status "github.com/docker/compose-cli/local/moby"
+	"github.com/docker/compose-cli/utils"
 )
 
 const (
@@ -97,7 +98,7 @@ func (s *composeService) ensureService(ctx context.Context, project *types.Proje
 		return nil
 	}
 
-	expected, err := jsonHash(service)
+	expected, err := utils.ServiceHash(service)
 	if err != nil {
 		return err
 	}
@@ -249,7 +250,7 @@ func (s *composeService) recreateContainer(ctx context.Context, project *types.P
 // setDependentLifecycle define the Lifecycle strategy for all services to depend on specified service
 func setDependentLifecycle(project *types.Project, service string, strategy string) {
 	for i, s := range project.Services {
-		if contains(s.GetDependencies(), service) {
+		if utils.StringContains(s.GetDependencies(), service) {
 			if s.Extensions == nil {
 				s.Extensions = map[string]interface{}{}
 			}

+ 4 - 3
local/compose/create.go

@@ -40,6 +40,7 @@ import (
 	"github.com/docker/compose-cli/api/compose"
 	"github.com/docker/compose-cli/api/progress"
 	convert "github.com/docker/compose-cli/local/moby"
+	"github.com/docker/compose-cli/utils"
 )
 
 func (s *composeService) Create(ctx context.Context, project *types.Project, opts compose.CreateOptions) error {
@@ -102,7 +103,7 @@ func (s *composeService) Create(ctx context.Context, project *types.Project, opt
 	prepareNetworkMode(project)
 
 	return InDependencyOrder(ctx, project, func(c context.Context, service types.ServiceConfig) error {
-		if contains(opts.Services, service.Name) {
+		if utils.StringContains(opts.Services, service.Name) {
 			return s.ensureService(c, project, service, opts.Recreate, opts.Inherit, opts.Timeout)
 		}
 		return s.ensureService(c, project, service, opts.RecreateDependencies, opts.Inherit, opts.Timeout)
@@ -121,7 +122,7 @@ func prepareVolumes(p *types.Project) error {
 				p.Services[i].DependsOn = make(types.DependsOnConfig, len(dependServices))
 			}
 			for _, service := range p.Services {
-				if contains(dependServices, service.Name) {
+				if utils.StringContains(dependServices, service.Name) {
 					p.Services[i].DependsOn[service.Name] = types.ServiceDependency{
 						Condition: types.ServiceConditionStarted,
 					}
@@ -196,7 +197,7 @@ func getImageName(service types.ServiceConfig, projectName string) string {
 func (s *composeService) getCreateOptions(ctx context.Context, p *types.Project, service types.ServiceConfig, number int, inherit *moby.Container,
 	autoRemove bool) (*container.Config, *container.HostConfig, *network.NetworkingConfig, error) {
 
-	hash, err := jsonHash(service)
+	hash, err := utils.ServiceHash(service)
 	if err != nil {
 		return nil, nil, nil, err
 	}

+ 5 - 3
local/compose/dependencies.go

@@ -24,6 +24,8 @@ import (
 
 	"github.com/compose-spec/compose-go/types"
 	"golang.org/x/sync/errgroup"
+
+	"github.com/docker/compose-cli/utils"
 )
 
 // ServiceStatus indicates the status of a service
@@ -313,7 +315,7 @@ func (g *Graph) HasCycles() (bool, error) {
 		path := []string{
 			vertex.Key,
 		}
-		if !contains(discovered, vertex.Key) && !contains(finished, vertex.Key) {
+		if !utils.StringContains(discovered, vertex.Key) && !utils.StringContains(finished, vertex.Key) {
 			var err error
 			discovered, finished, err = g.visit(vertex.Key, path, discovered, finished)
 
@@ -331,11 +333,11 @@ func (g *Graph) visit(key string, path []string, discovered []string, finished [
 
 	for _, v := range g.Vertices[key].Children {
 		path := append(path, v.Key)
-		if contains(discovered, v.Key) {
+		if utils.StringContains(discovered, v.Key) {
 			return nil, nil, fmt.Errorf("cycle found: %s", strings.Join(path, " -> "))
 		}
 
-		if !contains(finished, v.Key) {
+		if !utils.StringContains(finished, v.Key) {
 			if _, _, err := g.visit(v.Key, path, discovered, finished); err != nil {
 				return nil, nil, err
 			}

+ 1 - 1
local/compose/logs.go

@@ -43,7 +43,7 @@ func (s *composeService) Logs(ctx context.Context, projectName string, consumer
 	}
 	if len(options.Services) > 0 {
 		ignore = func(s string) bool {
-			return !contains(options.Services, s)
+			return !utils.StringContains(options.Services, s)
 		}
 	}
 

+ 6 - 12
local/compose/util.go → utils/hash.go

@@ -14,27 +14,21 @@
    limitations under the License.
 */
 
-package compose
+package utils
 
 import (
 	"encoding/json"
 
+	"github.com/compose-spec/compose-go/types"
 	"github.com/opencontainers/go-digest"
 )
 
-func jsonHash(o interface{}) (string, error) {
+// ServiceHash compute configuration has for a service
+// TODO move this to compose-go
+func ServiceHash(o types.ServiceConfig) (string, error) {
 	bytes, err := json.Marshal(o)
 	if err != nil {
 		return "", err
 	}
-	return digest.SHA256.FromBytes(bytes).String(), nil
-}
-
-func contains(slice []string, item string) bool {
-	for _, v := range slice {
-		if v == item {
-			return true
-		}
-	}
-	return false
+	return digest.SHA256.FromBytes(bytes).Encoded(), nil
 }