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

chore: improvements for Podman support #1251

Draft
wants to merge 7 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 4 additions & 0 deletions container_test.go
Expand Up @@ -127,6 +127,10 @@ func Test_GetDockerfile(t *testing.T) {
}

func Test_BuildImageWithContexts(t *testing.T) {
if testcontainersdocker.IsPodman() {
t.Skip("Incompatible Docker API version for Podman")
}

type TestCase struct {
Name string
ContextPath string
Expand Down
37 changes: 28 additions & 9 deletions docker.go
Expand Up @@ -769,6 +769,15 @@ type DockerProvider struct {
config TestcontainersConfig
}

// BridgeNetworkName gets the name of the bridge newwork: bridge or podman
func (p *DockerProvider) BridgeNetworkName() string {
if testcontainersdocker.IsPodman() {
return Podman
}

return Bridge
}

// Client gets the docker client used by the provider
func (p *DockerProvider) Client() client.APIClient {
return p.client
Expand Down Expand Up @@ -865,7 +874,7 @@ func (p *DockerProvider) CreateContainer(ctx context.Context, req ContainerReque
// Make sure that bridge network exists
// In case it is disabled we will create reaper_default network
if p.DefaultNetwork == "" {
p.DefaultNetwork, err = p.getDefaultNetwork(ctx, p.client)
p.DefaultNetwork, err = p.getDefaultNetwork(ctx)
if err != nil {
return nil, err
}
Expand All @@ -874,7 +883,7 @@ func (p *DockerProvider) CreateContainer(ctx context.Context, req ContainerReque
// If default network is not bridge make sure it is attached to the request
// as container won't be attached to it automatically
// in case of Podman the bridge network is called 'podman' as 'bridge' would conflict
if p.DefaultNetwork != p.defaultBridgeNetworkName {
if p.DefaultNetwork != p.BridgeNetworkName() {
isAttached := false
for _, net := range req.Networks {
if net == p.DefaultNetwork {
Expand Down Expand Up @@ -1259,7 +1268,7 @@ func (p *DockerProvider) CreateNetwork(ctx context.Context, req NetworkRequest)
// Make sure that bridge network exists
// In case it is disabled we will create reaper_default network
if p.DefaultNetwork == "" {
if p.DefaultNetwork, err = p.getDefaultNetwork(ctx, p.client); err != nil {
if p.DefaultNetwork, err = p.getDefaultNetwork(ctx); err != nil {
return nil, err
}
}
Expand Down Expand Up @@ -1329,7 +1338,7 @@ func (p *DockerProvider) GetGatewayIP(ctx context.Context) (string, error) {
// Use a default network as defined in the DockerProvider
if p.DefaultNetwork == "" {
var err error
p.DefaultNetwork, err = p.getDefaultNetwork(ctx, p.client)
p.DefaultNetwork, err = p.getDefaultNetwork(ctx)
if err != nil {
return "", err
}
Expand All @@ -1353,9 +1362,13 @@ func (p *DockerProvider) GetGatewayIP(ctx context.Context) (string, error) {
return ip, nil
}

func (p *DockerProvider) getDefaultNetwork(ctx context.Context, cli client.APIClient) (string, error) {
// getDefaultNetwork returns the name of the default network. In the case the default bridge
// network is present in the list of available networks, it will be returned. Otherwise, it will
// check if the reaper_default network is present. If the bridge network is not present and the
// reaper network is not present, it will create the reaper_default network, returning the latter's name.
func (p *DockerProvider) getDefaultNetwork(ctx context.Context) (string, error) {
// Get list of available networks
networkResources, err := cli.NetworkList(ctx, types.NetworkListOptions{})
networkResources, err := p.client.NetworkList(ctx, types.NetworkListOptions{})
if err != nil {
return "", err
}
Expand All @@ -1364,9 +1377,15 @@ func (p *DockerProvider) getDefaultNetwork(ctx context.Context, cli client.APICl

reaperNetworkExists := false

defaultBridgeNetworkName := p.BridgeNetworkName()
for _, net := range networkResources {
if net.Name == p.defaultBridgeNetworkName {
return p.defaultBridgeNetworkName, nil
if net.Name == defaultBridgeNetworkName {
return defaultBridgeNetworkName, nil
}
// even though the bridge network is called 'podman' in podman,
// the Docker API still returns 'bridge' as the name
if net.Name == Bridge {
return defaultBridgeNetworkName, nil
}

if net.Name == reaperNetwork {
Expand All @@ -1376,7 +1395,7 @@ func (p *DockerProvider) getDefaultNetwork(ctx context.Context, cli client.APICl

// Create a bridge network for the container communications
if !reaperNetworkExists {
_, err = cli.NetworkCreate(ctx, reaperNetwork, types.NetworkCreate{
_, err = p.client.NetworkCreate(ctx, reaperNetwork, types.NetworkCreate{
Driver: Bridge,
Attachable: true,
Labels: map[string]string{
Expand Down
14 changes: 12 additions & 2 deletions docker_auth_test.go
Expand Up @@ -29,6 +29,10 @@ func init() {
}

func TestGetDockerConfig(t *testing.T) {
if testcontainersdocker.IsPodman() {
t.Skip("dockercfg dependency does not support Podman's config file yet")
}

const expectedErrorMessage = "Expected to find %s in auth configs"

// Verify that the default docker config file exists before any test in this suite runs.
Expand Down Expand Up @@ -170,6 +174,10 @@ func removeImageFromLocalCache(t *testing.T, image string) {
}

func TestBuildContainerFromDockerfileWithDockerAuthConfig(t *testing.T) {
if testcontainersdocker.IsPodman() {
t.Skip("dockercfg dependency does not support Podman's config file yet")
}

t.Cleanup(func() {
os.Setenv("DOCKER_AUTH_CONFIG", originalDockerAuthConfig)
})
Expand Down Expand Up @@ -236,6 +244,10 @@ func TestBuildContainerFromDockerfileShouldFailWithWrongDockerAuthConfig(t *test
}

func TestCreateContainerFromPrivateRegistry(t *testing.T) {
if testcontainersdocker.IsPodman() {
t.Skip("dockercfg dependency does not support Podman's config file yet")
}

t.Cleanup(func() {
os.Setenv("DOCKER_AUTH_CONFIG", originalDockerAuthConfig)
})
Expand Down Expand Up @@ -299,7 +311,6 @@ func prepareLocalRegistryWithAuth(t *testing.T) {
}

genContainerReq := GenericContainerRequest{
ProviderType: providerType,
ContainerRequest: req,
Started: true,
}
Expand All @@ -320,7 +331,6 @@ func prepareLocalRegistryWithAuth(t *testing.T) {

func prepareRedisImage(ctx context.Context, req ContainerRequest, t *testing.T) (Container, error) {
genContainerReq := GenericContainerRequest{
ProviderType: providerType,
ContainerRequest: req,
Started: true,
}
Expand Down
2 changes: 0 additions & 2 deletions docker_exec_test.go
Expand Up @@ -17,7 +17,6 @@ func TestExecWithMultiplexedResponse(t *testing.T) {
}

container, err := GenericContainer(ctx, GenericContainerRequest{
ProviderType: providerType,
ContainerRequest: req,
Started: true,
})
Expand Down Expand Up @@ -45,7 +44,6 @@ func TestExecWithNonMultiplexedResponse(t *testing.T) {
}

container, err := GenericContainer(ctx, GenericContainerRequest{
ProviderType: providerType,
ContainerRequest: req,
Started: true,
})
Expand Down