Browse code

Merge pull request #2735 from shykes/engine-job-kill

New engine command: 'kill'

Michael Crosby authored on 2013/12/12 03:35:57
Showing 4 changed files
... ...
@@ -151,19 +151,11 @@ func postContainersKill(srv *Server, version float64, w http.ResponseWriter, r *
151 151
 	if err := parseForm(r); err != nil {
152 152
 		return err
153 153
 	}
154
-	name := vars["name"]
155
-
156
-	signal := 0
157
-	if r != nil {
158
-		if s := r.Form.Get("signal"); s != "" {
159
-			s, err := strconv.Atoi(s)
160
-			if err != nil {
161
-				return err
162
-			}
163
-			signal = s
164
-		}
154
+	job := srv.Eng.Job("kill", vars["name"])
155
+	if sig := r.Form.Get("signal"); sig != "" {
156
+		job.Args = append(job.Args, sig)
165 157
 	}
166
-	if err := srv.ContainerKill(name, signal); err != nil {
158
+	if err := job.Run(); err != nil {
167 159
 		return err
168 160
 	}
169 161
 	w.WriteHeader(http.StatusNoContent)
... ...
@@ -199,7 +199,7 @@ func TestCreateStartRestartStopStartKillRm(t *testing.T) {
199 199
 		t.Fatal(err)
200 200
 	}
201 201
 
202
-	if err := srv.ContainerKill(id, 0); err != nil {
202
+	if err := eng.Job("kill", id).Run(); err != nil {
203 203
 		t.Fatal(err)
204 204
 	}
205 205
 
... ...
@@ -105,7 +105,7 @@ func containerWaitTimeout(eng *engine.Engine, id string, t utils.Fataler) error
105 105
 }
106 106
 
107 107
 func containerKill(eng *engine.Engine, id string, t utils.Fataler) {
108
-	if err := getContainer(eng, id, t).Kill(); err != nil {
108
+	if err := eng.Job("kill", id).Run(); err != nil {
109 109
 		t.Fatal(err)
110 110
 	}
111 111
 }
... ...
@@ -22,6 +22,7 @@ import (
22 22
 	"path"
23 23
 	"path/filepath"
24 24
 	"runtime"
25
+	"strconv"
25 26
 	"strings"
26 27
 	"sync"
27 28
 	"syscall"
... ...
@@ -82,6 +83,10 @@ func jobInitApi(job *engine.Job) engine.Status {
82 82
 		job.Error(err)
83 83
 		return engine.StatusErr
84 84
 	}
85
+	if err := job.Eng.Register("kill", srv.ContainerKill); err != nil {
86
+		job.Error(err)
87
+		return engine.StatusErr
88
+	}
85 89
 	if err := job.Eng.Register("serveapi", srv.ListenAndServe); err != nil {
86 90
 		job.Error(err)
87 91
 		return engine.StatusErr
... ...
@@ -148,25 +153,43 @@ func (v *simpleVersionInfo) Version() string {
148 148
 // If no signal is given (sig 0), then Kill with SIGKILL and wait
149 149
 // for the container to exit.
150 150
 // If a signal is given, then just send it to the container and return.
151
-func (srv *Server) ContainerKill(name string, sig int) error {
151
+func (srv *Server) ContainerKill(job *engine.Job) engine.Status {
152
+	if n := len(job.Args); n < 1 || n > 2 {
153
+		job.Errorf("Usage: %s CONTAINER [SIGNAL]", job.Name)
154
+		return engine.StatusErr
155
+	}
156
+	name := job.Args[0]
157
+	var sig uint64
158
+	if len(job.Args) == 2 && job.Args[1] != "" {
159
+		var err error
160
+		// The largest legal signal is 31, so let's parse on 5 bits
161
+		sig, err = strconv.ParseUint(job.Args[1], 10, 5)
162
+		if err != nil {
163
+			job.Errorf("Invalid signal: %s", job.Args[1])
164
+			return engine.StatusErr
165
+		}
166
+	}
152 167
 	if container := srv.runtime.Get(name); container != nil {
153 168
 		// If no signal is passed, perform regular Kill (SIGKILL + wait())
154 169
 		if sig == 0 {
155 170
 			if err := container.Kill(); err != nil {
156
-				return fmt.Errorf("Cannot kill container %s: %s", name, err)
171
+				job.Errorf("Cannot kill container %s: %s", name, err)
172
+				return engine.StatusErr
157 173
 			}
158 174
 			srv.LogEvent("kill", container.ID, srv.runtime.repositories.ImageName(container.Image))
159 175
 		} else {
160 176
 			// Otherwise, just send the requested signal
161
-			if err := container.kill(sig); err != nil {
162
-				return fmt.Errorf("Cannot kill container %s: %s", name, err)
177
+			if err := container.kill(int(sig)); err != nil {
178
+				job.Errorf("Cannot kill container %s: %s", name, err)
179
+				return engine.StatusErr
163 180
 			}
164 181
 			// FIXME: Add event for signals
165 182
 		}
166 183
 	} else {
167
-		return fmt.Errorf("No such container: %s", name)
184
+		job.Errorf("No such container: %s", name)
185
+		return engine.StatusErr
168 186
 	}
169
-	return nil
187
+	return engine.StatusOK
170 188
 }
171 189
 
172 190
 func (srv *Server) ContainerExport(job *engine.Job) engine.Status {