mirror of
https://github.com/psviderski/unregistry.git
synced 2025-12-14 20:35:57 +01:00
chore: run SSH daemon in test dind container to create e2e test for docker-pussh
This commit is contained in:
@@ -6,6 +6,7 @@
|
||||
!internal/
|
||||
!scripts/
|
||||
!go.*
|
||||
!test/e2e/ssh/test_key.pub
|
||||
|
||||
# Ignore unnecessary files inside allowed directories.
|
||||
**/.DS_Store
|
||||
|
||||
@@ -24,4 +24,3 @@ EXPOSE 5000
|
||||
# Run as root user by default to allow access to the containerd socket. This in unfortunate as running as non-root user
|
||||
# requires changing the containerd socket permissions which still can be manually done by advanced users.
|
||||
ENTRYPOINT ["unregistry"]
|
||||
|
||||
|
||||
@@ -21,7 +21,10 @@ FROM docker:28.3.3-dind AS unregistry-dind
|
||||
|
||||
ENV UNREGISTRY_CONTAINERD_SOCK="/run/docker/containerd/containerd.sock"
|
||||
|
||||
RUN apk add --no-cache openssh && ssh-keygen -A && mkdir /root/.ssh
|
||||
|
||||
COPY scripts/dind-entrypoint.sh /usr/local/bin/entrypoint.sh
|
||||
COPY test/e2e/ssh/test_key.pub /root/.ssh/authorized_keys
|
||||
COPY --from=builder /build/unregistry /usr/local/bin/
|
||||
|
||||
EXPOSE 5000
|
||||
|
||||
@@ -15,6 +15,11 @@ cleanup() {
|
||||
kill "$(cat /run/docker.pid)" 2>/dev/null || true
|
||||
fi
|
||||
|
||||
# Terminate SSH daemon if PID file exists.
|
||||
if [ -f /run/sshd.pid ]; then
|
||||
kill "$(cat /run/sshd.pid)" 2>/dev/null || true
|
||||
fi
|
||||
|
||||
# Wait for processes to terminate.
|
||||
wait
|
||||
}
|
||||
@@ -28,7 +33,8 @@ else
|
||||
echo "Using the default Docker image store."
|
||||
fi
|
||||
|
||||
dind dockerd --host=tcp://0.0.0.0:2375 --tls=false &
|
||||
dind dockerd --host unix:///run/docker.sock --host=tcp://0.0.0.0:2375 --tls=false &
|
||||
/usr/sbin/sshd -o AllowTcpForwarding=yes
|
||||
|
||||
# Execute the passed command and wait for it while maintaining signal handling.
|
||||
"$@" &
|
||||
|
||||
@@ -11,9 +11,7 @@ import (
|
||||
"slices"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/api/types/filters"
|
||||
"github.com/docker/docker/pkg/jsonmessage"
|
||||
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
@@ -26,83 +24,20 @@ import (
|
||||
|
||||
"github.com/docker/docker/api/types/image"
|
||||
"github.com/docker/docker/client"
|
||||
"github.com/testcontainers/testcontainers-go"
|
||||
"github.com/testcontainers/testcontainers-go/wait"
|
||||
)
|
||||
|
||||
func TestRegistryPushPull(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
|
||||
// Start unregistry in a Docker-in-Docker container with Docker using containerd image store.
|
||||
req := testcontainers.GenericContainerRequest{
|
||||
ContainerRequest: testcontainers.ContainerRequest{
|
||||
FromDockerfile: testcontainers.FromDockerfile{
|
||||
Context: filepath.Join("..", ".."),
|
||||
Dockerfile: "Dockerfile.test",
|
||||
BuildOptionsModifier: func(buildOptions *types.ImageBuildOptions) {
|
||||
buildOptions.Target = "unregistry-dind"
|
||||
},
|
||||
},
|
||||
Env: map[string]string{
|
||||
"UNREGISTRY_LOG_LEVEL": "debug",
|
||||
},
|
||||
Privileged: true,
|
||||
// Explicitly specify the host port for the registry because if not specified, 'docker push' from Docker
|
||||
// Desktop is unable to reach the automatically mapped one for some reason.
|
||||
ExposedPorts: []string{"2375", "50000:5000"},
|
||||
WaitingFor: wait.ForAll(
|
||||
wait.ForListeningPort("2375"),
|
||||
wait.ForListeningPort("5000"),
|
||||
).WithStartupTimeoutDefault(15 * time.Second),
|
||||
},
|
||||
Started: true,
|
||||
}
|
||||
unregistryContainer, err := testcontainers.GenericContainer(ctx, req)
|
||||
require.NoError(t, err)
|
||||
|
||||
t.Cleanup(func() {
|
||||
// Print last 20 lines of unregistry container logs.
|
||||
logs, err := unregistryContainer.Logs(ctx)
|
||||
assert.NoError(t, err, "Failed to get logs from unregistry container.")
|
||||
if err == nil {
|
||||
defer logs.Close()
|
||||
logsContent, err := io.ReadAll(logs)
|
||||
assert.NoError(t, err, "Failed to read logs from unregistry container.")
|
||||
if err == nil {
|
||||
|
||||
lines := strings.Split(string(logsContent), "\n")
|
||||
start := len(lines) - 20
|
||||
if start < 0 {
|
||||
start = 0
|
||||
}
|
||||
|
||||
t.Log("=== Last 20 lines of unregistry container logs ===")
|
||||
for i := start; i < len(lines); i++ {
|
||||
if lines[i] != "" {
|
||||
t.Log(lines[i])
|
||||
}
|
||||
}
|
||||
t.Log("=== End of unregistry container logs ===")
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure the container is terminated after the test.
|
||||
assert.NoError(t, unregistryContainer.Terminate(ctx))
|
||||
})
|
||||
|
||||
mappedDockerPort, err := unregistryContainer.MappedPort(ctx, "2375")
|
||||
require.NoError(t, err)
|
||||
mappedRegistryPort, err := unregistryContainer.MappedPort(ctx, "5000")
|
||||
require.NoError(t, err)
|
||||
mappedDockerPort, mappedRegistryPort := runUnregistryDinD(t, true)
|
||||
|
||||
remoteCli, err := client.NewClientWithOpts(
|
||||
client.WithHost("tcp://localhost:"+mappedDockerPort.Port()),
|
||||
client.WithHost("tcp://localhost:"+mappedDockerPort),
|
||||
client.WithAPIVersionNegotiation(),
|
||||
)
|
||||
require.NoError(t, err)
|
||||
defer remoteCli.Close()
|
||||
|
||||
registryAddr := "localhost:" + mappedRegistryPort.Port()
|
||||
registryAddr := "localhost:" + mappedRegistryPort
|
||||
t.Logf("Unregistry started at %s", registryAddr)
|
||||
|
||||
localCli, err := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation())
|
||||
|
||||
7
test/e2e/ssh/test_key
Normal file
7
test/e2e/ssh/test_key
Normal file
@@ -0,0 +1,7 @@
|
||||
-----BEGIN OPENSSH PRIVATE KEY-----
|
||||
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW
|
||||
QyNTUxOQAAACBS9CsZhkOgawNzvNPRSIOJiKhz9xEqUkPGeMGXZV2UmQAAAJBT8W4dU/Fu
|
||||
HQAAAAtzc2gtZWQyNTUxOQAAACBS9CsZhkOgawNzvNPRSIOJiKhz9xEqUkPGeMGXZV2UmQ
|
||||
AAAECiXqC92PMhl7Xe1TtjWTVtd9r+PORzw4iGLmdzmbwE9FL0KxmGQ6BrA3O809FIg4mI
|
||||
qHP3ESpSQ8Z4wZdlXZSZAAAACGUyZUB0ZXN0AQIDBAU=
|
||||
-----END OPENSSH PRIVATE KEY-----
|
||||
1
test/e2e/ssh/test_key.pub
Normal file
1
test/e2e/ssh/test_key.pub
Normal file
@@ -0,0 +1 @@
|
||||
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIFL0KxmGQ6BrA3O809FIg4mIqHP3ESpSQ8Z4wZdlXZSZ e2e@test
|
||||
87
test/e2e/unregistry.go
Normal file
87
test/e2e/unregistry.go
Normal file
@@ -0,0 +1,87 @@
|
||||
package e2e
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"github.com/testcontainers/testcontainers-go"
|
||||
"github.com/testcontainers/testcontainers-go/wait"
|
||||
)
|
||||
|
||||
// runUnregistryDinD starts unregistry in a Docker-in-Docker container. It returns the mapped Docker
|
||||
// port and the mapped unregistry port. The containerdStore parameter specifies whether to use containerd image store.
|
||||
func runUnregistryDinD(t *testing.T, containerdStore bool) (string, string) {
|
||||
ctx := context.Background()
|
||||
// Start unregistry in a Docker-in-Docker container with Docker using containerd image store.
|
||||
req := testcontainers.GenericContainerRequest{
|
||||
ContainerRequest: testcontainers.ContainerRequest{
|
||||
FromDockerfile: testcontainers.FromDockerfile{
|
||||
Context: filepath.Join("..", ".."),
|
||||
Dockerfile: "Dockerfile.test",
|
||||
BuildOptionsModifier: func(buildOptions *types.ImageBuildOptions) {
|
||||
buildOptions.Target = "unregistry-dind"
|
||||
},
|
||||
},
|
||||
Env: map[string]string{
|
||||
"DOCKER_CONTAINERD_STORE": fmt.Sprintf("%t", containerdStore),
|
||||
"UNREGISTRY_LOG_LEVEL": "debug",
|
||||
},
|
||||
Privileged: true,
|
||||
// Explicitly specify the host port for the registry because if not specified, 'docker push' from Docker
|
||||
// Desktop is unable to reach the automatically mapped one for some reason.
|
||||
ExposedPorts: []string{"2375", "50000:5000"},
|
||||
WaitingFor: wait.ForAll(
|
||||
wait.ForListeningPort("2375"),
|
||||
wait.ForListeningPort("5000"),
|
||||
).WithStartupTimeoutDefault(15 * time.Second),
|
||||
},
|
||||
Started: true,
|
||||
}
|
||||
ctr, err := testcontainers.GenericContainer(ctx, req)
|
||||
require.NoError(t, err)
|
||||
|
||||
t.Cleanup(func() {
|
||||
// Print last 20 lines of unregistry container logs.
|
||||
logs, err := ctr.Logs(ctx)
|
||||
assert.NoError(t, err, "Failed to get logs from unregistry container.")
|
||||
if err == nil {
|
||||
defer logs.Close()
|
||||
logsContent, err := io.ReadAll(logs)
|
||||
assert.NoError(t, err, "Failed to read logs from unregistry container.")
|
||||
if err == nil {
|
||||
|
||||
lines := strings.Split(string(logsContent), "\n")
|
||||
start := len(lines) - 20
|
||||
if start < 0 {
|
||||
start = 0
|
||||
}
|
||||
|
||||
t.Log("=== Last 20 lines of unregistry container logs ===")
|
||||
for i := start; i < len(lines); i++ {
|
||||
if lines[i] != "" {
|
||||
t.Log(lines[i])
|
||||
}
|
||||
}
|
||||
t.Log("=== End of unregistry container logs ===")
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure the container is terminated after the test.
|
||||
assert.NoError(t, ctr.Terminate(ctx))
|
||||
})
|
||||
|
||||
mappedDockerPort, err := ctr.MappedPort(ctx, "2375")
|
||||
require.NoError(t, err)
|
||||
mappedRegistryPort, err := ctr.MappedPort(ctx, "5000")
|
||||
require.NoError(t, err)
|
||||
|
||||
return mappedDockerPort.Port(), mappedRegistryPort.Port()
|
||||
}
|
||||
Reference in New Issue
Block a user