Browse Source

added docs and moved to api version 1.2

Victor Vieux 12 years ago
parent
commit
3dd1e4d58c
3 changed files with 101 additions and 16 deletions
  1. 65 8
      api.go
  2. 14 1
      auth/auth.go
  3. 22 7
      docs/sources/api/docker_remote_api.rst

+ 65 - 8
api.go

@@ -13,7 +13,7 @@ import (
 	"strings"
 )
 
-const API_VERSION = 1.1
+const API_VERSION = 1.2
 
 func hijackServer(w http.ResponseWriter) (io.ReadCloser, io.Writer, error) {
 	conn, _, err := w.(http.Hijacker).Hijack()
@@ -68,15 +68,55 @@ func getBoolParam(value string) (bool, error) {
 	return false, fmt.Errorf("Bad parameter")
 }
 
-func postAuth(srv *Server, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
-	authConfig := &auth.AuthConfig{}
-	if err := json.NewDecoder(r.Body).Decode(authConfig); err != nil {
+func getAuth(srv *Server, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
+	if version > 1.1 {
+		w.WriteHeader(http.StatusNotFound)
+		return nil
+	}
+	authConfig, err := auth.LoadConfig(srv.runtime.root)
+	if err != nil {
+		if err != auth.ErrConfigFileMissing {
+			return err
+		}
+		authConfig = &auth.AuthConfig{}
+	}
+	b, err := json.Marshal(&auth.AuthConfig{Username: authConfig.Username, Email: authConfig.Email})
+	if err != nil {
 		return err
 	}
-	status, err := auth.Login(authConfig)
+	writeJson(w, b)
+	return nil
+}
+
+func postAuth(srv *Server, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
+	authConfig := &auth.AuthConfig{}
+	err := json.NewDecoder(r.Body).Decode(authConfig)
 	if err != nil {
 		return err
 	}
+	status := ""
+	if version > 1.1 {
+		status, err = auth.Login(authConfig, false)
+		if err != nil {
+			return err
+		}
+	} else {
+		localAuthConfig, err := auth.LoadConfig(srv.runtime.root)
+		if err != nil {
+			if err != auth.ErrConfigFileMissing {
+				return err
+			}
+		}
+		if authConfig.Username == localAuthConfig.Username {
+			authConfig.Password = localAuthConfig.Password
+		}
+
+		newAuthConfig := auth.NewAuthConfig(authConfig.Username, authConfig.Password, authConfig.Email, srv.runtime.root)
+		status, err = auth.Login(newAuthConfig, true)
+		if err != nil {
+			return err
+		}
+	}
 	if status != "" {
 		b, err := json.Marshal(&ApiAuth{Status: status})
 		if err != nil {
@@ -288,7 +328,15 @@ func postImagesCreate(srv *Server, version float64, w http.ResponseWriter, r *ht
 	if image != "" { //pull
 		registry := r.Form.Get("registry")
 		authConfig := &auth.AuthConfig{}
-		json.NewDecoder(r.Body).Decode(authConfig)
+		if version > 1.1 {
+			json.NewDecoder(r.Body).Decode(authConfig)
+		} else {
+			localAuthConfig, err := auth.LoadConfig(srv.runtime.root)
+			if err != nil && err != auth.ErrConfigFileMissing {
+				return err
+			}
+			authConfig = localAuthConfig
+		}
 		if err := srv.ImagePull(image, tag, registry, w, sf, authConfig); err != nil {
 			if sf.Used() {
 				w.Write(sf.FormatError(err))
@@ -358,8 +406,16 @@ func postImagesInsert(srv *Server, version float64, w http.ResponseWriter, r *ht
 
 func postImagesPush(srv *Server, version float64, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
 	authConfig := &auth.AuthConfig{}
-	if err := json.NewDecoder(r.Body).Decode(authConfig); err != nil {
-		return err
+	if version > 1.1 {
+		if err := json.NewDecoder(r.Body).Decode(authConfig); err != nil {
+			return err
+		}
+	} else {
+		localAuthConfig, err := auth.LoadConfig(srv.runtime.root)
+		if err != nil && err != auth.ErrConfigFileMissing {
+			return err
+		}
+		authConfig = localAuthConfig
 	}
 	if err := parseForm(r); err != nil {
 		return err
@@ -682,6 +738,7 @@ func ListenAndServe(addr string, srv *Server, logging bool) error {
 
 	m := map[string]map[string]func(*Server, float64, http.ResponseWriter, *http.Request, map[string]string) error{
 		"GET": {
+			"/auth":                         getAuth,
 			"/version":                      getVersion,
 			"/info":                         getInfo,
 			"/images/json":                  getImagesJson,

+ 14 - 1
auth/auth.go

@@ -120,7 +120,8 @@ func SaveConfig(authConfig *AuthConfig) error {
 }
 
 // try to register/login to the registry server
-func Login(authConfig *AuthConfig) (string, error) {
+func Login(authConfig *AuthConfig, store bool) (string, error) {
+	storeConfig := false
 	client := &http.Client{}
 	reqStatusCode := 0
 	var status string
@@ -146,6 +147,7 @@ func Login(authConfig *AuthConfig) (string, error) {
 	if reqStatusCode == 201 {
 		status = "Account created. Please use the confirmation link we sent" +
 			" to your e-mail to activate it.\n"
+		storeConfig = true
 	} else if reqStatusCode == 403 {
 		return "", fmt.Errorf("Login: Your account hasn't been activated. " +
 			"Please check your e-mail for a confirmation link.")
@@ -164,7 +166,13 @@ func Login(authConfig *AuthConfig) (string, error) {
 			}
 			if resp.StatusCode == 200 {
 				status = "Login Succeeded\n"
+				storeConfig = true
 			} else if resp.StatusCode == 401 {
+				if store {
+					if err := SaveConfig(authConfig); err != nil {
+						return "", err
+					}
+				}
 				return "", fmt.Errorf("Wrong login/password, please try again")
 			} else {
 				return "", fmt.Errorf("Login: %s (Code: %d; Headers: %s)", body,
@@ -176,5 +184,10 @@ func Login(authConfig *AuthConfig) (string, error) {
 	} else {
 		return "", fmt.Errorf("Unexpected status code [%d] : %s", reqStatusCode, reqBody)
 	}
+	if storeConfig && store {
+		if err := SaveConfig(authConfig); err != nil {
+			return "", err
+		}
+	}
 	return status, nil
 }

+ 22 - 7
docs/sources/api/docker_remote_api.rst

@@ -14,12 +14,13 @@ Docker Remote API
 - The Remote API is replacing rcli
 - Default port in the docker deamon is 4243 
 - The API tends to be REST, but for some complex commands, like attach or pull, the HTTP connection is hijacked to transport stdout stdin and stderr
+- Since API version 1.2, the auth configuration is now handled client side, so the client has to send the authConfig as POST in /images/create and /images/<name>/pull
 
 2. Version
 ==========
 
-The current verson of the API is 1.1
-Calling /images/<name>/insert is the same as calling /v1.1/images/<name>/insert
+The current verson of the API is 1.2
+Calling /images/<name>/insert is the same as calling /v1.2/images/<name>/insert
 You can still call an old version of the api using /v1.0/images/<name>/insert
 
 3. Endpoints
@@ -550,11 +551,18 @@ Create an image
 
 	Create an image, either by pull it from the registry or by importing it
 
-	**Example request**:
+	**Example request v1.0**:
+
+        .. sourcecode:: http
+
+           POST /images/create?fromImage=base HTTP/1.1
+
+	**Example request v1.2**:
 
         .. sourcecode:: http
 
            POST /images/create?fromImage=base HTTP/1.1
+	   {{ authConfig }}
 
         **Example response v1.1**:
 
@@ -720,11 +728,18 @@ Push an image on the registry
 
 	Push the image ``name`` on the registry
 
-	 **Example request**:
+	 **Example request v1.0**:
+
+	 .. sourcecode:: http
+
+	    POST /images/test/push HTTP/1.1
+
+	 **Example request v1.2**:
 
 	 .. sourcecode:: http
 
 	    POST /images/test/push HTTP/1.1
+	    {{ authConfig }}
 
 	 **Example response v1.1**:
 
@@ -875,7 +890,7 @@ Build an image from Dockerfile via stdin
         :statuscode 500: server error
 
 
-Get default username and email
+Get default username and email <deprecated with 1.2>
 ******************************
 
 .. http:get:: /auth
@@ -904,8 +919,8 @@ Get default username and email
         :statuscode 500: server error
 
 
-Set auth configuration
-**********************
+Check auth configuration (and store if if api < 1.2)
+****************************************************
 
 .. http:post:: /auth