use new moby/moby modules instead of docker/docker dependency

Signed-off-by: Guillaume Lours <glours@users.noreply.github.com>
This commit is contained in:
Guillaume Lours 2026-04-03 14:27:24 +02:00 committed by Guillaume Lours
parent 9085f7bda1
commit ba417e4392
8 changed files with 207 additions and 7 deletions

2
go.mod
View file

@ -18,7 +18,6 @@ require (
github.com/docker/buildx v0.33.0
github.com/docker/cli v29.4.0+incompatible
github.com/docker/cli-docs-tool v0.11.0
github.com/docker/docker v28.5.2+incompatible
github.com/docker/go-units v0.5.0
github.com/eiannone/keyboard v0.0.0-20220611211555-0d226195f203
github.com/fsnotify/fsevents v0.2.0
@ -73,6 +72,7 @@ require (
github.com/containerd/typeurl/v2 v2.2.3 // indirect
github.com/cpuguy83/go-md2man/v2 v2.0.7 // indirect
github.com/docker/distribution v2.8.3+incompatible // indirect
github.com/docker/docker v28.5.2+incompatible // indirect
github.com/docker/docker-credential-helpers v0.9.5 // indirect
github.com/docker/go-connections v0.6.0 // indirect
github.com/felixge/httpsnoop v1.0.4 // indirect

View file

@ -21,7 +21,7 @@ package locker
import (
"os"
"github.com/docker/docker/pkg/pidfile"
"github.com/docker/compose/v5/internal/pidfile"
)
func (f *Pidfile) Lock() error {

View file

@ -21,7 +21,7 @@ package locker
import (
"os"
"github.com/docker/docker/pkg/pidfile"
"github.com/docker/compose/v5/internal/pidfile"
"github.com/mitchellh/go-ps"
)

View file

@ -0,0 +1,67 @@
/*
Copyright 2025 Docker Compose CLI authors
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Package pidfile provides helper functions to create and remove PID files.
// A PID file is usually a file used to store the process ID of a running
// process.
//
// This is a temporary copy of github.com/moby/moby/v2/pkg/pidfile, and
// should be replaced once pidfile is available as a standalone module.
package pidfile
import (
"bytes"
"fmt"
"os"
"strconv"
)
// Read reads the "PID file" at path, and returns the PID if it contains a
// valid PID of a running process, or 0 otherwise. It returns an error when
// failing to read the file, or if the file doesn't exist, but malformed content
// is ignored. Consumers should therefore check if the returned PID is a non-zero
// value before use.
func Read(path string) (pid int, _ error) {
pidByte, err := os.ReadFile(path)
if err != nil {
return 0, err
}
pid, err = strconv.Atoi(string(bytes.TrimSpace(pidByte)))
if err != nil {
return 0, nil
}
if pid != 0 && alive(pid) {
return pid, nil
}
return 0, nil
}
// Write writes a "PID file" at the specified path. It returns an error if the
// file exists and contains a valid PID of a running process, or when failing
// to write the file.
func Write(path string, pid int) error {
if pid < 1 {
return fmt.Errorf("invalid PID (%d): only positive PIDs are allowed", pid)
}
oldPID, err := Read(path)
if err != nil && !os.IsNotExist(err) {
return err
}
if oldPID != 0 {
return fmt.Errorf("process with PID %d is still running", oldPID)
}
return os.WriteFile(path, []byte(strconv.Itoa(pid)), 0o644)
}

View file

@ -0,0 +1,42 @@
//go:build !windows
/*
Copyright 2025 Docker Compose CLI authors
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package pidfile
import (
"errors"
"os"
"runtime"
"strconv"
"golang.org/x/sys/unix"
)
func alive(pid int) bool {
if pid < 1 {
return false
}
switch runtime.GOOS {
case "darwin":
err := unix.Kill(pid, 0)
return err == nil || errors.Is(err, unix.EPERM)
default:
_, err := os.Stat("/proc/" + strconv.Itoa(pid))
return err == nil
}
}

View file

@ -0,0 +1,38 @@
//go:build windows
/*
Copyright 2025 Docker Compose CLI authors
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package pidfile
import "golang.org/x/sys/windows"
func alive(pid int) bool {
if pid < 1 {
return false
}
h, err := windows.OpenProcess(windows.PROCESS_QUERY_LIMITED_INFORMATION, false, uint32(pid))
if err != nil {
return false
}
var c uint32
err = windows.GetExitCodeProcess(h, &c)
_ = windows.CloseHandle(h)
if err != nil {
return c == uint32(windows.STATUS_PENDING)
}
return true
}

View file

@ -17,13 +17,16 @@
package compose
import (
"bytes"
"encoding/binary"
"errors"
"io"
"strings"
"sync"
"testing"
"github.com/compose-spec/compose-go/v2/types"
"github.com/docker/docker/pkg/stdcopy"
"github.com/moby/moby/api/pkg/stdcopy"
containerType "github.com/moby/moby/api/types/container"
"github.com/moby/moby/client"
"go.uber.org/mock/gomock"
@ -33,6 +36,56 @@ import (
compose "github.com/docker/compose/v5/pkg/api"
)
// newStdWriter is copied from github.com/moby/moby/daemon/internal/stdcopymux
// because NewStdWriter was moved to a daemon-internal package in moby v2 and
// is no longer publicly importable. We need it in tests to produce multiplexed
// streams that stdcopy.StdCopy can demultiplex.
const (
stdWriterPrefixLen = 8
stdWriterFdIndex = 0
stdWriterSizeIndex = 4
)
var bufPool = &sync.Pool{New: func() any { return bytes.NewBuffer(nil) }}
type stdWriter struct {
io.Writer
prefix byte
}
func (w *stdWriter) Write(p []byte) (int, error) {
if w == nil || w.Writer == nil {
return 0, errors.New("writer not instantiated")
}
if p == nil {
return 0, nil
}
header := [stdWriterPrefixLen]byte{stdWriterFdIndex: w.prefix}
binary.BigEndian.PutUint32(header[stdWriterSizeIndex:], uint32(len(p)))
buf := bufPool.Get().(*bytes.Buffer)
buf.Write(header[:])
buf.Write(p)
n, err := w.Writer.Write(buf.Bytes())
n -= stdWriterPrefixLen
if n < 0 {
n = 0
}
buf.Reset()
bufPool.Put(buf)
return n, err
}
func newStdWriter(w io.Writer, streamType stdcopy.StdType) io.Writer {
return &stdWriter{
Writer: w,
prefix: byte(streamType),
}
}
func TestComposeService_Logs_Demux(t *testing.T) {
mockCtrl := gomock.NewController(t)
defer mockCtrl.Finish()
@ -68,8 +121,8 @@ func TestComposeService_Logs_Demux(t *testing.T) {
_ = c1Reader.Close()
_ = c1Writer.Close()
})
c1Stdout := stdcopy.NewStdWriter(c1Writer, stdcopy.Stdout)
c1Stderr := stdcopy.NewStdWriter(c1Writer, stdcopy.Stderr)
c1Stdout := newStdWriter(c1Writer, stdcopy.Stdout)
c1Stderr := newStdWriter(c1Writer, stdcopy.Stderr)
go func() {
_, err := c1Stdout.Write([]byte("hello stdout\n"))
assert.NilError(t, err, "Writing to fake stdout")

View file

@ -29,7 +29,7 @@ import (
"github.com/compose-spec/compose-go/v2/types"
"github.com/containerd/errdefs"
"github.com/docker/cli/cli-plugins/manager"
"github.com/docker/docker/api/types/versions"
"github.com/moby/moby/client/pkg/versions"
"github.com/spf13/cobra"
"golang.org/x/sync/errgroup"