From 35f1e301b573f057937c0d3f3232e4f03cd21a5d Mon Sep 17 00:00:00 2001
From: Dave Tucker
Date: Tue, 31 Jan 2017 05:15:51 +0000
Subject: [PATCH] Allow Proxy Configuration in config.json
This commit modifies config.json to allow for any proxies allowed in
build-args to be configured. These values will then be used
by default as build-args in docker build.
Signed-off-by: Dave Tucker
---
cli/command/container/run.go | 16 +++-
cli/command/image/build.go | 2 +-
cli/config/configfile/file.go | 43 +++++++++++
cli/config/configfile/file_test.go | 117 +++++++++++++++++++++++++++++
4 files changed, 175 insertions(+), 3 deletions(-)
diff --git a/cli/command/container/run.go b/cli/command/container/run.go
index 0164219b7f..56f0d0d57b 100644
--- a/cli/command/container/run.go
+++ b/cli/command/container/run.go
@@ -13,6 +13,7 @@ import (
"github.com/Sirupsen/logrus"
"github.com/docker/cli/cli"
"github.com/docker/cli/cli/command"
+ "github.com/docker/cli/opts"
"github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/container"
"github.com/docker/docker/pkg/promise"
@@ -96,14 +97,24 @@ func isLocalhost(ip string) bool {
return localhostIPRegexp.MatchString(ip)
}
-func runRun(dockerCli *command.DockerCli, flags *pflag.FlagSet, opts *runOptions, copts *containerOptions) error {
+func runRun(dockerCli *command.DockerCli, flags *pflag.FlagSet, ropts *runOptions, copts *containerOptions) error {
+ proxyConfig := dockerCli.ConfigFile().ParseProxyConfig(dockerCli.Client().DaemonHost(), copts.env.GetAll())
+ newEnv := []string{}
+ for k, v := range proxyConfig {
+ if v == nil {
+ newEnv = append(newEnv, k)
+ } else {
+ newEnv = append(newEnv, fmt.Sprintf("%s=%s", k, *v))
+ }
+ }
+ copts.env = *opts.NewListOptsRef(&newEnv, nil)
containerConfig, err := parse(flags, copts)
// just in case the parse does not exit
if err != nil {
reportError(dockerCli.Err(), "run", err.Error(), true)
return cli.StatusError{StatusCode: 125}
}
- return runContainer(dockerCli, opts, copts, containerConfig)
+ return runContainer(dockerCli, ropts, copts, containerConfig)
}
// nolint: gocyclo
@@ -159,6 +170,7 @@ func runContainer(dockerCli *command.DockerCli, opts *runOptions, copts *contain
sigc := ForwardAllSignals(ctx, dockerCli, createResponse.ID)
defer signal.StopCatch(sigc)
}
+
var (
waitDisplayID chan struct{}
errCh chan error
diff --git a/cli/command/image/build.go b/cli/command/image/build.go
index 1a6cb951bc..2077914717 100644
--- a/cli/command/image/build.go
+++ b/cli/command/image/build.go
@@ -290,7 +290,7 @@ func runBuild(dockerCli *command.DockerCli, options buildOptions) error {
Dockerfile: relDockerfile,
ShmSize: options.shmSize.Value(),
Ulimits: options.ulimits.GetList(),
- BuildArgs: opts.ConvertKVStringsToMapWithNil(options.buildArgs.GetAll()),
+ BuildArgs: dockerCli.ConfigFile().ParseProxyConfig(dockerCli.Client().DaemonHost(), options.buildArgs.GetAll()),
AuthConfigs: authConfigs,
Labels: opts.ConvertKVStringsToMap(options.labels.GetAll()),
CacheFrom: options.cacheFrom,
diff --git a/cli/config/configfile/file.go b/cli/config/configfile/file.go
index 7214325d87..78024acf54 100644
--- a/cli/config/configfile/file.go
+++ b/cli/config/configfile/file.go
@@ -9,6 +9,7 @@ import (
"path/filepath"
"strings"
+ "github.com/docker/cli/opts"
"github.com/docker/docker/api/types"
"github.com/pkg/errors"
)
@@ -41,6 +42,15 @@ type ConfigFile struct {
ConfigFormat string `json:"configFormat,omitempty"`
NodesFormat string `json:"nodesFormat,omitempty"`
PruneFilters []string `json:"pruneFilters,omitempty"`
+ Proxies map[string]ProxyConfig `json:"proxies,omitempty"`
+}
+
+// ProxyConfig contains proxy configuration settings
+type ProxyConfig struct {
+ HTTPProxy string `json:"httpProxy,omitempty"`
+ HTTPSProxy string `json:"httpsProxy,omitempty"`
+ NoProxy string `json:"noProxy,omitempty"`
+ FTPProxy string `json:"ftpProxy,omitempty"`
}
// LegacyLoadFromReader reads the non-nested configuration data given and sets up the
@@ -152,6 +162,39 @@ func (configFile *ConfigFile) Save() error {
return configFile.SaveToWriter(f)
}
+// ParseProxyConfig computes proxy configuration by retreiving the config for the provided host and
+// then checking this against any environment variables provided to the container
+func (configFile *ConfigFile) ParseProxyConfig(host string, runOpts []string) map[string]*string {
+ var cfgKey string
+
+ if _, ok := configFile.Proxies[host]; !ok {
+ cfgKey = "default"
+ } else {
+ cfgKey = host
+ }
+
+ config, _ := configFile.Proxies[cfgKey]
+ permitted := map[string]*string{
+ "HTTP_PROXY": &config.HTTPProxy,
+ "HTTPS_PROXY": &config.HTTPSProxy,
+ "NO_PROXY": &config.NoProxy,
+ "FTP_PROXY": &config.FTPProxy,
+ }
+ m := opts.ConvertKVStringsToMapWithNil(runOpts)
+ for k := range permitted {
+ if *permitted[k] == "" {
+ continue
+ }
+ if _, ok := m[k]; !ok {
+ m[k] = permitted[k]
+ }
+ if _, ok := m[strings.ToLower(k)]; !ok {
+ m[strings.ToLower(k)] = permitted[k]
+ }
+ }
+ return m
+}
+
// encodeAuth creates a base64 encoded string to containing authorization information
func encodeAuth(authConfig *types.AuthConfig) string {
if authConfig.Username == "" && authConfig.Password == "" {
diff --git a/cli/config/configfile/file_test.go b/cli/config/configfile/file_test.go
index 435797f681..8c84347719 100644
--- a/cli/config/configfile/file_test.go
+++ b/cli/config/configfile/file_test.go
@@ -1,9 +1,11 @@
package configfile
import (
+ "fmt"
"testing"
"github.com/docker/docker/api/types"
+ "github.com/stretchr/testify/assert"
)
func TestEncodeAuth(t *testing.T) {
@@ -25,3 +27,118 @@ func TestEncodeAuth(t *testing.T) {
t.Fatal("AuthString encoding isn't correct.")
}
}
+
+func TestProxyConfig(t *testing.T) {
+ httpProxy := "http://proxy.mycorp.com:3128"
+ httpsProxy := "https://user:password@proxy.mycorp.com:3129"
+ ftpProxy := "http://ftpproxy.mycorp.com:21"
+ noProxy := "*.intra.mycorp.com"
+ defaultProxyConfig := ProxyConfig{
+ HTTPProxy: httpProxy,
+ HTTPSProxy: httpsProxy,
+ FTPProxy: ftpProxy,
+ NoProxy: noProxy,
+ }
+
+ cfg := ConfigFile{
+ Proxies: map[string]ProxyConfig{
+ "default": defaultProxyConfig,
+ },
+ }
+
+ proxyConfig := cfg.ParseProxyConfig("/var/run/docker.sock", []string{})
+ expected := map[string]*string{
+ "HTTP_PROXY": &httpProxy,
+ "http_proxy": &httpProxy,
+ "HTTPS_PROXY": &httpsProxy,
+ "https_proxy": &httpsProxy,
+ "FTP_PROXY": &ftpProxy,
+ "ftp_proxy": &ftpProxy,
+ "NO_PROXY": &noProxy,
+ "no_proxy": &noProxy,
+ }
+ assert.Equal(t, expected, proxyConfig)
+}
+
+func TestProxyConfigOverride(t *testing.T) {
+ httpProxy := "http://proxy.mycorp.com:3128"
+ overrideHTTPProxy := "http://proxy.example.com:3128"
+ overrideNoProxy := ""
+ httpsProxy := "https://user:password@proxy.mycorp.com:3129"
+ ftpProxy := "http://ftpproxy.mycorp.com:21"
+ noProxy := "*.intra.mycorp.com"
+ defaultProxyConfig := ProxyConfig{
+ HTTPProxy: httpProxy,
+ HTTPSProxy: httpsProxy,
+ FTPProxy: ftpProxy,
+ NoProxy: noProxy,
+ }
+
+ cfg := ConfigFile{
+ Proxies: map[string]ProxyConfig{
+ "default": defaultProxyConfig,
+ },
+ }
+
+ ropts := []string{
+ fmt.Sprintf("HTTP_PROXY=%s", overrideHTTPProxy),
+ "NO_PROXY=",
+ }
+ proxyConfig := cfg.ParseProxyConfig("/var/run/docker.sock", ropts)
+ expected := map[string]*string{
+ "HTTP_PROXY": &overrideHTTPProxy,
+ "http_proxy": &httpProxy,
+ "HTTPS_PROXY": &httpsProxy,
+ "https_proxy": &httpsProxy,
+ "FTP_PROXY": &ftpProxy,
+ "ftp_proxy": &ftpProxy,
+ "NO_PROXY": &overrideNoProxy,
+ "no_proxy": &noProxy,
+ }
+ assert.Equal(t, expected, proxyConfig)
+}
+
+func TestProxyConfigPerHost(t *testing.T) {
+ httpProxy := "http://proxy.mycorp.com:3128"
+ httpsProxy := "https://user:password@proxy.mycorp.com:3129"
+ ftpProxy := "http://ftpproxy.mycorp.com:21"
+ noProxy := "*.intra.mycorp.com"
+
+ extHTTPProxy := "http://proxy.example.com:3128"
+ extHTTPSProxy := "https://user:password@proxy.example.com:3129"
+ extFTPProxy := "http://ftpproxy.example.com:21"
+ extNoProxy := "*.intra.example.com"
+
+ defaultProxyConfig := ProxyConfig{
+ HTTPProxy: httpProxy,
+ HTTPSProxy: httpsProxy,
+ FTPProxy: ftpProxy,
+ NoProxy: noProxy,
+ }
+ externalProxyConfig := ProxyConfig{
+ HTTPProxy: extHTTPProxy,
+ HTTPSProxy: extHTTPSProxy,
+ FTPProxy: extFTPProxy,
+ NoProxy: extNoProxy,
+ }
+
+ cfg := ConfigFile{
+ Proxies: map[string]ProxyConfig{
+ "default": defaultProxyConfig,
+ "tcp://example.docker.com:2376": externalProxyConfig,
+ },
+ }
+
+ proxyConfig := cfg.ParseProxyConfig("tcp://example.docker.com:2376", []string{})
+ expected := map[string]*string{
+ "HTTP_PROXY": &extHTTPProxy,
+ "http_proxy": &extHTTPProxy,
+ "HTTPS_PROXY": &extHTTPSProxy,
+ "https_proxy": &extHTTPSProxy,
+ "FTP_PROXY": &extFTPProxy,
+ "ftp_proxy": &extFTPProxy,
+ "NO_PROXY": &extNoProxy,
+ "no_proxy": &extNoProxy,
+ }
+ assert.Equal(t, expected, proxyConfig)
+}