introduce config --services, --volumes, --hash for backward compatibility

Signed-off-by: Nicolas De Loof <nicolas.deloof@gmail.com>
This commit is contained in:
Nicolas De Loof 2021-03-19 14:03:27 +01:00
parent 3366131096
commit ec5489a08c
No known key found for this signature in database
GPG Key ID: 9858809D6F8F6E7E
7 changed files with 87 additions and 27 deletions

View File

@ -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
}

View File

@ -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)
}
}

View File

@ -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{}{}
}

View File

@ -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
}

View File

@ -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
}

View File

@ -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)
}
}

View File

@ -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
}