diff --git a/docker/docker.go b/docker/docker.go index 5fc70f064f..686cd2181a 100644 --- a/docker/docker.go +++ b/docker/docker.go @@ -16,8 +16,11 @@ func main() { docker.SysInit() return } + // FIXME: Switch d and D ? (to be more sshd like) fl_daemon := flag.Bool("d", false, "Daemon mode") + fl_debug := flag.Bool("D", false, "Debug mode") flag.Parse() + rcli.DEBUG_FLAG = *fl_debug if *fl_daemon { if flag.NArg() != 0 { flag.Usage() diff --git a/rcli/tcp.go b/rcli/tcp.go index 869a3bcdb6..a1fa669023 100644 --- a/rcli/tcp.go +++ b/rcli/tcp.go @@ -10,6 +10,11 @@ import ( "net" ) +// Note: the globals are here to avoid import cycle +// FIXME: Handle debug levels mode? +var DEBUG_FLAG bool = false +var CLIENT_SOCKET io.Writer = nil + // Connect to a remote endpoint using protocol `proto` and address `addr`, // issue a single call, and return the result. // `proto` may be "tcp", "unix", etc. See the `net` package for available protocols. @@ -42,6 +47,9 @@ func ListenAndServe(proto, addr string, service Service) error { return err } else { go func() { + if DEBUG_FLAG { + CLIENT_SOCKET = conn + } if err := Serve(conn, service); err != nil { log.Printf("Error: " + err.Error() + "\n") fmt.Fprintf(conn, "Error: "+err.Error()+"\n") diff --git a/registry.go b/registry.go index a458817bb2..3d4c0e904f 100644 --- a/registry.go +++ b/registry.go @@ -213,6 +213,9 @@ func (graph *Graph) PushImage(imgOrig *Image, authConfig *auth.AuthConfig) error if err != nil { return fmt.Errorf("Error while retreiving the path for {%s}: %s", img.Id, err) } + + Debugf("Pushing image [%s] on {%s}\n", img.Id, REGISTRY_ENDPOINT+"/images/"+img.Id+"/json") + // FIXME: try json with UTF8 jsonData := strings.NewReader(string(jsonRaw)) req, err := http.NewRequest("PUT", REGISTRY_ENDPOINT+"/images/"+img.Id+"/json", jsonData) @@ -257,6 +260,7 @@ func (graph *Graph) PushImage(imgOrig *Image, authConfig *auth.AuthConfig) error "Fail to retrieve layer storage URL for image {%s}: %s\n", img.Id, err) } + // FIXME: Don't do this :D. Check the S3 requierement and implement chunks of 5MB // FIXME2: I won't stress it enough, DON'T DO THIS! very high priority layerData2, err := Tar(path.Join(graph.Root, img.Id, "layer"), Gzip) @@ -307,6 +311,8 @@ func (graph *Graph) pushTag(remote, revision, tag string, authConfig *auth.AuthC // "jsonify" the string revision = "\"" + revision + "\"" + Debugf("Pushing tags for rev [%s] on {%s}\n", revision, REGISTRY_ENDPOINT+"/users/"+remote+"/"+tag) + client := &http.Client{} req, err := http.NewRequest("PUT", REGISTRY_ENDPOINT+"/users/"+remote+"/"+tag, strings.NewReader(revision)) req.Header.Add("Content-type", "application/json") @@ -328,19 +334,50 @@ func (graph *Graph) pushTag(remote, revision, tag string, authConfig *auth.AuthC return nil } +func (graph *Graph) LookupRemoteRepository(remote string, authConfig *auth.AuthConfig) bool { + rt := &http.Transport{Proxy: http.ProxyFromEnvironment} + + req, err := http.NewRequest("GET", REGISTRY_ENDPOINT+"/users/"+remote, nil) + if err != nil { + return false + } + req.SetBasicAuth(authConfig.Username, authConfig.Password) + res, err := rt.RoundTrip(req) + if err != nil || res.StatusCode != 200 { + return false + } + return true +} + +func (graph *Graph) pushPrimitive(remote, tag, imgId string, authConfig *auth.AuthConfig) error { + // CHeck if the local impage exists + img, err := graph.Get(imgId) + if err != nil { + return err + } + // Push the image + if err = graph.PushImage(img, authConfig); err != nil { + return err + } + // And then the tag + if err = graph.pushTag(remote, imgId, tag, authConfig); err != nil { + return err + } + return nil +} + // Push a repository to the registry. // Remote has the format '/ func (graph *Graph) PushRepository(remote string, localRepo Repository, authConfig *auth.AuthConfig) error { + // Check if the remote repository exists + if !graph.LookupRemoteRepository(remote, authConfig) { + return fmt.Errorf("The remote repository %s does not exist\n", remote) + } + + // For each image within the repo, push them for tag, imgId := range localRepo { - fmt.Printf("tag: %s, imgId: %s\n", tag, imgId) - img, err := graph.Get(imgId) - if err != nil { - return err - } - if err = graph.PushImage(img, authConfig); err != nil { - return err - } - if err = graph.pushTag(remote, imgId, tag, authConfig); err != nil { + if err := graph.pushPrimitive(remote, tag, imgId, authConfig); err != nil { + // FIXME: Continue on error? return err } } diff --git a/runtime.go b/runtime.go index da95dfe365..b7f2582b46 100644 --- a/runtime.go +++ b/runtime.go @@ -6,7 +6,6 @@ import ( "github.com/dotcloud/docker/auth" "io" "io/ioutil" - "log" "os" "path" "sort" @@ -216,10 +215,10 @@ func (runtime *Runtime) restore() error { id := v.Name() container, err := runtime.Load(id) if err != nil { - log.Printf("Failed to load container %v: %v", id, err) + Debugf("Failed to load container %v: %v", id, err) continue } - log.Printf("Loaded container %v", container.Id) + Debugf("Loaded container %v", container.Id) } return nil } diff --git a/utils.go b/utils.go index 29f62f7534..ce722f264f 100644 --- a/utils.go +++ b/utils.go @@ -5,7 +5,9 @@ import ( "container/list" "errors" "fmt" + "github.com/dotcloud/docker/rcli" "io" + "log" "net/http" "os" "os/exec" @@ -37,6 +39,17 @@ func Download(url string, stderr io.Writer) (*http.Response, error) { return resp, nil } +// Debug function, if the debug flag is set, then display. Do nothing otherwise +// If Docker is in damon mode, also send the debug info on the socket +func Debugf(format string, a ...interface{}) { + if rcli.DEBUG_FLAG { + log.Printf(format, a...) + if rcli.CLIENT_SOCKET != nil { + fmt.Fprintf(rcli.CLIENT_SOCKET, log.Prefix()+format, a...) + } + } +} + // Reader with progress bar type progressReader struct { reader io.ReadCloser // Stream to read from