mirror of
https://github.com/docker/compose.git
synced 2026-08-03 22:27:30 +00:00
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:
parent
9085f7bda1
commit
ba417e4392
8 changed files with 207 additions and 7 deletions
2
go.mod
2
go.mod
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
)
|
||||
|
||||
|
|
|
|||
67
internal/pidfile/pidfile.go
Normal file
67
internal/pidfile/pidfile.go
Normal 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)
|
||||
}
|
||||
42
internal/pidfile/pidfile_unix.go
Normal file
42
internal/pidfile/pidfile_unix.go
Normal 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
|
||||
}
|
||||
}
|
||||
38
internal/pidfile/pidfile_windows.go
Normal file
38
internal/pidfile/pidfile_windows.go
Normal 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
|
||||
}
|
||||
|
|
@ -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")
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue