|
@@ -32,15 +32,19 @@ var (
|
|
|
GIT_COMMIT string
|
|
|
)
|
|
|
|
|
|
-func ParseCommands(args ...string) error {
|
|
|
- cli := NewDockerCli("0.0.0.0", 4243)
|
|
|
+func (cli *DockerCli) getMethod(name string) (reflect.Method, bool) {
|
|
|
+ methodName := "Cmd" + strings.ToUpper(name[:1]) + strings.ToLower(name[1:])
|
|
|
+ return reflect.TypeOf(cli).MethodByName(methodName)
|
|
|
+}
|
|
|
+
|
|
|
+func ParseCommands(addr string, port int, args ...string) error {
|
|
|
+ cli := NewDockerCli(addr, port)
|
|
|
|
|
|
if len(args) > 0 {
|
|
|
- methodName := "Cmd" + strings.ToUpper(args[0][:1]) + strings.ToLower(args[0][1:])
|
|
|
- method, exists := reflect.TypeOf(cli).MethodByName(methodName)
|
|
|
+ method, exists := cli.getMethod(args[0])
|
|
|
if !exists {
|
|
|
fmt.Println("Error: Command not found:", args[0])
|
|
|
- return cli.CmdHelp(args...)
|
|
|
+ return cli.CmdHelp(args[1:]...)
|
|
|
}
|
|
|
ret := method.Func.CallSlice([]reflect.Value{
|
|
|
reflect.ValueOf(cli),
|
|
@@ -55,7 +59,19 @@ func ParseCommands(args ...string) error {
|
|
|
}
|
|
|
|
|
|
func (cli *DockerCli) CmdHelp(args ...string) error {
|
|
|
- help := "Usage: docker COMMAND [arg...]\n\nA self-sufficient runtime for linux containers.\n\nCommands:\n"
|
|
|
+ if len(args) > 0 {
|
|
|
+ method, exists := cli.getMethod(args[0])
|
|
|
+ if !exists {
|
|
|
+ fmt.Println("Error: Command not found:", args[0])
|
|
|
+ } else {
|
|
|
+ method.Func.CallSlice([]reflect.Value{
|
|
|
+ reflect.ValueOf(cli),
|
|
|
+ reflect.ValueOf([]string{"--help"}),
|
|
|
+ })[0].Interface()
|
|
|
+ return nil
|
|
|
+ }
|
|
|
+ }
|
|
|
+ help := fmt.Sprintf("Usage: docker [OPTIONS] COMMAND [arg...]\n -H=\"%s:%d\": Host:port to bind/connect to\n\nA self-sufficient runtime for linux containers.\n\nCommands:\n", cli.addr, cli.port)
|
|
|
for cmd, description := range map[string]string{
|
|
|
"attach": "Attach to a running container",
|
|
|
"build": "Build a container from Dockerfile or via stdin",
|
|
@@ -609,39 +625,13 @@ func (cli *DockerCli) CmdPush(args ...string) error {
|
|
|
return nil
|
|
|
}
|
|
|
|
|
|
- body, _, err := cli.call("GET", "/auth", nil)
|
|
|
- if err != nil {
|
|
|
- return err
|
|
|
- }
|
|
|
-
|
|
|
- var out auth.AuthConfig
|
|
|
- err = json.Unmarshal(body, &out)
|
|
|
+ username, err := cli.checkIfLogged(*registry == "", "push")
|
|
|
if err != nil {
|
|
|
return err
|
|
|
}
|
|
|
|
|
|
- // If the login failed AND we're using the index, abort
|
|
|
- if *registry == "" && out.Username == "" {
|
|
|
- if err := cli.CmdLogin(args...); err != nil {
|
|
|
- return err
|
|
|
- }
|
|
|
-
|
|
|
- body, _, err = cli.call("GET", "/auth", nil)
|
|
|
- if err != nil {
|
|
|
- return err
|
|
|
- }
|
|
|
- err = json.Unmarshal(body, &out)
|
|
|
- if err != nil {
|
|
|
- return err
|
|
|
- }
|
|
|
-
|
|
|
- if out.Username == "" {
|
|
|
- return fmt.Errorf("Please login prior to push. ('docker login')")
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
if len(strings.SplitN(name, "/", 2)) == 1 {
|
|
|
- return fmt.Errorf("Impossible to push a \"root\" repository. Please rename your repository in <user>/<repo> (ex: %s/%s)", out.Username, name)
|
|
|
+ return fmt.Errorf("Impossible to push a \"root\" repository. Please rename your repository in <user>/<repo> (ex: %s/%s)", username, name)
|
|
|
}
|
|
|
|
|
|
v := url.Values{}
|
|
@@ -672,6 +662,12 @@ func (cli *DockerCli) CmdPull(args ...string) error {
|
|
|
remote = remoteParts[0]
|
|
|
}
|
|
|
|
|
|
+ if strings.Contains(remote, "/") {
|
|
|
+ if _, err := cli.checkIfLogged(true, "pull"); err != nil {
|
|
|
+ return err
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
v := url.Values{}
|
|
|
v.Set("fromImage", remote)
|
|
|
v.Set("tag", *tag)
|
|
@@ -1161,6 +1157,40 @@ func (cli *DockerCli) CmdRun(args ...string) error {
|
|
|
return nil
|
|
|
}
|
|
|
|
|
|
+func (cli *DockerCli) checkIfLogged(condition bool, action string) (string, error) {
|
|
|
+ body, _, err := cli.call("GET", "/auth", nil)
|
|
|
+ if err != nil {
|
|
|
+ return "", err
|
|
|
+ }
|
|
|
+
|
|
|
+ var out auth.AuthConfig
|
|
|
+ err = json.Unmarshal(body, &out)
|
|
|
+ if err != nil {
|
|
|
+ return "", err
|
|
|
+ }
|
|
|
+
|
|
|
+ // If condition AND the login failed
|
|
|
+ if condition && out.Username == "" {
|
|
|
+ if err := cli.CmdLogin(""); err != nil {
|
|
|
+ return "", err
|
|
|
+ }
|
|
|
+
|
|
|
+ body, _, err = cli.call("GET", "/auth", nil)
|
|
|
+ if err != nil {
|
|
|
+ return "", err
|
|
|
+ }
|
|
|
+ err = json.Unmarshal(body, &out)
|
|
|
+ if err != nil {
|
|
|
+ return "", err
|
|
|
+ }
|
|
|
+
|
|
|
+ if out.Username == "" {
|
|
|
+ return "", fmt.Errorf("Please login prior to %s. ('docker login')", action)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return out.Username, nil
|
|
|
+}
|
|
|
+
|
|
|
func (cli *DockerCli) call(method, path string, data interface{}) ([]byte, int, error) {
|
|
|
var params io.Reader
|
|
|
if data != nil {
|
|
@@ -1171,7 +1201,7 @@ func (cli *DockerCli) call(method, path string, data interface{}) ([]byte, int,
|
|
|
params = bytes.NewBuffer(buf)
|
|
|
}
|
|
|
|
|
|
- req, err := http.NewRequest(method, fmt.Sprintf("http://%s:%d/v%f", cli.host, cli.port, API_VERSION)+path, params)
|
|
|
+ req, err := http.NewRequest(method, fmt.Sprintf("http://%s:%d/v%g%s", cli.addr, cli.port, API_VERSION, path), params)
|
|
|
if err != nil {
|
|
|
return nil, -1, err
|
|
|
}
|
|
@@ -1203,7 +1233,7 @@ func (cli *DockerCli) stream(method, path string, in io.Reader, out io.Writer) e
|
|
|
if (method == "POST" || method == "PUT") && in == nil {
|
|
|
in = bytes.NewReader([]byte{})
|
|
|
}
|
|
|
- req, err := http.NewRequest(method, fmt.Sprintf("http://%s:%d/v%f%s", cli.host, cli.port, API_VERSION, path), in)
|
|
|
+ req, err := http.NewRequest(method, fmt.Sprintf("http://%s:%d/v%g%s", cli.addr, cli.port, API_VERSION, path), in)
|
|
|
if err != nil {
|
|
|
return err
|
|
|
}
|
|
@@ -1234,12 +1264,12 @@ func (cli *DockerCli) stream(method, path string, in io.Reader, out io.Writer) e
|
|
|
}
|
|
|
|
|
|
func (cli *DockerCli) hijack(method, path string, setRawTerminal bool) error {
|
|
|
- req, err := http.NewRequest(method, fmt.Sprintf("/v%f%s", API_VERSION, path), nil)
|
|
|
+ req, err := http.NewRequest(method, fmt.Sprintf("/v%g%s", API_VERSION, path), nil)
|
|
|
if err != nil {
|
|
|
return err
|
|
|
}
|
|
|
req.Header.Set("Content-Type", "plain/text")
|
|
|
- dial, err := net.Dial("tcp", fmt.Sprintf("%s:%d", cli.host, cli.port))
|
|
|
+ dial, err := net.Dial("tcp", fmt.Sprintf("%s:%d", cli.addr, cli.port))
|
|
|
if err != nil {
|
|
|
return err
|
|
|
}
|
|
@@ -1320,8 +1350,8 @@ func Subcmd(name, signature, description string) *flag.FlagSet {
|
|
|
return flags
|
|
|
}
|
|
|
|
|
|
-func NewDockerCli(host string, port int) *DockerCli {
|
|
|
- return &DockerCli{host, port}
|
|
|
+func NewDockerCli(addr string, port int) *DockerCli {
|
|
|
+ return &DockerCli{addr, port}
|
|
|
}
|
|
|
|
|
|
type DockerCli struct {
|