Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Windows port of Docker Client #9113

Merged
merged 10 commits into from Nov 15, 2014
1 change: 1 addition & 0 deletions .gitignore
Expand Up @@ -4,6 +4,7 @@
.vagrant*
bin
docker/docker
*.exe
.*.swp
a.out
*.orig
Expand Down
3 changes: 2 additions & 1 deletion Dockerfile
Expand Up @@ -68,7 +68,8 @@ RUN cd /usr/local/go/src && ./make.bash --no-clean 2>&1
ENV DOCKER_CROSSPLATFORMS \
linux/386 linux/arm \
darwin/amd64 darwin/386 \
freebsd/amd64 freebsd/386 freebsd/arm
freebsd/amd64 freebsd/386 freebsd/arm \
windows/amd64 windows/386
# (set an explicit GOARM of 5 for maximum compatibility)
ENV GOARM 5
RUN cd /usr/local/go/src && bash -xc 'for platform in $DOCKER_CROSSPLATFORMS; do GOOS=${platform%/*} GOARCH=${platform##*/} ./make.bash --no-clean 2>&1; done'
Expand Down
9 changes: 4 additions & 5 deletions api/client/commands.go
Expand Up @@ -18,7 +18,6 @@ import (
"runtime"
"strconv"
"strings"
"syscall"
"text/tabwriter"
"text/template"
"time"
Expand Down Expand Up @@ -608,7 +607,7 @@ func (cli *DockerCli) forwardAllSignals(cid string) chan os.Signal {
signal.CatchAll(sigc)
go func() {
for s := range sigc {
if s == syscall.SIGCHLD {
if s == signal.SIGCHLD {
continue
}
var sig string
Expand All @@ -619,7 +618,7 @@ func (cli *DockerCli) forwardAllSignals(cid string) chan os.Signal {
}
}
if sig == "" {
log.Errorf("Unsupported signal: %d. Discarding.", s)
log.Errorf("Unsupported signal: %v. Discarding.", s)
}
if _, _, err := readBody(cli.call("POST", fmt.Sprintf("/containers/%s/kill?signal=%s", cid, sig), nil, false)); err != nil {
log.Debugf("Error sending signal: %s", err)
Expand Down Expand Up @@ -2184,7 +2183,7 @@ func (cli *DockerCli) CmdCreate(args ...string) error {
flName = cmd.String([]string{"-name"}, "", "Assign a name to the container")
)

config, hostConfig, cmd, err := runconfig.Parse(cmd, args, nil)
config, hostConfig, cmd, err := runconfig.Parse(cmd, args)
if err != nil {
return err
}
Expand Down Expand Up @@ -2220,7 +2219,7 @@ func (cli *DockerCli) CmdRun(args ...string) error {
ErrConflictDetachAutoRemove = fmt.Errorf("Conflicting options: --rm and -d")
)

config, hostConfig, cmd, err := runconfig.Parse(cmd, args, nil)
config, hostConfig, cmd, err := runconfig.Parse(cmd, args)
if err != nil {
return err
}
Expand Down
4 changes: 2 additions & 2 deletions api/client/utils.go
Expand Up @@ -14,12 +14,12 @@ import (
gosignal "os/signal"
"strconv"
"strings"
"syscall"

log "github.com/Sirupsen/logrus"
"github.com/docker/docker/api"
"github.com/docker/docker/dockerversion"
"github.com/docker/docker/engine"
"github.com/docker/docker/pkg/signal"
"github.com/docker/docker/pkg/stdcopy"
"github.com/docker/docker/pkg/term"
"github.com/docker/docker/registry"
Expand Down Expand Up @@ -238,7 +238,7 @@ func (cli *DockerCli) monitorTtySize(id string, isExec bool) error {
cli.resizeTty(id, isExec)

sigchan := make(chan os.Signal, 1)
gosignal.Notify(sigchan, syscall.SIGWINCH)
gosignal.Notify(sigchan, signal.SIGWINCH)
go func() {
for _ = range sigchan {
cli.resizeTty(id, isExec)
Expand Down
2 changes: 1 addition & 1 deletion builder/dispatchers.go
Expand Up @@ -183,7 +183,7 @@ func run(b *Builder, args []string, attributes map[string]bool, original string)
runCmd.SetOutput(ioutil.Discard)
runCmd.Usage = nil

config, _, _, err := runconfig.Parse(runCmd, append([]string{b.image}, args...), nil)
config, _, _, err := runconfig.Parse(runCmd, append([]string{b.image}, args...))
if err != nil {
return err
}
Expand Down
2 changes: 2 additions & 0 deletions daemon/graphdriver/fsdiff.go
@@ -1,3 +1,5 @@
// +build daemon

package graphdriver

import (
Expand Down
10 changes: 9 additions & 1 deletion docker/flags.go
Expand Up @@ -4,6 +4,7 @@ import (
"fmt"
"os"
"path/filepath"
"runtime"

"github.com/docker/docker/opts"
flag "github.com/docker/docker/pkg/mflag"
Expand All @@ -16,10 +17,17 @@ var (

func init() {
if dockerCertPath == "" {
dockerCertPath = filepath.Join(os.Getenv("HOME"), ".docker")
dockerCertPath = filepath.Join(getHomeDir(), ".docker")
}
}

func getHomeDir() string {
if runtime.GOOS == "windows" {
return os.Getenv("USERPROFILE")
}
return os.Getenv("HOME")
}

var (
flVersion = flag.Bool([]string{"v", "-version"}, false, "Print version information and quit")
flDaemon = flag.Bool([]string{"d", "-daemon"}, false, "Enable daemon mode")
Expand Down
14 changes: 7 additions & 7 deletions integration/runtime_test.go
Expand Up @@ -661,7 +661,7 @@ func TestDefaultContainerName(t *testing.T) {
daemon := mkDaemonFromEngine(eng, t)
defer nuke(daemon)

config, _, _, err := parseRun([]string{unitTestImageID, "echo test"}, nil)
config, _, _, err := parseRun([]string{unitTestImageID, "echo test"})
if err != nil {
t.Fatal(err)
}
Expand All @@ -685,7 +685,7 @@ func TestRandomContainerName(t *testing.T) {
daemon := mkDaemonFromEngine(eng, t)
defer nuke(daemon)

config, _, _, err := parseRun([]string{GetTestImage(daemon).ID, "echo test"}, nil)
config, _, _, err := parseRun([]string{GetTestImage(daemon).ID, "echo test"})
if err != nil {
t.Fatal(err)
}
Expand Down Expand Up @@ -716,7 +716,7 @@ func TestContainerNameValidation(t *testing.T) {
{"abc-123_AAA.1", true},
{"\000asdf", false},
} {
config, _, _, err := parseRun([]string{unitTestImageID, "echo test"}, nil)
config, _, _, err := parseRun([]string{unitTestImageID, "echo test"})
if err != nil {
if !test.Valid {
continue
Expand Down Expand Up @@ -757,7 +757,7 @@ func TestLinkChildContainer(t *testing.T) {
daemon := mkDaemonFromEngine(eng, t)
defer nuke(daemon)

config, _, _, err := parseRun([]string{unitTestImageID, "echo test"}, nil)
config, _, _, err := parseRun([]string{unitTestImageID, "echo test"})
if err != nil {
t.Fatal(err)
}
Expand All @@ -773,7 +773,7 @@ func TestLinkChildContainer(t *testing.T) {
t.Fatalf("Expect webapp id to match container id: %s != %s", webapp.ID, container.ID)
}

config, _, _, err = parseRun([]string{GetTestImage(daemon).ID, "echo test"}, nil)
config, _, _, err = parseRun([]string{GetTestImage(daemon).ID, "echo test"})
if err != nil {
t.Fatal(err)
}
Expand All @@ -799,7 +799,7 @@ func TestGetAllChildren(t *testing.T) {
daemon := mkDaemonFromEngine(eng, t)
defer nuke(daemon)

config, _, _, err := parseRun([]string{unitTestImageID, "echo test"}, nil)
config, _, _, err := parseRun([]string{unitTestImageID, "echo test"})
if err != nil {
t.Fatal(err)
}
Expand All @@ -815,7 +815,7 @@ func TestGetAllChildren(t *testing.T) {
t.Fatalf("Expect webapp id to match container id: %s != %s", webapp.ID, container.ID)
}

config, _, _, err = parseRun([]string{unitTestImageID, "echo test"}, nil)
config, _, _, err = parseRun([]string{unitTestImageID, "echo test"})
if err != nil {
t.Fatal(err)
}
Expand Down
10 changes: 5 additions & 5 deletions integration/server_test.go
Expand Up @@ -12,7 +12,7 @@ func TestCreateNumberHostname(t *testing.T) {
eng := NewTestEngine(t)
defer mkDaemonFromEngine(eng, t).Nuke()

config, _, _, err := parseRun([]string{"-h", "web.0", unitTestImageID, "echo test"}, nil)
config, _, _, err := parseRun([]string{"-h", "web.0", unitTestImageID, "echo test"})
if err != nil {
t.Fatal(err)
}
Expand All @@ -24,7 +24,7 @@ func TestCommit(t *testing.T) {
eng := NewTestEngine(t)
defer mkDaemonFromEngine(eng, t).Nuke()

config, _, _, err := parseRun([]string{unitTestImageID, "/bin/cat"}, nil)
config, _, _, err := parseRun([]string{unitTestImageID, "/bin/cat"})
if err != nil {
t.Fatal(err)
}
Expand All @@ -48,7 +48,7 @@ func TestMergeConfigOnCommit(t *testing.T) {
container1, _, _ := mkContainer(runtime, []string{"-e", "FOO=bar", unitTestImageID, "echo test > /tmp/foo"}, t)
defer runtime.Destroy(container1)

config, _, _, err := parseRun([]string{container1.ID, "cat /tmp/foo"}, nil)
config, _, _, err := parseRun([]string{container1.ID, "cat /tmp/foo"})
if err != nil {
t.Error(err)
}
Expand Down Expand Up @@ -102,7 +102,7 @@ func TestRestartKillWait(t *testing.T) {
runtime := mkDaemonFromEngine(eng, t)
defer runtime.Nuke()

config, hostConfig, _, err := parseRun([]string{"-i", unitTestImageID, "/bin/cat"}, nil)
config, hostConfig, _, err := parseRun([]string{"-i", unitTestImageID, "/bin/cat"})
if err != nil {
t.Fatal(err)
}
Expand Down Expand Up @@ -163,7 +163,7 @@ func TestCreateStartRestartStopStartKillRm(t *testing.T) {
eng := NewTestEngine(t)
defer mkDaemonFromEngine(eng, t).Nuke()

config, hostConfig, _, err := parseRun([]string{"-i", unitTestImageID, "/bin/cat"}, nil)
config, hostConfig, _, err := parseRun([]string{"-i", unitTestImageID, "/bin/cat"})
if err != nil {
t.Fatal(err)
}
Expand Down
7 changes: 3 additions & 4 deletions integration/utils_test.go
Expand Up @@ -19,7 +19,6 @@ import (
"github.com/docker/docker/daemon"
"github.com/docker/docker/engine"
flag "github.com/docker/docker/pkg/mflag"
"github.com/docker/docker/pkg/sysinfo"
"github.com/docker/docker/runconfig"
"github.com/docker/docker/utils"
)
Expand Down Expand Up @@ -250,7 +249,7 @@ func readFile(src string, t *testing.T) (content string) {
// The caller is responsible for destroying the container.
// Call t.Fatal() at the first error.
func mkContainer(r *daemon.Daemon, args []string, t *testing.T) (*daemon.Container, *runconfig.HostConfig, error) {
config, hc, _, err := parseRun(args, nil)
config, hc, _, err := parseRun(args)
defer func() {
if err != nil && t != nil {
t.Fatal(err)
Expand Down Expand Up @@ -351,9 +350,9 @@ func getImages(eng *engine.Engine, t *testing.T, all bool, filter string) *engin

}

func parseRun(args []string, sysInfo *sysinfo.SysInfo) (*runconfig.Config, *runconfig.HostConfig, *flag.FlagSet, error) {
func parseRun(args []string) (*runconfig.Config, *runconfig.HostConfig, *flag.FlagSet, error) {
cmd := flag.NewFlagSet("run", flag.ContinueOnError)
cmd.SetOutput(ioutil.Discard)
cmd.Usage = nil
return runconfig.Parse(cmd, args, sysInfo)
return runconfig.Parse(cmd, args)
}
8 changes: 4 additions & 4 deletions opts/opts.go
Expand Up @@ -5,7 +5,7 @@ import (
"net"
"net/url"
"os"
"path/filepath"
"path"
"regexp"
"strings"

Expand Down Expand Up @@ -151,13 +151,13 @@ func ValidatePath(val string) (string, error) {
splited := strings.SplitN(val, ":", 2)
if len(splited) == 1 {
containerPath = splited[0]
val = filepath.Clean(splited[0])
val = path.Clean(splited[0])
} else {
containerPath = splited[1]
val = fmt.Sprintf("%s:%s", splited[0], filepath.Clean(splited[1]))
val = fmt.Sprintf("%s:%s", splited[0], path.Clean(splited[1]))
}

if !filepath.IsAbs(containerPath) {
if !path.IsAbs(containerPath) {
return val, fmt.Errorf("%s is not an absolute path", containerPath)
}
return val, nil
Expand Down
19 changes: 5 additions & 14 deletions pkg/archive/archive.go
Expand Up @@ -192,20 +192,11 @@ func (ta *tarAppender) addTarFile(path, name string) error {

hdr.Name = name

var (
nlink uint32
inode uint64
)
if stat, ok := fi.Sys().(*syscall.Stat_t); ok {
nlink = uint32(stat.Nlink)
inode = uint64(stat.Ino)
// Currently go does not fill in the major/minors
if stat.Mode&syscall.S_IFBLK == syscall.S_IFBLK ||
stat.Mode&syscall.S_IFCHR == syscall.S_IFCHR {
hdr.Devmajor = int64(major(uint64(stat.Rdev)))
hdr.Devminor = int64(minor(uint64(stat.Rdev)))
}
nlink, inode, err := setHeaderForSpecialDevice(hdr, ta, name, fi.Sys())
if err != nil {
return err
}

// if it's a regular file and has more than 1 link,
// it's hardlinked, so set the type flag accordingly
if fi.Mode().IsRegular() && nlink > 1 {
Expand Down Expand Up @@ -291,7 +282,7 @@ func createTarFile(path, extractDir string, hdr *tar.Header, reader io.Reader, L
mode |= syscall.S_IFIFO
}

if err := syscall.Mknod(path, mode, int(mkdev(hdr.Devmajor, hdr.Devminor))); err != nil {
if err := system.Mknod(path, mode, int(system.Mkdev(hdr.Devmajor, hdr.Devminor))); err != nil {
return err
}

Expand Down
39 changes: 39 additions & 0 deletions pkg/archive/archive_unix.go
@@ -0,0 +1,39 @@
// +build !windows

package archive

import (
"errors"
"syscall"

"github.com/docker/docker/vendor/src/code.google.com/p/go/src/pkg/archive/tar"
)

func setHeaderForSpecialDevice(hdr *tar.Header, ta *tarAppender, name string, stat interface{}) (nlink uint32, inode uint64, err error) {
s, ok := stat.(*syscall.Stat_t)

if !ok {
err = errors.New("cannot convert stat value to syscall.Stat_t")
return
}

nlink = uint32(s.Nlink)
inode = uint64(s.Ino)

// Currently go does not fil in the major/minors
if s.Mode&syscall.S_IFBLK == syscall.S_IFBLK ||
s.Mode&syscall.S_IFCHR == syscall.S_IFCHR {
hdr.Devmajor = int64(major(uint64(s.Rdev)))
hdr.Devminor = int64(minor(uint64(s.Rdev)))
}

return
}

func major(device uint64) uint64 {
return (device >> 8) & 0xfff
}

func minor(device uint64) uint64 {
return (device & 0xff) | ((device >> 12) & 0xfff00)
}
12 changes: 12 additions & 0 deletions pkg/archive/archive_windows.go
@@ -0,0 +1,12 @@
// +build windows

package archive

import (
"github.com/docker/docker/vendor/src/code.google.com/p/go/src/pkg/archive/tar"
)

func setHeaderForSpecialDevice(hdr *tar.Header, ta *tarAppender, name string, stat interface{}) (nlink uint32, inode uint64, err error) {
// do nothing. no notion of Rdev, Inode, Nlink in stat on Windows
return
}