Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve Podman compatibility #414

Merged
merged 7 commits into from
Jun 22, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 52 additions & 0 deletions .github/workflows/ci-podman.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
name: Podman pipeline

on: [push, pull_request]

jobs:
build:
strategy:
matrix:
go-version: [1.14.x, 1.15.x, 1.16.x, 1.17.x, 1.x]
runs-on: ubuntu-22.04
steps:
- name: Set up Go 1.x
uses: actions/setup-go@v3
with:
go-version: ${{ matrix.go-version }}
id: go

- name: Check out code into the Go module directory
uses: actions/checkout@v3

- name: Enable systemd user process
run: |
loginctl enable-linger $(whoami)
sleep 1

- name: Set XDG_RUNTIME_DIR
run: echo "XDG_RUNTIME_DIR=/run/user/$UID" >> $GITHUB_ENV

- name: Install Podman
run: |
set -x
sudo apt-get remove -y podman docker-ce docker docker-engine docker.io containerd runc ||:
sudo apt update
sudo apt install -y software-properties-common debian-archive-keyring dirmngr
sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 0E98404D386FA1D9
sudo add-apt-repository -y "deb http://deb.debian.org/debian experimental main"
sudo apt update
sudo apt -y -t experimental install podman crun docker-compose
sudo systemctl daemon-reload
sleep 5
sudo systemctl start podman.socket
sudo podman info

- name: Set DOCKER_HOST
run: echo "DOCKER_HOST=unix:///run/podman/podman.sock" >> $GITHUB_ENV

- name: gotestsum
# only run tests on linux, there are a number of things that won't allow the tests to run on anything else
# many (maybe, all?) images used can only be build on Linux, they don't have Windows in their manifest, and
# we can't put Windows Server in "Linux Mode" in Github actions
# another, host mode is only available on Linux, and we have tests around that, do we skip them?
run: sudo go run gotest.tools/gotestsum --format short-verbose --rerun-fails=5 --packages="./..." -- -coverprofile=cover.txt
14 changes: 7 additions & 7 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@ on: [push, pull_request]

jobs:
static-analysis:
runs-on: [ubuntu-latest]
runs-on: ubuntu-latest
steps:

- uses: actions/checkout@v2
- uses: actions/checkout@v3
- name: Run ShellCheck
run: |
shellcheck scripts/*.sh
Expand All @@ -24,13 +24,13 @@ jobs:
steps:

- name: Set up Go 1.x
uses: actions/setup-go@v2
uses: actions/setup-go@v3
with:
go-version: ${{ matrix.go-version }}
id: go

- name: Check out code into the Go module directory
uses: actions/checkout@v2
uses: actions/checkout@v3

- name: modVerify
run: go mod verify
Expand All @@ -52,14 +52,14 @@ jobs:
# we can't put Windows Server in "Linux Mode" in Github actions
# another, host mode is only available on Linux, and we have tests around that, do we skip them?
if: ${{ matrix.platform == 'ubuntu-latest' }}
run: go run gotest.tools/gotestsum --format short-verbose -- -coverprofile=cover.txt ./...
run: go run gotest.tools/gotestsum --format short-verbose --rerun-fails=5 --packages="./..." -- -coverprofile=cover.txt

# only report code coverage on linux
- name: Upload coverage report
if: ${{ matrix.platform == 'ubuntu-latest' }}
uses: codecov/codecov-action@v1
uses: codecov/codecov-action@v2
with:
file: ./cover.txt
files: ./cover.txt
name: testcontainers-go-${{ matrix.go-version }}

- name: Run checker
Expand Down
59 changes: 58 additions & 1 deletion compose.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"os/exec"
"path/filepath"
"runtime"
"strconv"
"strings"
"sync"

Expand All @@ -26,6 +27,29 @@ const (
envComposeFile = "COMPOSE_FILE"
)

var (
_ ComposeVersion = (*composeVersion1)(nil)
_ ComposeVersion = (*composeVersion2)(nil)
)

type ComposeVersion interface {
Format(parts ...string) string
}

type composeVersion1 struct {
}

func (c composeVersion1) Format(parts ...string) string {
return strings.Join(parts, "_")
}

type composeVersion2 struct {
}

func (c composeVersion2) Format(parts ...string) string {
return strings.Join(parts, "-")
}

// DockerCompose defines the contract for running Docker Compose
type DockerCompose interface {
Down() ExecError
Expand All @@ -44,6 +68,7 @@ type waitService struct {
// LocalDockerCompose represents a Docker Compose execution using local binary
// docker-compose or docker-compose.exe, depending on the underlying platform
type LocalDockerCompose struct {
ComposeVersion
*LocalDockerComposeOptions
Executable string
ComposeFilePaths []string
Expand Down Expand Up @@ -107,6 +132,7 @@ func NewLocalDockerCompose(filePaths []string, identifier string, opts ...LocalD
dc.absComposeFilePaths[i] = abs
}

_ = dc.determineVersion()
_ = dc.validate()

dc.Identifier = strings.ToLower(identifier)
Expand Down Expand Up @@ -215,6 +241,37 @@ func (dc *LocalDockerCompose) WithExposedService(service string, port int, strat
return dc
}

// determineVersion checks which version of docker-compose is installed
// depending on the version services names are composed in a different way
func (dc *LocalDockerCompose) determineVersion() error {
execErr := executeCompose(dc, []string{"version", "--short"})

if err := execErr.Error; err != nil {
return err
}

components := bytes.Split(execErr.StdoutOutput, []byte("."))
if componentsLen := len(components); componentsLen != 3 {
return fmt.Errorf("expected 3 version components in %s", execErr.StdoutOutput)
}

majorVersion, err := strconv.ParseInt(string(components[0]), 10, 8)
if err != nil {
return err
}

switch majorVersion {
case 1:
dc.ComposeVersion = composeVersion1{}
case 2:
dc.ComposeVersion = composeVersion2{}
default:
return fmt.Errorf("unexpected compose version %d", majorVersion)
}

return nil
}

// validate checks if the files to be run in the compose are valid YAML files, setting up
// references to all services in them
func (dc *LocalDockerCompose) validate() error {
Expand Down Expand Up @@ -332,7 +389,7 @@ func executeCompose(dc *LocalDockerCompose, args []string) ExecError {
environment[k] = v
}

cmds := []string{}
var cmds []string
pwd := "."
if len(dc.absComposeFilePaths) > 0 {
pwd, _ = filepath.Split(dc.absComposeFilePaths[0])
Expand Down
Loading