docker_test.go 3.0 KB

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