bump compose-go to v2.6.2

Signed-off-by: Guillaume Lours <705411+glours@users.noreply.github.com>
This commit is contained in:
Guillaume Lours 2025-05-07 15:29:18 +02:00
parent 9e17bc7a4c
commit acdf95fe75
No known key found for this signature in database
13 changed files with 1357 additions and 358 deletions

2
go.mod
View File

@ -6,7 +6,7 @@ require (
github.com/Masterminds/semver/v3 v3.2.1
github.com/Microsoft/go-winio v0.6.2
github.com/aws/aws-sdk-go-v2/config v1.27.27
github.com/compose-spec/compose-go/v2 v2.6.0
github.com/compose-spec/compose-go/v2 v2.6.2
github.com/containerd/console v1.0.4
github.com/containerd/containerd/v2 v2.0.5
github.com/containerd/continuity v0.4.5

4
go.sum
View File

@ -64,8 +64,8 @@ github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XL
github.com/cloudflare/cfssl v0.0.0-20180223231731-4e2dcbde5004/go.mod h1:yMWuSON2oQp+43nFtAV/uvKQIFpSPerB57DCt9t8sSA=
github.com/codahale/rfc6979 v0.0.0-20141003034818-6a90f24967eb h1:EDmT6Q9Zs+SbUoc7Ik9EfrFqcylYqgPZ9ANSbTAntnE=
github.com/codahale/rfc6979 v0.0.0-20141003034818-6a90f24967eb/go.mod h1:ZjrT6AXHbDs86ZSdt/osfBi5qfexBrKUdONk989Wnk4=
github.com/compose-spec/compose-go/v2 v2.6.0 h1:/+oBD2ixSENOeN/TlJqWZmUak0xM8A7J08w/z661Wd4=
github.com/compose-spec/compose-go/v2 v2.6.0/go.mod h1:vPlkN0i+0LjLf9rv52lodNMUTJF5YHVfHVGLLIP67NA=
github.com/compose-spec/compose-go/v2 v2.6.2 h1:31uZNNLeRrKjtUCc56CzPpPykW1Tm6SxLn4gx9Jjzqw=
github.com/compose-spec/compose-go/v2 v2.6.2/go.mod h1:vPlkN0i+0LjLf9rv52lodNMUTJF5YHVfHVGLLIP67NA=
github.com/containerd/cgroups/v3 v3.0.5 h1:44na7Ud+VwyE7LIoJ8JTNQOa549a8543BmzaJHo6Bzo=
github.com/containerd/cgroups/v3 v3.0.5/go.mod h1:SA5DLYnXO8pTGYiAHXz94qvLQTKfVM5GEVisn4jpins=
github.com/containerd/console v1.0.4 h1:F2g4+oChYvBTsASRTz8NP6iIAi97J3TtSAsLbIFn4ro=

View File

@ -81,6 +81,8 @@ type ProjectOptions struct {
// Callbacks to retrieve metadata information during parse defined before
// creating the project
Listeners []loader.Listener
// ResourceLoaders manages support for remote resources
ResourceLoaders []loader.ResourceLoader
}
type ProjectOptionsFn func(*ProjectOptions) error
@ -347,8 +349,9 @@ func WithResolvedPaths(resolve bool) ProjectOptionsFn {
// WithResourceLoader register support for ResourceLoader to manage remote resources
func WithResourceLoader(r loader.ResourceLoader) ProjectOptionsFn {
return func(o *ProjectOptions) error {
o.ResourceLoaders = append(o.ResourceLoaders, r)
o.loadOptions = append(o.loadOptions, func(options *loader.Options) {
options.ResourceLoaders = append(options.ResourceLoaders, r)
options.ResourceLoaders = o.ResourceLoaders
})
return nil
}
@ -390,8 +393,14 @@ func (o *ProjectOptions) GetWorkingDir() (string, error) {
if o.WorkingDir != "" {
return filepath.Abs(o.WorkingDir)
}
PATH:
for _, path := range o.ConfigPaths {
if path != "-" {
for _, l := range o.ResourceLoaders {
if l.Accept(path) {
break PATH
}
}
absPath, err := filepath.Abs(path)
if err != nil {
return "", err

View File

@ -68,7 +68,10 @@ func applyServiceExtends(ctx context.Context, name string, services map[string]a
)
switch v := extends.(type) {
case map[string]any:
ref = v["service"].(string)
ref, ok = v["service"].(string)
if !ok {
return nil, fmt.Errorf("extends.%s.service is required", name)
}
file = v["file"]
opts.ProcessEvent("extends", v)
case string:

View File

@ -686,7 +686,10 @@ func projectName(details *types.ConfigDetails, opts *Options) error {
}
pjNameFromConfigFile = interpolated["name"].(string)
}
pjNameFromConfigFile = NormalizeProjectName(pjNameFromConfigFile)
if !opts.SkipNormalization {
pjNameFromConfigFile = NormalizeProjectName(pjNameFromConfigFile)
}
if pjNameFromConfigFile != "" {
opts.projectName = pjNameFromConfigFile
}

View File

@ -131,6 +131,13 @@ func checkConsistency(project *types.Project) error { //nolint:gocyclo
s.Deploy.Replicas = s.Scale
}
if s.Scale != nil && *s.Scale < 0 {
return fmt.Errorf("services.%s.scale: must be greater than or equal to 0", s.Name)
}
if s.Deploy != nil && s.Deploy.Replicas != nil && *s.Deploy.Replicas < 0 {
return fmt.Errorf("services.%s.deploy.replicas: must be greater than or equal to 0", s.Name)
}
if s.CPUS != 0 && s.Deploy != nil {
if s.Deploy.Resources.Limits != nil && s.Deploy.Resources.Limits.NanoCPUs.Value() != s.CPUS {
return fmt.Errorf("services.%s: can't set distinct values on 'cpus' and 'deploy.resources.limits.cpus': %w",
@ -172,6 +179,24 @@ func checkConsistency(project *types.Project) error { //nolint:gocyclo
}
}
}
mounts := map[string]string{}
for i, tmpfs := range s.Tmpfs {
loc := fmt.Sprintf("services.%s.tmpfs[%d]", s.Name, i)
path, _, _ := strings.Cut(tmpfs, ":")
if p, ok := mounts[path]; ok {
return fmt.Errorf("%s: target %s already mounted as %s", loc, path, p)
}
mounts[path] = loc
}
for i, volume := range s.Volumes {
loc := fmt.Sprintf("services.%s.volumes[%d]", s.Name, i)
if p, ok := mounts[volume.Target]; ok {
return fmt.Errorf("%s: target %s already mounted as %s", loc, volume.Target, p)
}
mounts[volume.Target] = loc
}
}
for name, secret := range project.Secrets {

View File

@ -35,7 +35,7 @@ func (r *relativePathsResolver) maybeUnixPath(a any) (any, error) {
// Note that this is not required for Docker for Windows when specifying
// a local Windows path, because Docker for Windows translates the Windows
// path into a valid path within the VM.
if !path.IsAbs(p) && !isWindowsAbs(p) {
if !path.IsAbs(p) && !IsWindowsAbs(p) {
if filepath.IsAbs(p) {
return p, nil
}

View File

@ -16,66 +16,218 @@
package paths
// This file contains utilities to check for Windows absolute paths on Linux.
// The code in this file was largely copied from the Golang filepath package
// https://github.com/golang/go/blob/master/src/internal/filepathlite/path_windows.go
import "slices"
// Copyright 2010 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// https://github.com/golang/go/blob/master/LICENSE
// This file contains utilities to check for Windows absolute paths on Linux.
// The code in this file was largely copied from the Golang filepath package
// https://github.com/golang/go/blob/1d0e94b1e13d5e8a323a63cd1cc1ef95290c9c36/src/path/filepath/path_windows.go#L12-L65
func isSlash(c uint8) bool {
func IsPathSeparator(c uint8) bool {
return c == '\\' || c == '/'
}
// isAbs reports whether the path is a Windows absolute path.
func isWindowsAbs(path string) (b bool) {
// IsWindowsAbs reports whether the path is absolute.
// copied from IsAbs(path string) (b bool) from internal.filetpathlite
func IsWindowsAbs(path string) (b bool) {
l := volumeNameLen(path)
if l == 0 {
return false
}
// If the volume name starts with a double slash, this is an absolute path.
if IsPathSeparator(path[0]) && IsPathSeparator(path[1]) {
return true
}
path = path[l:]
if path == "" {
return false
}
return isSlash(path[0])
return IsPathSeparator(path[0])
}
// volumeNameLen returns length of the leading volume name on Windows.
// It returns 0 elsewhere.
//
// See:
// https://learn.microsoft.com/en-us/dotnet/standard/io/file-path-formats
// https://googleprojectzero.blogspot.com/2016/02/the-definitive-guide-on-win32-to-nt.html
func volumeNameLen(path string) int {
if len(path) < 2 {
return 0
}
// with drive letter
c := path[0]
if path[1] == ':' && ('a' <= c && c <= 'z' || 'A' <= c && c <= 'Z') {
switch {
case len(path) >= 2 && path[1] == ':':
// Path starts with a drive letter.
//
// Not all Windows functions necessarily enforce the requirement that
// drive letters be in the set A-Z, and we don't try to here.
//
// We don't handle the case of a path starting with a non-ASCII character,
// in which case the "drive letter" might be multiple bytes long.
return 2
}
// is it UNC? https://msdn.microsoft.com/en-us/library/windows/desktop/aa365247(v=vs.85).aspx
if l := len(path); l >= 5 && isSlash(path[0]) && isSlash(path[1]) &&
!isSlash(path[2]) && path[2] != '.' {
// first, leading `\\` and next shouldn't be `\`. its server name.
for n := 3; n < l-1; n++ {
// second, next '\' shouldn't be repeated.
if isSlash(path[n]) {
n++
// third, following something characters. its share name.
if !isSlash(path[n]) {
if path[n] == '.' {
break
}
for ; n < l; n++ {
if isSlash(path[n]) {
break
}
}
return n
}
break
}
case len(path) == 0 || !IsPathSeparator(path[0]):
// Path does not have a volume component.
return 0
case pathHasPrefixFold(path, `\\.\UNC`):
// We're going to treat the UNC host and share as part of the volume
// prefix for historical reasons, but this isn't really principled;
// Windows's own GetFullPathName will happily remove the first
// component of the path in this space, converting
// \\.\unc\a\b\..\c into \\.\unc\a\c.
return uncLen(path, len(`\\.\UNC\`))
case pathHasPrefixFold(path, `\\.`) ||
pathHasPrefixFold(path, `\\?`) || pathHasPrefixFold(path, `\??`):
// Path starts with \\.\, and is a Local Device path; or
// path starts with \\?\ or \??\ and is a Root Local Device path.
//
// We treat the next component after the \\.\ prefix as
// part of the volume name, which means Clean(`\\?\c:\`)
// won't remove the trailing \. (See #64028.)
if len(path) == 3 {
return 3 // exactly \\.
}
_, rest, ok := cutPath(path[4:])
if !ok {
return len(path)
}
return len(path) - len(rest) - 1
case len(path) >= 2 && IsPathSeparator(path[1]):
// Path starts with \\, and is a UNC path.
return uncLen(path, 2)
}
return 0
}
// pathHasPrefixFold tests whether the path s begins with prefix,
// ignoring case and treating all path separators as equivalent.
// If s is longer than prefix, then s[len(prefix)] must be a path separator.
func pathHasPrefixFold(s, prefix string) bool {
if len(s) < len(prefix) {
return false
}
for i := 0; i < len(prefix); i++ {
if IsPathSeparator(prefix[i]) {
if !IsPathSeparator(s[i]) {
return false
}
} else if toUpper(prefix[i]) != toUpper(s[i]) {
return false
}
}
if len(s) > len(prefix) && !IsPathSeparator(s[len(prefix)]) {
return false
}
return true
}
// uncLen returns the length of the volume prefix of a UNC path.
// prefixLen is the prefix prior to the start of the UNC host;
// for example, for "//host/share", the prefixLen is len("//")==2.
func uncLen(path string, prefixLen int) int {
count := 0
for i := prefixLen; i < len(path); i++ {
if IsPathSeparator(path[i]) {
count++
if count == 2 {
return i
}
}
}
return len(path)
}
// cutPath slices path around the first path separator.
func cutPath(path string) (before, after string, found bool) {
for i := range path {
if IsPathSeparator(path[i]) {
return path[:i], path[i+1:], true
}
}
return path, "", false
}
// postClean adjusts the results of Clean to avoid turning a relative path
// into an absolute or rooted one.
func postClean(out *lazybuf) {
if out.volLen != 0 || out.buf == nil {
return
}
// If a ':' appears in the path element at the start of a path,
// insert a .\ at the beginning to avoid converting relative paths
// like a/../c: into c:.
for _, c := range out.buf {
if IsPathSeparator(c) {
break
}
if c == ':' {
out.prepend('.', Separator)
return
}
}
// If a path begins with \??\, insert a \. at the beginning
// to avoid converting paths like \a\..\??\c:\x into \??\c:\x
// (equivalent to c:\x).
if len(out.buf) >= 3 && IsPathSeparator(out.buf[0]) && out.buf[1] == '?' && out.buf[2] == '?' {
out.prepend(Separator, '.')
}
}
func toUpper(c byte) byte {
if 'a' <= c && c <= 'z' {
return c - ('a' - 'A')
}
return c
}
const (
Separator = '\\' // OS-specific path separator
)
// A lazybuf is a lazily constructed path buffer.
// It supports append, reading previously appended bytes,
// and retrieving the final string. It does not allocate a buffer
// to hold the output until that output diverges from s.
type lazybuf struct {
path string
buf []byte
w int
volAndPath string
volLen int
}
func (b *lazybuf) index(i int) byte {
if b.buf != nil {
return b.buf[i]
}
return b.path[i]
}
func (b *lazybuf) append(c byte) {
if b.buf == nil {
if b.w < len(b.path) && b.path[b.w] == c {
b.w++
return
}
b.buf = make([]byte, len(b.path))
copy(b.buf, b.path[:b.w])
}
b.buf[b.w] = c
b.w++
}
func (b *lazybuf) prepend(prefix ...byte) {
b.buf = slices.Insert(b.buf, 0, prefix...)
b.w += len(prefix)
}
func (b *lazybuf) string() string {
if b.buf == nil {
return b.volAndPath[:b.volLen+b.w]
}
return b.volAndPath[:b.volLen] + string(b.buf[:b.w])
}

File diff suppressed because it is too large Load Diff

View File

@ -1834,8 +1834,6 @@ func deriveDeepCopy_39(dst, src *DeviceRequest) {
// deriveDeepCopy_40 recursively copies the contents of src into dst.
func deriveDeepCopy_40(dst, src *ServiceNetworkConfig) {
dst.Priority = src.Priority
dst.GatewayPriority = src.GatewayPriority
if src.Aliases == nil {
dst.Aliases = nil
} else {
@ -1854,6 +1852,14 @@ func deriveDeepCopy_40(dst, src *ServiceNetworkConfig) {
}
copy(dst.Aliases, src.Aliases)
}
if src.DriverOpts != nil {
dst.DriverOpts = make(map[string]string, len(src.DriverOpts))
deriveDeepCopy_4(dst.DriverOpts, src.DriverOpts)
} else {
dst.DriverOpts = nil
}
dst.GatewayPriority = src.GatewayPriority
dst.InterfaceName = src.InterfaceName
dst.Ipv4Address = src.Ipv4Address
dst.Ipv6Address = src.Ipv6Address
if src.LinkLocalIPs == nil {
@ -1875,12 +1881,7 @@ func deriveDeepCopy_40(dst, src *ServiceNetworkConfig) {
copy(dst.LinkLocalIPs, src.LinkLocalIPs)
}
dst.MacAddress = src.MacAddress
if src.DriverOpts != nil {
dst.DriverOpts = make(map[string]string, len(src.DriverOpts))
deriveDeepCopy_4(dst.DriverOpts, src.DriverOpts)
} else {
dst.DriverOpts = nil
}
dst.Priority = src.Priority
if src.Extensions != nil {
dst.Extensions = make(map[string]any, len(src.Extensions))
src.Extensions.DeepCopy(dst.Extensions)

View File

@ -658,7 +658,7 @@ func (p Project) WithServicesEnvironmentResolved(discardEnvFiles bool) (*Project
return resolve, true
}
// then service.environment
if s, ok := service.Environment[k]; ok {
if s, ok := service.Environment[k]; ok && s != nil {
return *s, true
}
return "", false

View File

@ -470,14 +470,15 @@ type PlacementPreferences struct {
// ServiceNetworkConfig is the network configuration for a service
type ServiceNetworkConfig struct {
Priority int `yaml:"priority,omitempty" json:"priority,omitempty"`
GatewayPriority int `yaml:"gw_priority,omitempty" json:"gw_priority,omitempty"`
Aliases []string `yaml:"aliases,omitempty" json:"aliases,omitempty"`
DriverOpts Options `yaml:"driver_opts,omitempty" json:"driver_opts,omitempty"`
GatewayPriority int `yaml:"gw_priority,omitempty" json:"gw_priority,omitempty"`
InterfaceName string `yaml:"interface_name,omitempty" json:"interface_name,omitempty"`
Ipv4Address string `yaml:"ipv4_address,omitempty" json:"ipv4_address,omitempty"`
Ipv6Address string `yaml:"ipv6_address,omitempty" json:"ipv6_address,omitempty"`
LinkLocalIPs []string `yaml:"link_local_ips,omitempty" json:"link_local_ips,omitempty"`
MacAddress string `yaml:"mac_address,omitempty" json:"mac_address,omitempty"`
DriverOpts Options `yaml:"driver_opts,omitempty" json:"driver_opts,omitempty"`
Priority int `yaml:"priority,omitempty" json:"priority,omitempty"`
Extensions Extensions `yaml:"#extensions,inline,omitempty" json:"-"`
}

2
vendor/modules.txt vendored
View File

@ -122,7 +122,7 @@ github.com/aws/smithy-go/transport/http/internal/io
# github.com/cenkalti/backoff/v4 v4.3.0
## explicit; go 1.18
github.com/cenkalti/backoff/v4
# github.com/compose-spec/compose-go/v2 v2.6.0
# github.com/compose-spec/compose-go/v2 v2.6.2
## explicit; go 1.23
github.com/compose-spec/compose-go/v2/cli
github.com/compose-spec/compose-go/v2/consts