docker_test.go 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
  1. package main
  2. import (
  3. "context"
  4. "testing"
  5. "time"
  6. F "github.com/sagernet/sing/common/format"
  7. "github.com/docker/docker/api/types"
  8. "github.com/docker/docker/api/types/container"
  9. "github.com/docker/docker/client"
  10. "github.com/docker/go-connections/nat"
  11. "github.com/stretchr/testify/require"
  12. )
  13. type DockerOptions struct {
  14. Image string
  15. EntryPoint string
  16. Ports []uint16
  17. Cmd []string
  18. Env []string
  19. Bind []string
  20. Stdin []byte
  21. }
  22. func startDockerContainer(t *testing.T, options DockerOptions) {
  23. dockerClient, err := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation())
  24. require.NoError(t, err)
  25. defer dockerClient.Close()
  26. writeStdin := len(options.Stdin) > 0
  27. var containerOptions container.Config
  28. if writeStdin {
  29. containerOptions.OpenStdin = true
  30. containerOptions.StdinOnce = true
  31. }
  32. containerOptions.Image = options.Image
  33. if options.EntryPoint != "" {
  34. containerOptions.Entrypoint = []string{options.EntryPoint}
  35. }
  36. containerOptions.Cmd = options.Cmd
  37. containerOptions.Env = options.Env
  38. containerOptions.ExposedPorts = make(nat.PortSet)
  39. var hostOptions container.HostConfig
  40. if !isDarwin {
  41. hostOptions.NetworkMode = "host"
  42. }
  43. hostOptions.PortBindings = make(nat.PortMap)
  44. for _, port := range options.Ports {
  45. containerOptions.ExposedPorts[nat.Port(F.ToString(port, "/tcp"))] = struct{}{}
  46. containerOptions.ExposedPorts[nat.Port(F.ToString(port, "/udp"))] = struct{}{}
  47. hostOptions.PortBindings[nat.Port(F.ToString(port, "/tcp"))] = []nat.PortBinding{
  48. {HostPort: F.ToString(port), HostIP: "0.0.0.0"},
  49. }
  50. hostOptions.PortBindings[nat.Port(F.ToString(port, "/udp"))] = []nat.PortBinding{
  51. {HostPort: F.ToString(port), HostIP: "0.0.0.0"},
  52. }
  53. }
  54. dockerContainer, err := dockerClient.ContainerCreate(context.Background(), &containerOptions, &hostOptions, nil, nil, "")
  55. require.NoError(t, err)
  56. t.Cleanup(func() {
  57. cleanContainer(dockerContainer.ID)
  58. })
  59. require.NoError(t, dockerClient.ContainerStart(context.Background(), dockerContainer.ID, types.ContainerStartOptions{}))
  60. if writeStdin {
  61. stdinAttach, err := dockerClient.ContainerAttach(context.Background(), dockerContainer.ID, types.ContainerAttachOptions{
  62. Stdin: writeStdin,
  63. Stream: true,
  64. })
  65. require.NoError(t, err)
  66. _, err = stdinAttach.Conn.Write(options.Stdin)
  67. require.NoError(t, err)
  68. stdinAttach.Close()
  69. }
  70. /*attach, err := dockerClient.ContainerAttach(context.Background(), dockerContainer.ID, types.ContainerAttachOptions{
  71. Stdout: true,
  72. Stderr: true,
  73. Logs: true,
  74. Stream: true,
  75. })
  76. require.NoError(t, err)
  77. go func() {
  78. stdcopy.StdCopy(os.Stderr, os.Stderr, attach.Reader)
  79. }()*/
  80. time.Sleep(time.Second)
  81. }
  82. func cleanContainer(id string) error {
  83. dockerClient, err := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation())
  84. if err != nil {
  85. return err
  86. }
  87. defer dockerClient.Close()
  88. return dockerClient.ContainerRemove(context.Background(), id, types.ContainerRemoveOptions{Force: true})
  89. }