|
@@ -1,16 +1,22 @@
|
|
|
package daemon // import "github.com/docker/docker/integration/daemon"
|
|
|
|
|
|
import (
|
|
|
+ "context"
|
|
|
+ "fmt"
|
|
|
+ "net/http"
|
|
|
+ "net/http/httptest"
|
|
|
"os"
|
|
|
"os/exec"
|
|
|
"path/filepath"
|
|
|
"runtime"
|
|
|
"testing"
|
|
|
|
|
|
+ "github.com/docker/docker/api/types"
|
|
|
"github.com/docker/docker/daemon/config"
|
|
|
"github.com/docker/docker/testutil/daemon"
|
|
|
"gotest.tools/v3/assert"
|
|
|
is "gotest.tools/v3/assert/cmp"
|
|
|
+ "gotest.tools/v3/env"
|
|
|
"gotest.tools/v3/skip"
|
|
|
)
|
|
|
|
|
@@ -146,3 +152,150 @@ func TestConfigDaemonSeccompProfiles(t *testing.T) {
|
|
|
})
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
+func TestDaemonProxy(t *testing.T) {
|
|
|
+ skip.If(t, runtime.GOOS == "windows", "cannot start multiple daemons on windows")
|
|
|
+
|
|
|
+ var received string
|
|
|
+ proxyServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
|
+ received = r.Host
|
|
|
+ w.Header().Set("Content-Type", "application/json")
|
|
|
+ _, _ = w.Write([]byte("OK"))
|
|
|
+ }))
|
|
|
+ defer proxyServer.Close()
|
|
|
+
|
|
|
+ // Configure proxy through env-vars
|
|
|
+ t.Run("environment variables", func(t *testing.T) {
|
|
|
+ defer env.Patch(t, "HTTP_PROXY", proxyServer.URL)()
|
|
|
+ defer env.Patch(t, "HTTPS_PROXY", proxyServer.URL)()
|
|
|
+ defer env.Patch(t, "NO_PROXY", "example.com")()
|
|
|
+
|
|
|
+ d := daemon.New(t)
|
|
|
+ c := d.NewClientT(t)
|
|
|
+ defer func() { _ = c.Close() }()
|
|
|
+ ctx := context.Background()
|
|
|
+ d.Start(t)
|
|
|
+
|
|
|
+ _, err := c.ImagePull(ctx, "example.org:5000/some/image:latest", types.ImagePullOptions{})
|
|
|
+ assert.ErrorContains(t, err, "", "pulling should have failed")
|
|
|
+ assert.Equal(t, received, "example.org:5000")
|
|
|
+
|
|
|
+ // Test NoProxy: example.com should not hit the proxy, and "received" variable should not be changed.
|
|
|
+ _, err = c.ImagePull(ctx, "example.com/some/image:latest", types.ImagePullOptions{})
|
|
|
+ assert.ErrorContains(t, err, "", "pulling should have failed")
|
|
|
+ assert.Equal(t, received, "example.org:5000", "should not have used proxy")
|
|
|
+
|
|
|
+ info := d.Info(t)
|
|
|
+ assert.Equal(t, info.HTTPProxy, proxyServer.URL)
|
|
|
+ assert.Equal(t, info.HTTPSProxy, proxyServer.URL)
|
|
|
+ assert.Equal(t, info.NoProxy, "example.com")
|
|
|
+ d.Stop(t)
|
|
|
+ })
|
|
|
+
|
|
|
+ // Configure proxy through command-line flags
|
|
|
+ t.Run("command-line options", func(t *testing.T) {
|
|
|
+ defer env.Patch(t, "HTTP_PROXY", "http://from-env-http.invalid")()
|
|
|
+ defer env.Patch(t, "http_proxy", "http://from-env-http.invalid")()
|
|
|
+ defer env.Patch(t, "HTTPS_PROXY", "https://from-env-https.invalid")()
|
|
|
+ defer env.Patch(t, "https_proxy", "https://from-env-http.invalid")()
|
|
|
+ defer env.Patch(t, "NO_PROXY", "ignore.invalid")()
|
|
|
+ defer env.Patch(t, "no_proxy", "ignore.invalid")()
|
|
|
+
|
|
|
+ d := daemon.New(t)
|
|
|
+ d.Start(t, "--http-proxy", proxyServer.URL, "--https-proxy", proxyServer.URL, "--no-proxy", "example.com")
|
|
|
+
|
|
|
+ logs, err := d.ReadLogFile()
|
|
|
+ assert.NilError(t, err)
|
|
|
+ assert.Assert(t, is.Contains(string(logs), "overriding existing proxy variable with value from configuration"))
|
|
|
+ for _, v := range []string{"http_proxy", "HTTP_PROXY", "https_proxy", "HTTPS_PROXY", "no_proxy", "NO_PROXY"} {
|
|
|
+ assert.Assert(t, is.Contains(string(logs), "name="+v))
|
|
|
+ }
|
|
|
+
|
|
|
+ c := d.NewClientT(t)
|
|
|
+ defer func() { _ = c.Close() }()
|
|
|
+ ctx := context.Background()
|
|
|
+
|
|
|
+ _, err = c.ImagePull(ctx, "example.org:5001/some/image:latest", types.ImagePullOptions{})
|
|
|
+ assert.ErrorContains(t, err, "", "pulling should have failed")
|
|
|
+ assert.Equal(t, received, "example.org:5001")
|
|
|
+
|
|
|
+ // Test NoProxy: example.com should not hit the proxy, and "received" variable should not be changed.
|
|
|
+ _, err = c.ImagePull(ctx, "example.com/some/image:latest", types.ImagePullOptions{})
|
|
|
+ assert.ErrorContains(t, err, "", "pulling should have failed")
|
|
|
+ assert.Equal(t, received, "example.org:5001", "should not have used proxy")
|
|
|
+
|
|
|
+ info := d.Info(t)
|
|
|
+ assert.Equal(t, info.HTTPProxy, proxyServer.URL)
|
|
|
+ assert.Equal(t, info.HTTPSProxy, proxyServer.URL)
|
|
|
+ assert.Equal(t, info.NoProxy, "example.com")
|
|
|
+
|
|
|
+ d.Stop(t)
|
|
|
+ })
|
|
|
+
|
|
|
+ // Configure proxy through configuration file
|
|
|
+ t.Run("configuration file", func(t *testing.T) {
|
|
|
+ defer env.Patch(t, "HTTP_PROXY", "http://from-env-http.invalid")()
|
|
|
+ defer env.Patch(t, "http_proxy", "http://from-env-http.invalid")()
|
|
|
+ defer env.Patch(t, "HTTPS_PROXY", "https://from-env-https.invalid")()
|
|
|
+ defer env.Patch(t, "https_proxy", "https://from-env-http.invalid")()
|
|
|
+ defer env.Patch(t, "NO_PROXY", "ignore.invalid")()
|
|
|
+ defer env.Patch(t, "no_proxy", "ignore.invalid")()
|
|
|
+
|
|
|
+ d := daemon.New(t)
|
|
|
+ c := d.NewClientT(t)
|
|
|
+ defer func() { _ = c.Close() }()
|
|
|
+ ctx := context.Background()
|
|
|
+
|
|
|
+ configFile := filepath.Join(d.RootDir(), "daemon.json")
|
|
|
+ configJSON := fmt.Sprintf(`{"http-proxy":%[1]q, "https-proxy": %[1]q, "no-proxy": "example.com"}`, proxyServer.URL)
|
|
|
+ assert.NilError(t, os.WriteFile(configFile, []byte(configJSON), 0644))
|
|
|
+
|
|
|
+ d.Start(t, "--config-file", configFile)
|
|
|
+
|
|
|
+ logs, err := d.ReadLogFile()
|
|
|
+ assert.NilError(t, err)
|
|
|
+ assert.Assert(t, is.Contains(string(logs), "overriding existing proxy variable with value from configuration"))
|
|
|
+ for _, v := range []string{"http_proxy", "HTTP_PROXY", "https_proxy", "HTTPS_PROXY", "no_proxy", "NO_PROXY"} {
|
|
|
+ assert.Assert(t, is.Contains(string(logs), "name="+v))
|
|
|
+ }
|
|
|
+
|
|
|
+ _, err = c.ImagePull(ctx, "example.org:5002/some/image:latest", types.ImagePullOptions{})
|
|
|
+ assert.ErrorContains(t, err, "", "pulling should have failed")
|
|
|
+ assert.Equal(t, received, "example.org:5002")
|
|
|
+
|
|
|
+ // Test NoProxy: example.com should not hit the proxy, and "received" variable should not be changed.
|
|
|
+ _, err = c.ImagePull(ctx, "example.com/some/image:latest", types.ImagePullOptions{})
|
|
|
+ assert.ErrorContains(t, err, "", "pulling should have failed")
|
|
|
+ assert.Equal(t, received, "example.org:5002", "should not have used proxy")
|
|
|
+
|
|
|
+ info := d.Info(t)
|
|
|
+ assert.Equal(t, info.HTTPProxy, proxyServer.URL)
|
|
|
+ assert.Equal(t, info.HTTPSProxy, proxyServer.URL)
|
|
|
+ assert.Equal(t, info.NoProxy, "example.com")
|
|
|
+
|
|
|
+ d.Stop(t)
|
|
|
+ })
|
|
|
+
|
|
|
+ // Conflicting options (passed both through command-line options and config file)
|
|
|
+ t.Run("conflicting options", func(t *testing.T) {
|
|
|
+ const (
|
|
|
+ proxyRawURL = "https://myuser:mypassword@example.org"
|
|
|
+ )
|
|
|
+
|
|
|
+ d := daemon.New(t)
|
|
|
+
|
|
|
+ configFile := filepath.Join(d.RootDir(), "daemon.json")
|
|
|
+ configJSON := fmt.Sprintf(`{"http-proxy":%[1]q, "https-proxy": %[1]q, "no-proxy": "example.com"}`, proxyRawURL)
|
|
|
+ assert.NilError(t, os.WriteFile(configFile, []byte(configJSON), 0644))
|
|
|
+
|
|
|
+ err := d.StartWithError("--http-proxy", proxyRawURL, "--https-proxy", proxyRawURL, "--no-proxy", "example.com", "--config-file", configFile, "--validate")
|
|
|
+ assert.ErrorContains(t, err, "daemon exited during startup")
|
|
|
+ logs, err := d.ReadLogFile()
|
|
|
+ assert.NilError(t, err)
|
|
|
+ expected := fmt.Sprintf(
|
|
|
+ `the following directives are specified both as a flag and in the configuration file: http-proxy: (from flag: %[1]s, from file: %[1]s), https-proxy: (from flag: %[1]s, from file: %[1]s), no-proxy: (from flag: example.com, from file: example.com)`,
|
|
|
+ proxyRawURL,
|
|
|
+ )
|
|
|
+ assert.Assert(t, is.Contains(string(logs), expected))
|
|
|
+ })
|
|
|
+}
|