diff --git a/runnable-mail_test.go b/runnable-mail_test.go index ecdf3e4bce037549f4295458b16283e3d42a2cee..11f509a60fcd48882087279a71d85310154f98e2 100644 --- a/runnable-mail_test.go +++ b/runnable-mail_test.go @@ -3,150 +3,112 @@ package jobqueue import ( "context" "fmt" + "github.com/docker/docker/api/types" + "github.com/docker/docker/api/types/container" + "github.com/docker/docker/client" "github.com/docker/go-connections/nat" "github.com/stretchr/testify/assert" "net" + "os" "testing" "time" ) -func startTestSMTPDockerImageAndContainer(t *testing.T, ctx context.Context) (*mockPortContainer, error) { +const DOCKER_TEST_HOST_IP = "127.0.0.1" + +func startTestSMTPDockerImageAndContainer(t *testing.T, port string, ctx context.Context) error { t.Helper() - mc := &mockPortContainer{} + cli, err := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation()) + if err != nil { + return err + } - smtpPortMap := nat.PortMap{ - "1025/tcp": []nat.PortBinding{ - { - HostIP: "0.0.0.0", - HostPort: "", - }, - }, - "8025/tcp": []nat.PortBinding{ - { - HostIP: "0.0.0.0", - HostPort: "8025", - }, - }, + imageName := "axllent/mailpit" + + reader, err := cli.ImagePull(ctx, imageName, types.ImagePullOptions{}) + if err != nil { + return err } - mr := &mockRunnable{ - ctx: ctx, - imageName: "axllent/mailpit", - portMap: smtpPortMap, - cmd: []string{}, - volume: "", - t: t, + // if debug image pull, comment out the following lines + //_, _ = io.Copy(os.Stdout, reader) + _ = reader + + hostConfig := &container.HostConfig{ + PortBindings: nat.PortMap{ + "1025/tcp": []nat.PortBinding{ + { + HostIP: DOCKER_TEST_HOST_IP, + HostPort: port, + }, + }, + // if you want to test the web interface, uncomment the following lines + //"8025/tcp": []nat.PortBinding{ + // { + // HostIP: DOCKER_TEST_HOST_IP, + // HostPort: "8025", + // }, + //}, + }, } - smtpPorts, err := mr.startTestDockerImageAndContainer() + resp, err := cli.ContainerCreate(ctx, &container.Config{ + Image: imageName, + }, hostConfig, nil, nil, "") if err != nil { - return mc, err + return err + } + + if err := cli.ContainerStart(ctx, resp.ID, types.ContainerStartOptions{}); err != nil { + return err } - pp := *smtpPorts + go func() { + <-ctx.Done() + + timeout := 0 + stopOptions := container.StopOptions{ + Timeout: &timeout, + Signal: "SIGKILL", + } + newCtx, _ := context.WithTimeout(context.Background(), 60*time.Second) + if err := cli.ContainerStop(newCtx, resp.ID, stopOptions); err != nil { + t.Errorf("ContainerStop returned error: %v", err) + } + if err := cli.ContainerRemove(newCtx, resp.ID, types.ContainerRemoveOptions{ + Force: true, + }); err != nil { + t.Errorf("ContainerRemove returned error: %v", err) + } + + }() + + statusCh, errCh := cli.ContainerWait(ctx, resp.ID, container.WaitConditionNotRunning) + select { + case err := <-errCh: + if err != nil { + // empty error means container exited normally (see container_wait.go) + if err.Error() == "" { + return nil + } + + return err + } + case <-statusCh: - px, ok := pp["1025/tcp"] - if !ok { - return mc, fmt.Errorf("1025/tcp port not found") } - smtpPort := px[0].HostPort - - mc.setPort(smtpPort) - - return mc, nil - - //cli, err := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation()) - //if err != nil { - // return err - //} - // - //imageName := "axllent/mailpit" - // - //reader, err := cli.ImagePull(ctx, imageName, types.ImagePullOptions{}) - //if err != nil { - // return err - //} - // - //// if debug image pull, comment out the following lines - ////_, _ = io.Copy(os.Stdout, reader) - //_ = reader - // - //host, _, _ := net.SplitHostPort(cli.DaemonHost()) - //if host == "" || host == "unix" { - // host = DOCKER_TEST_HOST_IP - //} - // - //hostConfig := &container.HostConfig{ - // PortBindings: nat.PortMap{ - // "1025/tcp": []nat.PortBinding{ - // { - // HostIP: host, - // HostPort: port, - // }, - // }, - // "8025/tcp": []nat.PortBinding{ - // { - // HostIP: host, - // HostPort: "8025", - // }, - // }, - // }, - //} - // - //resp, err := cli.ContainerCreate(ctx, &container.Config{ - // Image: imageName, - //}, hostConfig, nil, nil, "") - // - //if err != nil { - // return err - //} - // - //if err := cli.ContainerStart(ctx, resp.ID, types.ContainerStartOptions{}); err != nil { - // return err - //} - // - //go func() { - // <-ctx.Done() - // - // timeout := 0 - // stopOptions := container.StopOptions{ - // Timeout: &timeout, - // Signal: "SIGKILL", - // } - // newCtx, _ := context.WithTimeout(context.Background(), 60*time.Second) - // if err := cli.ContainerStop(newCtx, resp.ID, stopOptions); err != nil { - // t.Errorf("ContainerStop returned error: %v", err) - // } - // if err := cli.ContainerRemove(newCtx, resp.ID, types.ContainerRemoveOptions{ - // Force: true, - // }); err != nil { - // t.Errorf("ContainerRemove returned error: %v", err) - // } - // - //}() - // - //statusCh, errCh := cli.ContainerWait(ctx, resp.ID, container.WaitConditionNotRunning) - //select { - //case err := <-errCh: - // if err != nil { - // // empty error means container exited normally (see container_wait.go) - // if err.Error() == "" { - // return nil - // } - // - // return err - // } - //case <-statusCh: - // - //} - // - //return nil + return nil } func TestMailRunner(t *testing.T) { + if os.Getenv("CI_SERVER") != "" { + t.Skip("Skipping test because CI_SERVER is set") + // TODO: run this test in CI + } + ctb := context.Background() ctx, cancel := context.WithCancel(ctb) t.Cleanup(func() { @@ -154,32 +116,29 @@ func TestMailRunner(t *testing.T) { time.Sleep(1 * time.Second) }) - //listener, err := net.Listen("tcp", DOCKER_TEST_HOST_IP+":0") - //if err != nil { - // t.Errorf("Unexpected error: %v", err) - // return - //} - //portAsInt := listener.Addr().(*net.TCPAddr).Port - //portAsString := fmt.Sprintf("%d", portAsInt) - //_ = listener.Close() - - var pc *mockPortContainer - var err error - - done := make(chan bool) - //go func() { - pc, err = startTestSMTPDockerImageAndContainer(t, ctx) + listener, err := net.Listen("tcp", DOCKER_TEST_HOST_IP+":0") if err != nil { t.Errorf("Unexpected error: %v", err) - cancel() + return } - done <- true - //}() + portAsInt := listener.Addr().(*net.TCPAddr).Port + portAsString := fmt.Sprintf("%d", portAsInt) + _ = listener.Close() + + done := make(chan bool) + go func() { + err = startTestSMTPDockerImageAndContainer(t, portAsString, ctx) + if err != nil { + t.Errorf("Unexpected error: %v", err) + cancel() + } + done <- true + }() waitCtx, waitCancel := context.WithTimeout(ctx, 60*time.Second) defer waitCancel() for { - conn, err := net.DialTimeout("tcp", net.JoinHostPort(DOCKER_TEST_HOST_IP, pc.getPort()), 1*time.Second) + conn, err := net.DialTimeout("tcp", net.JoinHostPort(DOCKER_TEST_HOST_IP, portAsString), 1*time.Second) if err == nil { err = conn.Close() assert.Nil(t, err) @@ -203,7 +162,7 @@ func TestMailRunner(t *testing.T) { Subject: "this is a test", Body: "this is the body", Server: DOCKER_TEST_HOST_IP, - Port: pc.getPort(), + Port: portAsString, Username: "", Password: "", Headers: map[string]string{ diff --git a/runnable-sftp_test.go b/runnable-sftp_test.go index df297db5b5759db7dd112c26b3ae2d91b725a53c..6ec2dd31dacdedb42b249255c465c112f5c330cf 100644 --- a/runnable-sftp_test.go +++ b/runnable-sftp_test.go @@ -3,155 +3,108 @@ package jobqueue import ( "context" "fmt" + "github.com/docker/docker/api/types" + "github.com/docker/docker/api/types/container" + "github.com/docker/docker/client" "github.com/docker/go-connections/nat" "github.com/stretchr/testify/assert" "net" "os" - "strconv" "testing" "time" ) -func startSFTPTestDockerImageAndContainer(t *testing.T, volumePath string, ctx context.Context) (string, error) { +func startSFTPTestDockerImageAndContainer(t *testing.T, host string, port string, volume string, ctx context.Context) error { t.Helper() - sftpPortMap := nat.PortMap{ - "22/tcp": []nat.PortBinding{ - { - HostIP: "0.0.0.0", - HostPort: "", + cli, err := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation()) + if err != nil { + return err + } + + imageName := "atmoz/sftp:alpine" + + reader, err := cli.ImagePull(ctx, imageName, types.ImagePullOptions{}) + if err != nil { + return err + } + + //if debug image pull, comment out the following lines + //_, _ = io.Copy(os.Stdout, reader) + _ = reader + + hostConfig := &container.HostConfig{ + PortBindings: nat.PortMap{ + "22/tcp": []nat.PortBinding{ + { + HostIP: host, + HostPort: port, + }, }, }, } - sftpCmd := []string{"demo:secret:::upload"} - sftpVolume := volumePath // Ihr Volume hier - - mr := &mockRunnable{ - ctx: ctx, - imageName: "atmoz/sftp:alpine", - portMap: sftpPortMap, - cmd: sftpCmd, - volume: sftpVolume, - t: t, + if volume != "" { + hostConfig.Binds = append(hostConfig.Binds, volume+":/home/demo/upload") } - sftpPorts, err := mr.startTestDockerImageAndContainer() + resp, err := cli.ContainerCreate(ctx, &container.Config{ + Image: imageName, + Cmd: []string{"demo:secret:::upload"}, + }, hostConfig, nil, nil, "") + if err != nil { - return "", err + return err } - pp := *sftpPorts - px, ok := pp["22/tcp"] - if !ok { - return "", fmt.Errorf("22/tcp port not found") + if err := cli.ContainerStart(ctx, resp.ID, types.ContainerStartOptions{}); err != nil { + return err } - return px[0].HostPort, nil - // - //sshPorts, ok := sftpPorts["22/tcp"] - //if !ok { - // return "", fmt.Errorf("22/tcp port not found") - //} - // - //sshPort, ok := sshPorts[0].HostPort - //if !ok { - // return "", fmt.Errorf("22/tcp port not found") - //} - // - //// check if port is open - //return sshPort, nil - - //t.Helper() - // - //cli, err := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation()) - //if err != nil { - // return err - //} - // - //imageName := "atmoz/sftp:alpine" - // - //reader, err := cli.ImagePull(ctx, imageName, types.ImagePullOptions{}) - //if err != nil { - // return err - //} - // - ////if debug image pull, comment out the following lines - ////_, _ = io.Copy(os.Stdout, reader) - //_ = reader - // - //host, _, _ := net.SplitHostPort(cli.DaemonHost()) - //if host == "" || host == "unix" { - // host = DOCKER_TEST_HOST_IP - //} - // - //hostConfig := &container.HostConfig{ - // PortBindings: nat.PortMap{ - // "22/tcp": []nat.PortBinding{ - // { - // HostIP: host, - // HostPort: port, - // }, - // }, - // }, - //} - // - //if volume != "" { - // hostConfig.Binds = append(hostConfig.Binds, volume+":/home/demo/upload") - //} - // - //resp, err := cli.ContainerCreate(ctx, &container.Config{ - // Image: imageName, - // Cmd: []string{"demo:secret:::upload"}, - //}, hostConfig, nil, nil, "") - // - //if err != nil { - // return err - //} - // - //if err := cli.ContainerStart(ctx, resp.ID, types.ContainerStartOptions{}); err != nil { - // return err - //} - // - //go func() { - // <-ctx.Done() - // - // timeout := 0 - // stopOptions := container.StopOptions{ - // Timeout: &timeout, - // Signal: "SIGKILL", - // } - // newCtx, _ := context.WithTimeout(context.Background(), 60*time.Second) - // if err := cli.ContainerStop(newCtx, resp.ID, stopOptions); err != nil { - // t.Errorf("ContainerStop returned error: %v", err) - // } - // if err := cli.ContainerRemove(newCtx, resp.ID, types.ContainerRemoveOptions{ - // Force: true, - // }); err != nil { - // t.Errorf("ContainerRemove returned error: %v", err) - // } - // - //}() - // - //statusCh, errCh := cli.ContainerWait(ctx, resp.ID, container.WaitConditionNotRunning) - //select { - //case err := <-errCh: - // if err != nil { - // // empty error means container exited normally (see container_wait.go) - // if err.Error() == "" { - // return nil - // } - // - // return err - // } - //case <-statusCh: - // - //} - // - //return nil + go func() { + <-ctx.Done() + + timeout := 0 + stopOptions := container.StopOptions{ + Timeout: &timeout, + Signal: "SIGKILL", + } + newCtx, _ := context.WithTimeout(context.Background(), 60*time.Second) + if err := cli.ContainerStop(newCtx, resp.ID, stopOptions); err != nil { + t.Errorf("ContainerStop returned error: %v", err) + } + if err := cli.ContainerRemove(newCtx, resp.ID, types.ContainerRemoveOptions{ + Force: true, + }); err != nil { + t.Errorf("ContainerRemove returned error: %v", err) + } + + }() + + statusCh, errCh := cli.ContainerWait(ctx, resp.ID, container.WaitConditionNotRunning) + select { + case err := <-errCh: + if err != nil { + // empty error means container exited normally (see container_wait.go) + if err.Error() == "" { + return nil + } + + return err + } + case <-statusCh: + + } + + return nil } func TestSFTPCRunnerLocalToRemote(t *testing.T) { + if os.Getenv("CI_SERVER") != "" { + t.Skip("Skipping test because CI_SERVER is set") + // TODO: run this test in CI + } + ctb := context.Background() ctx, cancel := context.WithCancel(ctb) t.Cleanup(func() { @@ -159,21 +112,20 @@ func TestSFTPCRunnerLocalToRemote(t *testing.T) { time.Sleep(1 * time.Second) }) - //listener, err := net.Listen("tcp", DOCKER_TEST_HOST_IP+":0") - //if err != nil { - // t.Errorf("Unexpected error: %v", err) - // return - //} - //portAsInt := listener.Addr().(*net.TCPAddr).Port - //portAsString := fmt.Sprintf("%d", portAsInt) - //_ = listener.Close() + host := "0.0.0.0" - var portAsString string - var err error + listener, err := net.Listen("tcp", host+":0") + if err != nil { + t.Errorf("Unexpected error: %v", err) + return + } + portAsInt := listener.Addr().(*net.TCPAddr).Port + portAsString := fmt.Sprintf("%d", portAsInt) + _ = listener.Close() done := make(chan bool) go func() { - portAsString, err = startSFTPTestDockerImageAndContainer(t, "", ctx) + err = startSFTPTestDockerImageAndContainer(t, host, portAsString, "", ctx) if err != nil { t.Errorf("Unexpected error: %v", err) cancel() @@ -184,7 +136,7 @@ func TestSFTPCRunnerLocalToRemote(t *testing.T) { waitCtx, waitCancel := context.WithTimeout(ctx, 60*time.Second) defer waitCancel() for { - conn, err := net.DialTimeout("tcp", net.JoinHostPort(DOCKER_TEST_HOST_IP, portAsString), 1*time.Second) + conn, err := net.DialTimeout("tcp", net.JoinHostPort(host, portAsString), 1*time.Second) if err == nil { err = conn.Close() assert.Nil(t, err) @@ -212,10 +164,8 @@ func TestSFTPCRunnerLocalToRemote(t *testing.T) { } } - portAsInt, err := strconv.Atoi(portAsString) - sftpRunnable := &SFTPRunnable{ - Host: DOCKER_TEST_HOST_IP, + Host: host, Port: portAsInt, User: "demo", Insecure: true, @@ -263,14 +213,16 @@ func TestSFTPCRunnerRemoteToLocal(t *testing.T) { time.Sleep(1 * time.Second) }) - //listener, err := net.Listen("tcp", DOCKER_TEST_HOST_IP+":0") - //if err != nil { - // t.Errorf("Unexpected error: %v", err) - // return - //} - //portAsInt := listener.Addr().(*net.TCPAddr).Port - //portAsString := fmt.Sprintf("%d", portAsInt) - //_ = listener.Close() + host := "127.0.0.1" + + listener, err := net.Listen("tcp", host+":0") + if err != nil { + t.Errorf("Unexpected error: %v", err) + return + } + portAsInt := listener.Addr().(*net.TCPAddr).Port + portAsString := fmt.Sprintf("%d", portAsInt) + _ = listener.Close() tempSrcDir := t.TempDir() // create 4 test files @@ -282,26 +234,20 @@ func TestSFTPCRunnerRemoteToLocal(t *testing.T) { } } - var mpContainer mockPortContainer - var err error - done := make(chan bool) go func() { - portAsString, err := startSFTPTestDockerImageAndContainer(t, tempSrcDir, ctx) + err = startSFTPTestDockerImageAndContainer(t, host, portAsString, tempSrcDir, ctx) if err != nil { t.Errorf("Unexpected error: %v", err) cancel() } - - mpContainer.setPort(portAsString) - done <- true }() waitCtx, waitCancel := context.WithTimeout(ctx, 60*time.Second) defer waitCancel() for { - conn, err := net.DialTimeout("tcp", net.JoinHostPort(DOCKER_TEST_HOST_IP, mpContainer.getPort()), 1*time.Second) + conn, err := net.DialTimeout("tcp", net.JoinHostPort(host, portAsString), 1*time.Second) if err == nil { err = conn.Close() assert.Nil(t, err) @@ -321,10 +267,8 @@ func TestSFTPCRunnerRemoteToLocal(t *testing.T) { tempDir := t.TempDir() - portAsInt := mpContainer.getPortAsInt() - sftpRunnable := &SFTPRunnable{ - Host: DOCKER_TEST_HOST_IP, + Host: host, Port: portAsInt, User: "demo", Insecure: true, diff --git a/utils.go b/utils.go deleted file mode 100644 index 62ddc89a6af9d2da3485ec93d9f16bac3ac93fae..0000000000000000000000000000000000000000 --- a/utils.go +++ /dev/null @@ -1,129 +0,0 @@ -package jobqueue - -import ( - "context" - "github.com/docker/docker/api/types" - "github.com/docker/docker/api/types/container" - "github.com/docker/docker/client" - "github.com/docker/go-connections/nat" - "strconv" - "sync" - "testing" - "time" -) - -const ( - DOCKER_TEST_HOST_IP = "172.17.0.1" -) - -type mockPortContainer struct { - mu sync.Mutex - port string -} - -func (mp *mockPortContainer) getPort() string { - mp.mu.Lock() - defer mp.mu.Unlock() - return mp.port -} - -func (mp *mockPortContainer) setPort(port string) { - mp.mu.Lock() - defer mp.mu.Unlock() - mp.port = port -} - -func (mp *mockPortContainer) getPortAsInt() int { - mp.mu.Lock() - defer mp.mu.Unlock() - port, _ := strconv.Atoi(mp.port) - return port -} - -type mockRunnable struct { - mu sync.Mutex - ctx context.Context - imageName string - portMap nat.PortMap - cmd []string - volume string - t *testing.T - hostPort string - creatVol bool -} - -func (mr *mockRunnable) startTestDockerImageAndContainer() (*nat.PortMap, error) { - mr.mu.Lock() - defer mr.mu.Unlock() - - t := mr.t - t.Helper() - - ctx := mr.ctx - imageName := mr.imageName - portMap := mr.portMap - cmd := mr.cmd - volPath := mr.volume - - cli, err := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation()) - if err != nil { - return nil, err - } - - reader, err := cli.ImagePull(ctx, imageName, types.ImagePullOptions{}) - if err != nil { - return nil, err - } - _ = reader - - //host, _, _ := net.SplitHostPort(cli.DaemonHost()) - //if host == "" || host == "unix" { - // host = DOCKER_TEST_HOST_IP - //} - - hostConfig := &container.HostConfig{ - PortBindings: portMap, - } - - if volPath != "" { - hostConfig.Binds = append(hostConfig.Binds, volPath+":/home/demo/upload") - } - - resp, err := cli.ContainerCreate(ctx, &container.Config{ - Image: imageName, - Cmd: cmd, - }, hostConfig, nil, nil, "") - - if err != nil { - return nil, err - } - - if err := cli.ContainerStart(ctx, resp.ID, types.ContainerStartOptions{}); err != nil { - return nil, err - } - - go func() { - <-ctx.Done() - - timeout := 0 - stopOptions := container.StopOptions{ - Timeout: &timeout, - } - newCtx, _ := context.WithTimeout(context.Background(), 60*time.Second) - if err := cli.ContainerStop(newCtx, resp.ID, stopOptions); err != nil { - t.Errorf("ContainerStop returned error: %v", err) - } - if err := cli.ContainerRemove(newCtx, resp.ID, types.ContainerRemoveOptions{ - Force: true, - }); err != nil { - t.Errorf("ContainerRemove returned error: %v", err) - } - }() - - inspected, err := cli.ContainerInspect(ctx, resp.ID) - if err != nil { - return nil, err - } - - return &inspected.NetworkSettings.Ports, nil -}