mirror of
https://github.com/containers/podman.git
synced 2025-05-20 00:27:03 +08:00
Merge pull request #21825 from Luap99/compose
some podman compose fixes
This commit is contained in:
@ -1,5 +1,3 @@
|
||||
//go:build amd64 || arm64
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
@ -16,10 +14,6 @@ import (
|
||||
|
||||
"github.com/containers/podman/v5/cmd/podman/registry"
|
||||
"github.com/containers/podman/v5/pkg/errorhandling"
|
||||
"github.com/containers/podman/v5/pkg/machine"
|
||||
"github.com/containers/podman/v5/pkg/machine/define"
|
||||
"github.com/containers/podman/v5/pkg/machine/provider"
|
||||
"github.com/containers/podman/v5/pkg/machine/vmconfigs"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/pflag"
|
||||
@ -114,10 +108,8 @@ func composeDockerHost() (string, error) {
|
||||
return registry.DefaultAPIAddress(), nil
|
||||
}
|
||||
|
||||
// TODO need to add support for --connection and --url
|
||||
connection, err := registry.PodmanConfig().ContainersConfDefaultsRO.GetConnection("", true)
|
||||
if err != nil {
|
||||
logrus.Info(err)
|
||||
conf := registry.PodmanConfig()
|
||||
if conf.URI == "" {
|
||||
switch runtime.GOOS {
|
||||
// If no default connection is set on Linux or FreeBSD,
|
||||
// we just use the local socket by default - just as
|
||||
@ -132,71 +124,27 @@ func composeDockerHost() (string, error) {
|
||||
}
|
||||
}
|
||||
|
||||
parsedConnection, err := url.Parse(connection.URI)
|
||||
parsedConnection, err := url.Parse(conf.URI)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("preparing connection to remote machine: %w", err)
|
||||
}
|
||||
|
||||
// If the default connection does not point to a `podman
|
||||
// machine`, we cannot use a local path and need to use SSH.
|
||||
if !connection.IsMachine {
|
||||
// Compose doesn't like paths, so we optimistically
|
||||
if !conf.MachineMode {
|
||||
// Docker Compose v1 doesn't like paths for ssh, so we optimistically
|
||||
// assume the presence of a Docker socket on the remote
|
||||
// machine which is the case for podman machines.
|
||||
return strings.TrimSuffix(connection.URI, parsedConnection.Path), nil
|
||||
}
|
||||
|
||||
machineProvider, err := provider.Get()
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("getting machine provider: %w", err)
|
||||
}
|
||||
dirs, err := machine.GetMachineDirs(machineProvider.VMType())
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
machineList, err := vmconfigs.LoadMachinesInDir(dirs)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("listing machines: %w", err)
|
||||
}
|
||||
|
||||
// Now we know that the connection points to a machine and we
|
||||
// can find the machine by looking for the one with the
|
||||
// matching port.
|
||||
connectionPort, err := strconv.Atoi(parsedConnection.Port())
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("parsing connection port: %w", err)
|
||||
}
|
||||
for _, item := range machineList {
|
||||
if connectionPort != item.SSH.Port {
|
||||
continue
|
||||
if parsedConnection.Scheme == "ssh" {
|
||||
return strings.TrimSuffix(conf.URI, parsedConnection.Path), nil
|
||||
}
|
||||
|
||||
state, err := machineProvider.State(item, false)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
if state != define.Running {
|
||||
return "", fmt.Errorf("machine %s is not running but in state %s", item.Name, state)
|
||||
}
|
||||
|
||||
// TODO This needs to be wired back in when all providers are complete
|
||||
// TODO Need someoone to plumb in the connection information below
|
||||
// if machineProvider.VMType() == define.WSLVirt || machineProvider.VMType() == define.HyperVVirt {
|
||||
// if info.ConnectionInfo.PodmanPipe == nil {
|
||||
// return "", errors.New("pipe of machine is not set")
|
||||
// }
|
||||
// return strings.Replace(info.ConnectionInfo.PodmanPipe.Path, `\\.\pipe\`, "npipe:////./pipe/", 1), nil
|
||||
// }
|
||||
// if info.ConnectionInfo.PodmanSocket == nil {
|
||||
// return "", errors.New("socket of machine is not set")
|
||||
// }
|
||||
// return "unix://" + info.ConnectionInfo.PodmanSocket.Path, nil
|
||||
return "", nil
|
||||
return conf.URI, nil
|
||||
}
|
||||
|
||||
return "", fmt.Errorf("could not find a matching machine for connection %q", connection.URI)
|
||||
uri, err := getMachineConn(conf.URI, parsedConnection)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("get machine connection URI: %w", err)
|
||||
}
|
||||
return uri, nil
|
||||
}
|
||||
|
||||
// composeEnv returns the compose-specific environment variables.
|
||||
|
67
cmd/podman/compose_machine.go
Normal file
67
cmd/podman/compose_machine.go
Normal file
@ -0,0 +1,67 @@
|
||||
//go:build amd64 || arm64
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/url"
|
||||
"strconv"
|
||||
|
||||
"github.com/containers/podman/v5/pkg/machine"
|
||||
"github.com/containers/podman/v5/pkg/machine/define"
|
||||
"github.com/containers/podman/v5/pkg/machine/provider"
|
||||
"github.com/containers/podman/v5/pkg/machine/vmconfigs"
|
||||
)
|
||||
|
||||
func getMachineConn(connectionURI string, parsedConnection *url.URL) (string, error) {
|
||||
machineProvider, err := provider.Get()
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("getting machine provider: %w", err)
|
||||
}
|
||||
dirs, err := machine.GetMachineDirs(machineProvider.VMType())
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
machineList, err := vmconfigs.LoadMachinesInDir(dirs)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("listing machines: %w", err)
|
||||
}
|
||||
|
||||
// Now we know that the connection points to a machine and we
|
||||
// can find the machine by looking for the one with the
|
||||
// matching port.
|
||||
connectionPort, err := strconv.Atoi(parsedConnection.Port())
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("parsing connection port: %w", err)
|
||||
}
|
||||
for _, item := range machineList {
|
||||
if connectionPort != item.SSH.Port {
|
||||
continue
|
||||
}
|
||||
|
||||
state, err := machineProvider.State(item, false)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
if state != define.Running {
|
||||
return "", fmt.Errorf("machine %s is not running but in state %s", item.Name, state)
|
||||
}
|
||||
|
||||
// TODO This needs to be wired back in when all providers are complete
|
||||
// TODO Need someoone to plumb in the connection information below
|
||||
// if machineProvider.VMType() == define.WSLVirt || machineProvider.VMType() == define.HyperVVirt {
|
||||
// if info.ConnectionInfo.PodmanPipe == nil {
|
||||
// return "", errors.New("pipe of machine is not set")
|
||||
// }
|
||||
// return strings.Replace(info.ConnectionInfo.PodmanPipe.Path, `\\.\pipe\`, "npipe:////./pipe/", 1), nil
|
||||
// }
|
||||
// if info.ConnectionInfo.PodmanSocket == nil {
|
||||
// return "", errors.New("socket of machine is not set")
|
||||
// }
|
||||
// return "unix://" + info.ConnectionInfo.PodmanSocket.Path, nil
|
||||
return "", nil
|
||||
}
|
||||
return "", fmt.Errorf("could not find a matching machine for connection %q", connectionURI)
|
||||
}
|
12
cmd/podman/compose_machine_unsupported.go
Normal file
12
cmd/podman/compose_machine_unsupported.go
Normal file
@ -0,0 +1,12 @@
|
||||
//go:build !(amd64 || arm64)
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"net/url"
|
||||
)
|
||||
|
||||
func getMachineConn(connection string, parsedConnection *url.URL) (string, error) {
|
||||
return "", errors.New("podman machine not supported on this architecture")
|
||||
}
|
@ -247,6 +247,15 @@ function podman() {
|
||||
return $rc
|
||||
}
|
||||
|
||||
# as rootless we want to test the remote connection so we add --connection
|
||||
function podman_compose() {
|
||||
if is_rootless; then
|
||||
$PODMAN_BIN --connection compose-sock compose "$@"
|
||||
else
|
||||
podman compose "$@"
|
||||
fi
|
||||
}
|
||||
|
||||
###################
|
||||
# random_string # Returns a pseudorandom human-readable string
|
||||
###################
|
||||
@ -271,12 +280,26 @@ done
|
||||
|
||||
# When rootless use a socket path accessible by the rootless user
|
||||
if is_rootless; then
|
||||
# lets test two cases here, for rootless we try to connect to the connection as this should be respected
|
||||
DOCKER_SOCK="$WORKDIR/docker.sock"
|
||||
# use PODMAN_CONNECTIONS_CONF so we do not overwrite user settings
|
||||
PODMAN_CONNECTIONS_CONF="$WORKDIR/connections.json"
|
||||
export PODMAN_CONNECTIONS_CONF
|
||||
$PODMAN_BIN system connection add --default notexists "unix:///I/do/not/exist"
|
||||
$PODMAN_BIN system connection add compose-sock "unix://$DOCKER_SOCK"
|
||||
|
||||
else
|
||||
# export DOCKER_HOST docker-compose will use it
|
||||
DOCKER_HOST="unix://$DOCKER_SOCK"
|
||||
export DOCKER_HOST
|
||||
fi
|
||||
|
||||
# export DOCKER_HOST docker-compose will use it
|
||||
DOCKER_HOST="unix://$DOCKER_SOCK"
|
||||
export DOCKER_HOST
|
||||
# hide annoying podman compose warnings, some tests want to check compose stderr and this breaks it.
|
||||
CONTAINERS_CONF_OVERRIDE="$WORKDIR/containers.conf"
|
||||
echo '[engine]
|
||||
compose_warning_logs=false' > "$CONTAINERS_CONF_OVERRIDE"
|
||||
export CONTAINERS_CONF_OVERRIDE
|
||||
|
||||
|
||||
# Identify the tests to run. If called with args, use those as globs.
|
||||
tests_to_run=()
|
||||
@ -336,12 +359,12 @@ for t in "${tests_to_run[@]}"; do
|
||||
trap - ERR
|
||||
fi
|
||||
|
||||
podman compose up -d &> $logfile
|
||||
podman_compose up -d &> $logfile
|
||||
docker_compose_rc=$?
|
||||
if [[ $docker_compose_rc -ne 0 ]]; then
|
||||
_show_ok 0 "$testname - up" "[ok]" "status=$docker_compose_rc"
|
||||
sed -e 's/^/# /' <$logfile
|
||||
podman compose down >>$logfile 2>&1 # No status check here
|
||||
podman_compose down >>$logfile 2>&1 # No status check here
|
||||
exit 1
|
||||
fi
|
||||
_show_ok 1 "$testname - up"
|
||||
@ -361,7 +384,7 @@ for t in "${tests_to_run[@]}"; do
|
||||
fi
|
||||
|
||||
# Done. Clean up.
|
||||
podman compose down &>> $logfile
|
||||
podman_compose down &>> $logfile
|
||||
rc=$?
|
||||
if [[ $rc -eq 0 ]]; then
|
||||
_show_ok 1 "$testname - down"
|
||||
|
@ -5,7 +5,7 @@ NL=$'\n'
|
||||
|
||||
cp docker-compose.yml docker-compose.yml.bak
|
||||
sed -i -e 's/10001/10002/' docker-compose.yml
|
||||
output=$(docker-compose up -d 2>&1)
|
||||
output=$(podman_compose up -d 2>&1)
|
||||
|
||||
# Horrible output check here but we really want to make sure that there are
|
||||
# no unexpected warning/errors and the normal messages are send on stderr as
|
||||
|
@ -55,10 +55,20 @@ EOF
|
||||
CONTAINERS_CONF_OVERRIDE=$compose_conf run_podman 42 compose fail
|
||||
|
||||
# Make sure the three env variables are set (and parsed)
|
||||
op='=~'
|
||||
url=".*/podman.sock"
|
||||
# if we run remote with --url check the url arg is honored
|
||||
if [[ "$PODMAN" =~ "--url" ]]; then
|
||||
# get the url from the podman string
|
||||
url="${PODMAN##*--url }"
|
||||
url="${url%% *}"
|
||||
op='='
|
||||
fi
|
||||
# podman-remote test might run with --url so unset this because the socket will be used otherwise
|
||||
CONTAINERS_CONF_OVERRIDE=$compose_conf run_podman compose env
|
||||
is "${lines[0]}" ".*/podman.sock"
|
||||
is "${lines[1]}" "0"
|
||||
is "${lines[2]}" ""
|
||||
assert "${lines[0]}" $op "$url" "line 1 of 3 (DOCKER_HOST)"
|
||||
assert "${lines[1]}" = "0" "line 2 of 3 (DOCKER_BUILDKIT)"
|
||||
assert "${lines[2]}" = "" "line 3 of 3 (DOCKER_CONFIG)"
|
||||
|
||||
DOCKER_HOST="$random_data" DOCKER_CONFIG="$random_data" CONTAINERS_CONF_OVERRIDE=$compose_conf run_podman compose env
|
||||
is "${lines[0]}" "$random_data"
|
||||
|
Reference in New Issue
Block a user