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: run tests on windows workers #2449

Open
wants to merge 57 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
57 commits
Select commit Hold shift + click to select a range
b6785c6
chore: run core on windows
mdelapenya Mar 18, 2024
a46f5db
revert: simplify pipeline
mdelapenya Mar 18, 2024
4045675
chore: do not use bridge driver on Windows
mdelapenya Mar 18, 2024
ddb0d94
docs: document driver
mdelapenya Mar 18, 2024
b3bd89f
Merge branch 'main' into windows-workers
mdelapenya Mar 25, 2024
27becea
chore: convert to constant
mdelapenya Mar 25, 2024
c07b9ee
chore: remove duplicated variable
mdelapenya Mar 25, 2024
a989e10
chore: do not expose windows constant
mdelapenya Mar 25, 2024
d874b4b
revert: run only on windows workers
mdelapenya Mar 26, 2024
1c36f14
fix: always detect OS and Docker Server version
mdelapenya Mar 26, 2024
977c28a
feat: run windows tests in Testcontainers Cloud
mdelapenya Mar 26, 2024
0f263ef
chore: inherit secrets in the reusable workflow
mdelapenya Mar 26, 2024
2da2575
chore: properly close docker client in tests
mdelapenya Mar 26, 2024
e5652c3
chore: do not apply nat driver on tcc
mdelapenya Mar 26, 2024
10ea4dd
chore: skip test for windows
mdelapenya Mar 26, 2024
82309e1
fix: use docker socket from testcontainers in subtests
mdelapenya Mar 26, 2024
2a497c2
Revert "chore: skip test for windows"
mdelapenya Mar 26, 2024
96a8ee7
chore: skip provider test on windows
mdelapenya Mar 26, 2024
17414f6
chore: better config tests for single initialisation
mdelapenya Mar 26, 2024
0b6ef18
fix: proper cleanup of docker client in tests
mdelapenya Mar 26, 2024
8b76f65
fix: do not set bridge as default network driver
mdelapenya Mar 26, 2024
50aa2b6
chore: check for remote host properly
mdelapenya Mar 26, 2024
2f303a1
fix: use extracted socket
mdelapenya Mar 26, 2024
d56bb5e
chore: simplify conditions
mdelapenya Mar 26, 2024
75705b0
fix: typo
mdelapenya Mar 26, 2024
5a7e0e9
chore: extract docker socket path verification to a function
mdelapenya Mar 26, 2024
7748feb
chore: add test for windows remote
mdelapenya Mar 26, 2024
4bf55ac
chore: skip host network tests on windows
mdelapenya Mar 26, 2024
b50dbd9
revert: log for errors
mdelapenya Mar 26, 2024
22c76de
chore: skip socket check tests
mdelapenya Mar 26, 2024
efef173
fix: do not timeout in tests
mdelapenya Mar 27, 2024
9c0d768
chore: skip test on Windows
mdelapenya Mar 27, 2024
dcd2737
chore: use pinned bash image
mdelapenya Mar 27, 2024
11905eb
revert: print container logs
mdelapenya Mar 27, 2024
db46e94
chore: leverage container lifecycle to create paths
mdelapenya Mar 27, 2024
19612a4
revert: use string
mdelapenya Mar 27, 2024
39c107d
chore: force LF line endings in Git
mdelapenya Mar 27, 2024
07e2781
Revert "revert: use string"
mdelapenya Mar 27, 2024
b8b7800
Revert "revert: print container logs"
mdelapenya Mar 27, 2024
0c9736e
Revert "revert: log for errors"
mdelapenya Mar 27, 2024
fe32906
Revert "revert: run only on windows workers"
mdelapenya Mar 27, 2024
02ac372
Revert "revert: simplify pipeline"
mdelapenya Mar 27, 2024
8f93deb
fix: update tests
mdelapenya Mar 27, 2024
e8ac173
chore: run core tests for PRs+Ubuntu or merge-commits+all platforms
mdelapenya Mar 27, 2024
b142495
revert: force always running tests
mdelapenya Mar 27, 2024
37463ff
fix: bring back removed modules
mdelapenya Mar 27, 2024
7acaea8
fix: pass secrets to reusable workflows
mdelapenya Mar 27, 2024
8a55ec3
chore: proper calculation of rootless socket
mdelapenya Mar 27, 2024
4756134
fix: create a default docker config.json file if it does not exists
mdelapenya Mar 27, 2024
05e52b6
fix: update comment on rootless
mdelapenya Mar 27, 2024
70bd817
chore: honour rootless socket path
mdelapenya Mar 27, 2024
51c2ceb
revert: log env for subprocess
mdelapenya Mar 27, 2024
2c91259
fix: use proper docker host in subprocess test
mdelapenya Mar 27, 2024
20caafd
chore: simplify test
mdelapenya Mar 27, 2024
853b194
chore: initialise DockerSocketPath on init
mdelapenya Mar 27, 2024
0ed8418
Revert "chore: initialise DockerSocketPath on init"
mdelapenya Mar 27, 2024
6e468bc
fix: testcontainers socket override checks
mdelapenya Mar 27, 2024
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
1 change: 1 addition & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
*.sh text eol=lf
14 changes: 10 additions & 4 deletions .github/workflows/ci-test-go.yml
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@ on:
type: boolean
default: false
description: "Disable the ryuk container for the test."
secrets:
TC_CLOUD_TOKEN:
required: true

permissions:
contents: read
Expand Down Expand Up @@ -92,15 +95,18 @@ jobs:
working-directory: ./${{ inputs.project-directory }}
run: make tools-tidy

- name: Setup Testcontainers Cloud Client
# Use Testcontainers Cloud for Windows and MacOS, but only for merge commits on main
if: ${{ inputs.run-tests && (inputs.platform == 'windows-latest' || inputs.platform == 'macos-latest') }}
uses: atomicjar/testcontainers-cloud-setup-action@v1
with:
token: ${{ secrets.TC_CLOUD_TOKEN }}

- name: ensure compilation
working-directory: ./${{ inputs.project-directory }}
run: go build

- name: go test
# 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?
if: ${{ inputs.run-tests }}
working-directory: ./${{ inputs.project-directory }}
timeout-minutes: 30
Expand Down
10 changes: 8 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,15 +27,16 @@ jobs:
strategy:
matrix:
go-version: [1.21.x, 1.x]
platform: [ubuntu-latest, macos-latest]
platform: [ubuntu-latest, macos-latest, windows-latest]
uses: ./.github/workflows/ci-test-go.yml
secrets: inherit
with:
go-version: ${{ matrix.go-version }}
fail-fast: true
platform: ${{ matrix.platform }}
project-directory: "."
rootless-docker: false
run-tests: ${{ matrix.platform == 'ubuntu-latest' }}
run-tests: true
ryuk-disabled: false

# The job below is a copy of the job above, but with ryuk disabled.
Expand All @@ -46,6 +47,7 @@ jobs:
matrix:
go-version: [1.21.x, 1.x]
uses: ./.github/workflows/ci-test-go.yml
secrets: inherit
with:
go-version: ${{ matrix.go-version }}
fail-fast: false
Expand All @@ -64,6 +66,7 @@ jobs:
go-version: [1.21.x, 1.x]
platform: [ubuntu-latest]
uses: ./.github/workflows/ci-test-go.yml
secrets: inherit
with:
go-version: ${{ matrix.go-version }}
fail-fast: false
Expand All @@ -79,6 +82,7 @@ jobs:
go-version: [1.21.x, 1.x]
platform: [ubuntu-latest, macos-latest, windows-latest]
uses: ./.github/workflows/ci-test-go.yml
secrets: inherit
with:
go-version: ${{ matrix.go-version }}
fail-fast: true
Expand All @@ -96,6 +100,7 @@ jobs:
platform: [ubuntu-latest]
module: [artemis, cassandra, chroma, clickhouse, cockroachdb, compose, consul, couchbase, elasticsearch, gcloud, inbucket, influxdb, k3s, k6, kafka, localstack, mariadb, milvus, minio, mockserver, mongodb, mssql, mysql, nats, neo4j, ollama, openfga, openldap, opensearch, postgres, pulsar, qdrant, rabbitmq, redis, redpanda, registry, surrealdb, vault, weaviate]
uses: ./.github/workflows/ci-test-go.yml
secrets: inherit
with:
go-version: ${{ matrix.go-version }}
fail-fast: false
Expand All @@ -111,6 +116,7 @@ jobs:
matrix:
module: [nginx, toxiproxy]
uses: ./.github/workflows/ci-test-go.yml
secrets: inherit
with:
go-version: "1.21.x"
fail-fast: true
Expand Down
18 changes: 5 additions & 13 deletions config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,21 +25,13 @@ func TestReadConfig(t *testing.T) {
t.Run("Config is read just once", func(t *testing.T) {
t.Setenv("HOME", "")
t.Setenv("USERPROFILE", "") // Windows support
t.Setenv("TESTCONTAINERS_RYUK_DISABLED", "true")

cfg := testcontainers.ReadConfig()

expected := testcontainers.TestcontainersConfig{
RyukDisabled: true,
Config: config.Config{
RyukDisabled: true,
},
}

assert.Equal(t, expected, cfg)
t.Setenv("TESTCONTAINERS_RYUK_DISABLED", "true")
cfg1 := testcontainers.ReadConfig()

t.Setenv("TESTCONTAINERS_RYUK_DISABLED", "false")
cfg = testcontainers.ReadConfig()
assert.Equal(t, expected, cfg)
cfg2 := testcontainers.ReadConfig()

assert.Equal(t, cfg1, cfg2)
})
}
113 changes: 64 additions & 49 deletions docker_auth_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,137 +26,152 @@ var indexDockerIO = core.IndexDockerIO
func TestGetDockerConfig(t *testing.T) {
const expectedErrorMessage = "Expected to find %s in auth configs"

t.Setenv("DOCKER_CONFIG", t.TempDir())

// Verify that the default docker config file exists before any test in this suite runs.
// Then, we can safely run the tests that rely on it.
// Then, we can safely run the tests that rely on it. If it does not exist, we create it
// using the content of the testdata/.docker/config.json file into a temporary directory.
defaultCfg, err := dockercfg.LoadDefaultConfig()
require.NoError(t, err)
require.NotEmpty(t, defaultCfg)
if err != nil {
// create docker config file
bs, err := os.ReadFile(filepath.Join(testDockerConfigDirPath, "config.json"))
require.NoError(t, err)

t.Run("without DOCKER_CONFIG env var retrieves default", func(t *testing.T) {
t.Setenv("DOCKER_CONFIG", "")
defaultCfgPath, err := dockercfg.ConfigPath()
require.NoError(t, err)

cfg, err := getDockerConfig()
// write file to default location
err = os.WriteFile(defaultCfgPath, bs, 0644)
require.NoError(t, err)
require.NotEmpty(t, cfg)

assert.Equal(t, defaultCfg, cfg)
defaultCfg, err = dockercfg.LoadDefaultConfig()
require.NoError(t, err)
}
require.NotEmpty(t, defaultCfg)

t.Run("without DOCKER_CONFIG env var retrieves default", func(tt *testing.T) {
cfg, err := getDockerConfig()
require.NoError(tt, err)
require.NotEmpty(tt, cfg)

assert.Equal(tt, defaultCfg, cfg)
})

t.Run("with DOCKER_CONFIG env var pointing to a non-existing file raises error", func(t *testing.T) {
t.Setenv("DOCKER_CONFIG", filepath.Join(testDockerConfigDirPath, "non-existing"))
t.Run("with DOCKER_CONFIG env var pointing to a non-existing file raises error", func(tt *testing.T) {
tt.Setenv("DOCKER_CONFIG", filepath.Join(testDockerConfigDirPath, "non-existing"))

cfg, err := getDockerConfig()
require.Error(t, err)
require.Empty(t, cfg)
require.Error(tt, err)
require.Empty(tt, cfg)
})

t.Run("with DOCKER_CONFIG env var", func(t *testing.T) {
t.Setenv("DOCKER_CONFIG", testDockerConfigDirPath)
t.Run("with DOCKER_CONFIG env var", func(tt *testing.T) {
tt.Setenv("DOCKER_CONFIG", testDockerConfigDirPath)

cfg, err := getDockerConfig()
require.NoError(t, err)
require.NotEmpty(t, cfg)
require.NoError(tt, err)
require.NotEmpty(tt, cfg)

assert.Len(t, cfg.AuthConfigs, 3)
assert.Len(tt, cfg.AuthConfigs, 3)

authCfgs := cfg.AuthConfigs

if _, ok := authCfgs[indexDockerIO]; !ok {
t.Errorf(expectedErrorMessage, indexDockerIO)
tt.Errorf(expectedErrorMessage, indexDockerIO)
}
if _, ok := authCfgs["https://example.com"]; !ok {
t.Errorf(expectedErrorMessage, "https://example.com")
tt.Errorf(expectedErrorMessage, "https://example.com")
}
if _, ok := authCfgs["https://my.private.registry"]; !ok {
t.Errorf(expectedErrorMessage, "https://my.private.registry")
tt.Errorf(expectedErrorMessage, "https://my.private.registry")
}
})

t.Run("DOCKER_AUTH_CONFIG env var takes precedence", func(t *testing.T) {
t.Setenv("DOCKER_AUTH_CONFIG", `{
t.Run("DOCKER_AUTH_CONFIG env var takes precedence", func(tt *testing.T) {
tt.Setenv("DOCKER_AUTH_CONFIG", `{
"auths": {
"`+exampleAuth+`": {}
},
"credsStore": "desktop"
}`)
t.Setenv("DOCKER_CONFIG", testDockerConfigDirPath)
tt.Setenv("DOCKER_CONFIG", testDockerConfigDirPath)

cfg, err := getDockerConfig()
require.NoError(t, err)
require.NotEmpty(t, cfg)
require.NoError(tt, err)
require.NotEmpty(tt, cfg)

assert.Len(t, cfg.AuthConfigs, 1)
assert.Len(tt, cfg.AuthConfigs, 1)

authCfgs := cfg.AuthConfigs

if _, ok := authCfgs[indexDockerIO]; ok {
t.Errorf("Not expected to find %s in auth configs", indexDockerIO)
tt.Errorf("Not expected to find %s in auth configs", indexDockerIO)
}
if _, ok := authCfgs[exampleAuth]; !ok {
t.Errorf(expectedErrorMessage, exampleAuth)
tt.Errorf(expectedErrorMessage, exampleAuth)
}
})

t.Run("retrieve auth with DOCKER_AUTH_CONFIG env var", func(t *testing.T) {
t.Run("retrieve auth with DOCKER_AUTH_CONFIG env var", func(tt *testing.T) {
base64 := "Z29waGVyOnNlY3JldA==" // gopher:secret

t.Setenv("DOCKER_AUTH_CONFIG", `{
tt.Setenv("DOCKER_AUTH_CONFIG", `{
"auths": {
"`+exampleAuth+`": { "username": "gopher", "password": "secret", "auth": "`+base64+`" }
},
"credsStore": "desktop"
}`)

registry, cfg, err := DockerImageAuth(context.Background(), exampleAuth+"/my/image:latest")
require.NoError(t, err)
require.NotEmpty(t, cfg)
require.NoError(tt, err)
require.NotEmpty(tt, cfg)

assert.Equal(t, exampleAuth, registry)
assert.Equal(t, "gopher", cfg.Username)
assert.Equal(t, "secret", cfg.Password)
assert.Equal(t, base64, cfg.Auth)
assert.Equal(tt, exampleAuth, registry)
assert.Equal(tt, "gopher", cfg.Username)
assert.Equal(tt, "secret", cfg.Password)
assert.Equal(tt, base64, cfg.Auth)
})

t.Run("match registry authentication by host", func(t *testing.T) {
t.Run("match registry authentication by host", func(tt *testing.T) {
base64 := "Z29waGVyOnNlY3JldA==" // gopher:secret
imageReg := "example-auth.com"
imagePath := "/my/image:latest"

t.Setenv("DOCKER_AUTH_CONFIG", `{
tt.Setenv("DOCKER_AUTH_CONFIG", `{
"auths": {
"`+exampleAuth+`": { "username": "gopher", "password": "secret", "auth": "`+base64+`" }
},
"credsStore": "desktop"
}`)

registry, cfg, err := DockerImageAuth(context.Background(), imageReg+imagePath)
require.NoError(t, err)
require.NotEmpty(t, cfg)
require.NoError(tt, err)
require.NotEmpty(tt, cfg)

assert.Equal(t, imageReg, registry)
assert.Equal(t, "gopher", cfg.Username)
assert.Equal(t, "secret", cfg.Password)
assert.Equal(t, base64, cfg.Auth)
assert.Equal(tt, imageReg, registry)
assert.Equal(tt, "gopher", cfg.Username)
assert.Equal(tt, "secret", cfg.Password)
assert.Equal(tt, base64, cfg.Auth)
})

t.Run("fail to match registry authentication due to invalid host", func(t *testing.T) {
t.Run("fail to match registry authentication due to invalid host", func(tt *testing.T) {
base64 := "Z29waGVyOnNlY3JldA==" // gopher:secret
imageReg := "example-auth.com"
imagePath := "/my/image:latest"
invalidRegistryURL := "://invalid-host"

t.Setenv("DOCKER_AUTH_CONFIG", `{
tt.Setenv("DOCKER_AUTH_CONFIG", `{
"auths": {
"`+invalidRegistryURL+`": { "username": "gopher", "password": "secret", "auth": "`+base64+`" }
},
"credsStore": "desktop"
}`)

registry, cfg, err := DockerImageAuth(context.Background(), imageReg+imagePath)
require.Equal(t, err, dockercfg.ErrCredentialsNotFound)
require.Empty(t, cfg)
require.Equal(tt, err, dockercfg.ErrCredentialsNotFound)
require.Empty(tt, cfg)

assert.Equal(t, imageReg, registry)
assert.Equal(tt, imageReg, registry)
})
}

Expand Down
8 changes: 8 additions & 0 deletions docker_client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@ func TestGetDockerInfo(t *testing.T) {
ctx := context.Background()
c, err := NewDockerClientWithOpts(ctx)
require.NoError(t, err)
t.Cleanup(func() {
err := c.Close()
require.NoError(t, err)
})

info, err := c.Info(ctx)
require.NoError(t, err)
Expand All @@ -23,6 +27,10 @@ func TestGetDockerInfo(t *testing.T) {
ctx := context.Background()
c, err := NewDockerClientWithOpts(ctx)
require.NoError(t, err)
t.Cleanup(func() {
err := c.Close()
require.NoError(t, err)
})

count := 1024
wg := sync.WaitGroup{}
Expand Down
Loading
Loading