Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 1 addition & 3 deletions api/client/build.go
Original file line number Diff line number Diff line change
Expand Up @@ -286,10 +286,8 @@ func (cli *DockerCli) CmdBuild(args ...string) error {

v.Set("dockerfile", *dockerfileName)

cli.LoadConfigFile()

headers := http.Header(make(map[string][]string))
buf, err := json.Marshal(cli.configFile)
buf, err := json.Marshal(cli.configFile.AuthConfigs)
if err != nil {
return err
}
Expand Down
15 changes: 7 additions & 8 deletions api/client/cli.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"net"
"net/http"
"os"
"path/filepath"
"reflect"
"strings"
"text/template"
Expand Down Expand Up @@ -120,14 +121,6 @@ func (cli *DockerCli) Subcmd(name, signature, description string, exitOnError bo
return flags
}

func (cli *DockerCli) LoadConfigFile() (err error) {
cli.configFile, err = registry.LoadConfig(homedir.Get())
if err != nil {
fmt.Fprintf(cli.err, "WARNING: %s\n", err)
}
return err
}

func (cli *DockerCli) CheckTtyInput(attachStdin, ttyMode bool) error {
// In order to attach to a container tty, input stream for the client must
// be a tty itself: redirecting or piping the client standard input is
Expand Down Expand Up @@ -184,9 +177,15 @@ func NewDockerCli(in io.ReadCloser, out, err io.Writer, keyFile string, proto, a
tr.Dial = (&net.Dialer{Timeout: timeout}).Dial
}

configFile, e := registry.LoadConfig(filepath.Join(homedir.Get(), ".docker"))
if e != nil {
fmt.Fprintf(err, "WARNING: Error loading config file:%v\n", e)
}

return &DockerCli{
proto: proto,
addr: addr,
configFile: configFile,
in: in,
out: out,
err: err,
Expand Down
3 changes: 0 additions & 3 deletions api/client/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,6 @@ func (cli *DockerCli) pullImageCustomOut(image string, out io.Writer) error {
return err
}

// Load the auth config file, to be able to pull the image
cli.LoadConfigFile()

// Resolve the Auth config relevant for this server
authConfig := cli.configFile.ResolveAuthConfig(repoInfo.Index)
buf, err := json.Marshal(authConfig)
Expand Down
7 changes: 7 additions & 0 deletions api/client/hijack.go
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,13 @@ func (cli *DockerCli) hijack(method, path string, setRawTerminal bool, in io.Rea
if err != nil {
return err
}

// Add CLI Config's HTTP Headers BEFORE we set the Docker headers
// then the user can't change OUR headers
for k, v := range cli.configFile.HttpHeaders {
req.Header.Set(k, v)
}

req.Header.Set("User-Agent", "Docker-Client/"+dockerversion.VERSION)
req.Header.Set("Content-Type", "text/plain")
req.Header.Set("Connection", "Upgrade")
Expand Down
3 changes: 1 addition & 2 deletions api/client/info.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,8 +68,7 @@ func (cli *DockerCli) CmdInfo(args ...string) error {
}

if info.IndexServerAddress != "" {
cli.LoadConfigFile()
u := cli.configFile.Configs[info.IndexServerAddress].Username
u := cli.configFile.AuthConfigs[info.IndexServerAddress].Username
if len(u) > 0 {
fmt.Fprintf(cli.out, "Username: %v\n", u)
fmt.Fprintf(cli.out, "Registry: %v\n", info.IndexServerAddress)
Expand Down
24 changes: 13 additions & 11 deletions api/client/login.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,9 @@ import (
"fmt"
"io"
"os"
"path"
"strings"

"github.com/docker/docker/api/types"
"github.com/docker/docker/pkg/homedir"
flag "github.com/docker/docker/pkg/mflag"
"github.com/docker/docker/pkg/term"
"github.com/docker/docker/registry"
Expand Down Expand Up @@ -56,8 +54,7 @@ func (cli *DockerCli) CmdLogin(args ...string) error {
return string(line)
}

cli.LoadConfigFile()
authconfig, ok := cli.configFile.Configs[serverAddress]
authconfig, ok := cli.configFile.AuthConfigs[serverAddress]
if !ok {
authconfig = registry.AuthConfig{}
}
Expand Down Expand Up @@ -113,12 +110,14 @@ func (cli *DockerCli) CmdLogin(args ...string) error {
authconfig.Password = password
authconfig.Email = email
authconfig.ServerAddress = serverAddress
cli.configFile.Configs[serverAddress] = authconfig
cli.configFile.AuthConfigs[serverAddress] = authconfig

stream, statusCode, err := cli.call("POST", "/auth", cli.configFile.Configs[serverAddress], nil)
stream, statusCode, err := cli.call("POST", "/auth", cli.configFile.AuthConfigs[serverAddress], nil)
if statusCode == 401 {
delete(cli.configFile.Configs, serverAddress)
registry.SaveConfig(cli.configFile)
delete(cli.configFile.AuthConfigs, serverAddress)
if err2 := cli.configFile.Save(); err2 != nil {
fmt.Fprintf(cli.out, "WARNING: could not save config file: %v\n", err2)
}
return err
}
if err != nil {
Expand All @@ -127,12 +126,15 @@ func (cli *DockerCli) CmdLogin(args ...string) error {

var response types.AuthResponse
if err := json.NewDecoder(stream).Decode(&response); err != nil {
cli.configFile, _ = registry.LoadConfig(homedir.Get())
// Upon error, remove entry
delete(cli.configFile.AuthConfigs, serverAddress)
return err
}

registry.SaveConfig(cli.configFile)
fmt.Fprintf(cli.out, "WARNING: login credentials saved in %s.\n", path.Join(homedir.Get(), registry.CONFIGFILE))
if err := cli.configFile.Save(); err != nil {
return fmt.Errorf("Error saving config file: %v", err)
}
fmt.Fprintf(cli.out, "WARNING: login credentials saved in %s\n", cli.configFile.Filename())

if response.Status != "" {
fmt.Fprintf(cli.out, "%s\n", response.Status)
Expand Down
7 changes: 3 additions & 4 deletions api/client/logout.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,13 @@ func (cli *DockerCli) CmdLogout(args ...string) error {
serverAddress = cmd.Arg(0)
}

cli.LoadConfigFile()
if _, ok := cli.configFile.Configs[serverAddress]; !ok {
if _, ok := cli.configFile.AuthConfigs[serverAddress]; !ok {
fmt.Fprintf(cli.out, "Not logged in to %s\n", serverAddress)
} else {
fmt.Fprintf(cli.out, "Remove login credentials for %s\n", serverAddress)
delete(cli.configFile.Configs, serverAddress)
delete(cli.configFile.AuthConfigs, serverAddress)

if err := registry.SaveConfig(cli.configFile); err != nil {
if err := cli.configFile.Save(); err != nil {
return fmt.Errorf("Failed to save docker config: %v", err)
}
}
Expand Down
2 changes: 0 additions & 2 deletions api/client/pull.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,6 @@ func (cli *DockerCli) CmdPull(args ...string) error {
return err
}

cli.LoadConfigFile()

_, _, err = cli.clientRequestAttemptLogin("POST", "/images/create?"+v.Encode(), nil, cli.out, repoInfo.Index, "pull")
return err
}
2 changes: 0 additions & 2 deletions api/client/push.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,6 @@ func (cli *DockerCli) CmdPush(args ...string) error {

name := cmd.Arg(0)

cli.LoadConfigFile()

remote, tag := parsers.ParseRepositoryTag(name)

// Resolve the Repository name from fqn to RepositoryInfo
Expand Down
2 changes: 0 additions & 2 deletions api/client/search.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,6 @@ func (cli *DockerCli) CmdSearch(args ...string) error {
return err
}

cli.LoadConfigFile()

rdr, _, err := cli.clientRequestAttemptLogin("GET", "/images/search?"+v.Encode(), nil, nil, repoInfo.Index, "search")
if err != nil {
return err
Expand Down
9 changes: 8 additions & 1 deletion api/client/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,13 @@ func (cli *DockerCli) clientRequest(method, path string, in io.Reader, headers m
if err != nil {
return nil, "", -1, err
}

// Add CLI Config's HTTP Headers BEFORE we set the Docker headers
// then the user can't change OUR headers
for k, v := range cli.configFile.HttpHeaders {
req.Header.Set(k, v)
}

req.Header.Set("User-Agent", "Docker-Client/"+dockerversion.VERSION)
req.URL.Host = cli.addr
req.URL.Scheme = cli.scheme
Expand Down Expand Up @@ -299,7 +306,7 @@ func (cli *DockerCli) monitorTtySize(id string, isExec bool) error {
sigchan := make(chan os.Signal, 1)
gosignal.Notify(sigchan, signal.SIGWINCH)
go func() {
for _ = range sigchan {
for range sigchan {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

go 1.4ism, I would revert this line just in case

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done - always hits me on this file.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@LK4D4 confirmed we're okay for dropping support for go1.3, so let's leave it.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

reverted

cli.resizeTty(id, isExec)
}
}()
Expand Down
4 changes: 2 additions & 2 deletions builder/evaluator.go
Original file line number Diff line number Diff line change
Expand Up @@ -101,8 +101,8 @@ type Builder struct {
// the final configs of the Dockerfile but dont want the layers
disableCommit bool

AuthConfig *registry.AuthConfig
AuthConfigFile *registry.ConfigFile
AuthConfig *registry.AuthConfig
ConfigFile *registry.ConfigFile

// Deprecated, original writer used for ImagePull. To be removed.
OutOld io.Writer
Expand Down
4 changes: 2 additions & 2 deletions builder/internals.go
Original file line number Diff line number Diff line change
Expand Up @@ -437,13 +437,13 @@ func (b *Builder) pullImage(name string) (*imagepkg.Image, error) {
}

pullRegistryAuth := b.AuthConfig
if len(b.AuthConfigFile.Configs) > 0 {
if len(b.ConfigFile.AuthConfigs) > 0 {
// The request came with a full auth config file, we prefer to use that
repoInfo, err := b.Daemon.RegistryService.ResolveRepository(remote)
if err != nil {
return nil, err
}
resolvedAuth := b.AuthConfigFile.ResolveAuthConfig(repoInfo.Index)
resolvedAuth := b.ConfigFile.ResolveAuthConfig(repoInfo.Index)
pullRegistryAuth = &resolvedAuth
}

Expand Down
2 changes: 1 addition & 1 deletion builder/job.go
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ func (b *BuilderJob) CmdBuild(job *engine.Job) error {
OutOld: job.Stdout,
StreamFormatter: sf,
AuthConfig: authConfig,
AuthConfigFile: configFile,
ConfigFile: configFile,
dockerfileName: dockerfileName,
cpuShares: cpuShares,
cpuSetCpus: cpuSetCpus,
Expand Down
29 changes: 29 additions & 0 deletions docs/sources/reference/commandline/cli.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,35 @@ These Go environment variables are case-insensitive. See the
[Go specification](http://golang.org/pkg/net/http/) for details on these
variables.

## Configuration Files

The Docker command line stores its configuration files in a directory called
`.docker` within your `HOME` directory. Docker manages most of the files in
`.docker` and you should not modify them. However, you *can modify* the
`.docker/config.json` file to control certain aspects of how the `docker`
command behaves.

Currently, you can modify the `docker` command behavior using environment
variables or command-line options. You can also use options within
`config.json` to modify some of the same behavior. When using these
mechanisms, you must keep in mind the order of precedence among them. Command
line options override environment variables and environment variables override
properties you specify in a `config.json` file.

The `config.json` file stores a JSON encoding of a single `HttpHeaders`
property. The property specifies a set of headers to include in all
messages sent from the Docker client to the daemon. Docker does not try to
interpret or understand these header; it simply puts them into the messages.
Docker does not allow these headers to change any headers it sets for itself.

Following is a sample `config.json` file:

{
"HttpHeaders: {
"MyHeader": "MyValue"
}
}

## Help
To list the help on any command just execute the command, followed by the `--help` option.

Expand Down
58 changes: 58 additions & 0 deletions integration-cli/docker_cli_config_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package main

import (
"io/ioutil"
"net/http"
"net/http/httptest"
"os"
"os/exec"
"path/filepath"
"testing"

"github.com/docker/docker/pkg/homedir"
)

func TestConfigHttpHeader(t *testing.T) {
testRequires(t, UnixCli) // Can't set/unset HOME on windows right now
// We either need a level of Go that supports Unsetenv (for cases
// when HOME/USERPROFILE isn't set), or we need to be able to use
// os/user but user.Current() only works if we aren't statically compiling

var headers map[string][]string

server := httptest.NewServer(http.HandlerFunc(
func(w http.ResponseWriter, r *http.Request) {
headers = r.Header
}))
defer server.Close()

homeKey := homedir.Key()
homeVal := homedir.Get()
tmpDir, _ := ioutil.TempDir("", "fake-home")
defer os.RemoveAll(tmpDir)

dotDocker := filepath.Join(tmpDir, ".docker")
os.Mkdir(dotDocker, 0600)
tmpCfg := filepath.Join(dotDocker, "config.json")

defer func() { os.Setenv(homeKey, homeVal) }()
os.Setenv(homeKey, tmpDir)

data := `{
"HttpHeaders": { "MyHeader": "MyValue" }
}`

err := ioutil.WriteFile(tmpCfg, []byte(data), 0600)
if err != nil {
t.Fatalf("Err creating file(%s): %v", tmpCfg, err)
}

cmd := exec.Command(dockerBinary, "-H="+server.URL[7:], "ps")
out, _, _ := runCommandWithOutput(cmd)

if headers["Myheader"] == nil || headers["Myheader"][0] != "MyValue" {
t.Fatalf("Missing/bad header: %q\nout:%v", headers, out)
}

logDone("config - add new http headers")
}
Loading