Merge lp:~sergiusens/snapweb/deletePackage into lp:~snappy-dev/snapweb/trunk
- deletePackage
- Merge into trunk
Status: | Merged |
---|---|
Approved by: | Sergio Schvezov |
Approved revision: | 122 |
Merged at revision: | 120 |
Proposed branch: | lp:~sergiusens/snapweb/deletePackage |
Merge into: | lp:~snappy-dev/snapweb/trunk |
Prerequisite: | lp:~chipaca/snapweb/json-responses |
Diff against target: |
376 lines (+136/-56) 5 files modified
snappy/converge.go (+35/-18) snappy/converge_test.go (+3/-3) snappy/handlers.go (+47/-19) webprogress/meter.go (+43/-8) webprogress/progress.go (+8/-8) |
To merge this branch: | bzr merge lp:~sergiusens/snapweb/deletePackage |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Sergio Schvezov | Approve | ||
John Lenton (community) | Approve | ||
Stephen Stewart (community) | Approve | ||
Review via email: mp+258394@code.launchpad.net |
This proposal supersedes a proposal from 2015-05-06.
Commit message
Implement package removal by adding DELETE to /v2/packages/
Description of the change
John Lenton (chipaca) wrote : | # |
Good!
We'll want to update to progress as per lp:~mvo/snappy/snappy-refactor-progress-pkgname before adding much more though.
Snappy Tarmac (snappydevtarmac) wrote : | # |
There are additional revisions which have not been approved in review. Please seek review and approval of these new revisions.
Sergio Schvezov (sergiusens) wrote : | # |
Out of sync approve
Snappy Tarmac (snappydevtarmac) wrote : | # |
The attempt to merge lp:~sergiusens/webdm/deletePackage into lp:webdm failed. Below is the output from the failed tests.
Checking formatting
Installing godeps
Install golint
Obtaining dependencies
update github.
update github.
github.
update github.
github.
update gopkg.in/check.v1 failed; trying to fetch newer version
github.
update gopkg.in/yaml.v2 failed; trying to fetch newer version
gopkg.in/check.v1 now at 64131543e7896d5
update launchpad.
gopkg.in/yaml.v2 now at 49c95bdc2184325
update github.
launchpad.
update github.
github.
update github.
github.
github.
Building
Running tests from /tmp/tmp.
? launchpad.
? launchpad.
FAIL launchpad.
? launchpad.
# we always run in a fresh dir in tarmac
export GOPATH=$(mktemp -d)
trap 'rm -rf "$GOPATH"' EXIT
# this is a hack, but not sure tarmac is golang friendly
mkdir -p $GOPATH/
cp -a . $GOPATH/
cd $GOPATH/
./run-checks
gopkg.in/yaml.v2
launchpad.
github.
github.
github.
github.
launchpad.
launchpad.
launchpad.
github.
launchpad.
launchpad.
launchpad.
github.
launchpad.
launchpad.
launchpad.
launchpad.
launchpad.
launchpad.
launchpad.
# launchpad.
snappy/
snappy/
snappy/
Snappy Tarmac (snappydevtarmac) wrote : | # |
The attempt to merge lp:~sergiusens/webdm/deletePackage into lp:webdm failed. Below is the output from the failed tests.
Checking formatting
Installing godeps
Install golint
Obtaining dependencies
update github.
update github.
github.
update github.
github.
update gopkg.in/check.v1 failed; trying to fetch newer version
github.
update gopkg.in/yaml.v2 failed; trying to fetch newer version
gopkg.in/check.v1 now at 64131543e7896d5
update launchpad.
gopkg.in/yaml.v2 now at 49c95bdc2184325
update github.
launchpad.
update github.
github.
update github.
github.
github.
Building
Running tests from /tmp/tmp.
? launchpad.
? launchpad.
FAIL launchpad.
? launchpad.
# we always run in a fresh dir in tarmac
export GOPATH=$(mktemp -d)
trap 'rm -rf "$GOPATH"' EXIT
# this is a hack, but not sure tarmac is golang friendly
mkdir -p $GOPATH/
cp -a . $GOPATH/
cd $GOPATH/
./run-checks
gopkg.in/yaml.v2
launchpad.
github.
github.
github.
github.
launchpad.
launchpad.
launchpad.
github.
launchpad.
launchpad.
launchpad.
github.
launchpad.
launchpad.
launchpad.
launchpad.
launchpad.
launchpad.
launchpad.
# launchpad.
snappy/
snappy/
snappy/
Sergio Schvezov (sergiusens) : | # |
Sergio Schvezov (sergiusens) wrote : | # |
there was an out of order merge
Snappy Tarmac (snappydevtarmac) wrote : | # |
The attempt to merge lp:~sergiusens/webdm/deletePackage into lp:webdm failed. Below is the output from the failed tests.
Checking formatting
Installing godeps
Install golint
Obtaining dependencies
update github.
update github.
github.
update github.
github.
update gopkg.in/check.v1 failed; trying to fetch newer version
github.
update gopkg.in/yaml.v2 failed; trying to fetch newer version
gopkg.in/check.v1 now at 64131543e7896d5
update launchpad.
gopkg.in/yaml.v2 now at 49c95bdc2184325
update github.
launchpad.
update github.
github.
update github.
github.
github.
Building
Running tests from /tmp/tmp.
? launchpad.
? launchpad.
FAIL launchpad.
? launchpad.
# we always run in a fresh dir in tarmac
export GOPATH=$(mktemp -d)
trap 'rm -rf "$GOPATH"' EXIT
# this is a hack, but not sure tarmac is golang friendly
mkdir -p $GOPATH/
cp -a . $GOPATH/
cd $GOPATH/
./run-checks
gopkg.in/yaml.v2
launchpad.
github.
github.
github.
github.
launchpad.
launchpad.
launchpad.
github.
launchpad.
launchpad.
launchpad.
github.
launchpad.
launchpad.
launchpad.
launchpad.
launchpad.
launchpad.
launchpad.
# launchpad.
snappy/
snappy/
snappy/
- 122. By Sergio Schvezov
-
Updating tests
Sergio Schvezov (sergiusens) : | # |
Preview Diff
1 | === modified file 'snappy/converge.go' |
2 | --- snappy/converge.go 2015-05-06 15:03:28 +0000 |
3 | +++ snappy/converge.go 2015-05-06 17:14:56 +0000 |
4 | @@ -29,21 +29,21 @@ |
5 | ) |
6 | |
7 | type snapPkg struct { |
8 | - Name string `json:"name"` |
9 | - Origin string `json:"origin"` |
10 | - Version string `json:"version"` |
11 | - Vendor string `json:"vendor"` |
12 | - Description string `json:"description"` |
13 | - Icon string `json:"icon"` |
14 | - Status string `json:"status"` |
15 | - Message string `json:"message,omitempty"` |
16 | - IsError bool `json:"-"` |
17 | - Progress float64 `json:"progress,omitempty"` |
18 | - InstalledSize int64 `json:"installed_size,omitempty"` |
19 | - DownloadSize int64 `json:"download_size,omitempty"` |
20 | - Type snappy.SnapType `json:"type,omitempty"` |
21 | - UIPort uint64 `json:"ui_port,omitempty"` |
22 | - UIUri string `json:"ui_uri,omitempty"` |
23 | + Name string `json:"name"` |
24 | + Origin string `json:"origin"` |
25 | + Version string `json:"version"` |
26 | + Vendor string `json:"vendor"` |
27 | + Description string `json:"description"` |
28 | + Icon string `json:"icon"` |
29 | + Status webprogress.Status `json:"status"` |
30 | + Message string `json:"message,omitempty"` |
31 | + IsError bool `json:"-"` |
32 | + Progress float64 `json:"progress,omitempty"` |
33 | + InstalledSize int64 `json:"installed_size,omitempty"` |
34 | + DownloadSize int64 `json:"download_size,omitempty"` |
35 | + Type snappy.SnapType `json:"type,omitempty"` |
36 | + UIPort uint64 `json:"ui_port,omitempty"` |
37 | + UIUri string `json:"ui_uri,omitempty"` |
38 | } |
39 | |
40 | type response struct { |
41 | @@ -111,6 +111,23 @@ |
42 | return mergeSnaps(installedSnapQs, remoteSnapQs, installedOnly), nil |
43 | } |
44 | |
45 | +func (h *Handler) doRemovePackage(progress *webprogress.WebProgress, pkgName string) { |
46 | + err := snappy.Remove(pkgName, 0, progress) |
47 | + progress.ErrorChan <- err |
48 | + close(progress.ErrorChan) |
49 | +} |
50 | + |
51 | +func (h *Handler) removePackage(pkgName string) error { |
52 | + progress, err := h.statusTracker.Add(pkgName, webprogress.OperationRemove) |
53 | + if err != nil { |
54 | + return err |
55 | + } |
56 | + |
57 | + go h.doRemovePackage(progress, pkgName) |
58 | + |
59 | + return nil |
60 | +} |
61 | + |
62 | func (h *Handler) doInstallPackage(progress *webprogress.WebProgress, pkgName string) { |
63 | _, err := snappy.Install(pkgName, 0, progress) |
64 | progress.ErrorChan <- err |
65 | @@ -118,7 +135,7 @@ |
66 | } |
67 | |
68 | func (h *Handler) installPackage(pkgName string) error { |
69 | - progress, err := h.installStatus.Add(pkgName) |
70 | + progress, err := h.statusTracker.Add(pkgName, webprogress.OperationInstall) |
71 | if err != nil { |
72 | return err |
73 | } |
74 | @@ -197,10 +214,10 @@ |
75 | snap.DownloadSize = snapQ.DownloadSize() |
76 | } |
77 | |
78 | - if stat, ok := h.installStatus.Get(snap.Name); ok { |
79 | + if stat, ok := h.statusTracker.Get(snap.Name); ok { |
80 | snap.Status = stat.Status |
81 | if stat.Done() { |
82 | - defer h.installStatus.Remove(snap.Name) |
83 | + defer h.statusTracker.Remove(snap.Name) |
84 | |
85 | if stat.Error != nil { |
86 | snap.Message = stat.Error.Error() |
87 | |
88 | === modified file 'snappy/converge_test.go' |
89 | --- snappy/converge_test.go 2015-05-06 12:49:52 +0000 |
90 | +++ snappy/converge_test.go 2015-05-06 17:14:56 +0000 |
91 | @@ -35,7 +35,7 @@ |
92 | |
93 | func (s *PayloadSuite) SetUpTest(c *C) { |
94 | os.Setenv("SNAP_APP_DATA_PATH", c.MkDir()) |
95 | - s.h.installStatus = webprogress.New() |
96 | + s.h.statusTracker = webprogress.New() |
97 | } |
98 | |
99 | func (s *PayloadSuite) TestPayloadWithNoServices(c *C) { |
100 | @@ -106,7 +106,7 @@ |
101 | |
102 | func (s *MergeSuite) SetUpTest(c *C) { |
103 | os.Setenv("SNAP_APP_DATA_PATH", c.MkDir()) |
104 | - s.h.installStatus = webprogress.New() |
105 | + s.h.statusTracker = webprogress.New() |
106 | } |
107 | |
108 | func (s *MergeSuite) TestOneInstalledAndNoRemote(c *C) { |
109 | @@ -213,7 +213,7 @@ |
110 | } |
111 | |
112 | func (s *MergeSuite) TestManyInstalledAndManyRemotesSomeInstalling(c *C) { |
113 | - s.h.installStatus.Add("app4.ubuntu") |
114 | + s.h.statusTracker.Add("app4.ubuntu", webprogress.OperationInstall) |
115 | |
116 | installed := []snapPkg{ |
117 | s.h.snapQueryToPayload(newFakePart("app1.canonical", "1.0", true)), |
118 | |
119 | === modified file 'snappy/handlers.go' |
120 | --- snappy/handlers.go 2015-05-06 10:24:29 +0000 |
121 | +++ snappy/handlers.go 2015-05-06 17:14:56 +0000 |
122 | @@ -32,13 +32,13 @@ |
123 | |
124 | // Handler implements snappy's packages api. |
125 | type Handler struct { |
126 | - installStatus *webprogress.Status |
127 | + statusTracker *webprogress.StatusTracker |
128 | } |
129 | |
130 | // NewHandler creates an instance that implements snappy's packages api. |
131 | func NewHandler() *Handler { |
132 | return &Handler{ |
133 | - installStatus: webprogress.New(), |
134 | + statusTracker: webprogress.New(), |
135 | } |
136 | } |
137 | |
138 | @@ -101,18 +101,54 @@ |
139 | vars := mux.Vars(r) |
140 | pkgName := vars["pkg"] |
141 | |
142 | - var msg string |
143 | - var status int |
144 | - |
145 | err := h.installPackage(pkgName) |
146 | - |
147 | + msg, status := respond(err) |
148 | + |
149 | + response := response{Message: msg, Package: pkgName} |
150 | + bs, err := json.Marshal(response) |
151 | + if err != nil { |
152 | + // giving up on json |
153 | + w.WriteHeader(http.StatusInternalServerError) |
154 | + fmt.Fprintf(w, "Error: %s", err) |
155 | + log.Print(err) |
156 | + return |
157 | + } |
158 | + |
159 | + w.WriteHeader(status) |
160 | + w.Write(bs) |
161 | +} |
162 | + |
163 | +func (h *Handler) remove(w http.ResponseWriter, r *http.Request) { |
164 | + w.Header().Set("Content-Type", "application/json") |
165 | + // Get the Key. |
166 | + vars := mux.Vars(r) |
167 | + pkgName := vars["pkg"] |
168 | + |
169 | + err := h.removePackage(pkgName) |
170 | + msg, status := respond(err) |
171 | + |
172 | + response := response{Message: msg, Package: pkgName} |
173 | + bs, err := json.Marshal(response) |
174 | + if err != nil { |
175 | + // giving up on json |
176 | + w.WriteHeader(http.StatusInternalServerError) |
177 | + fmt.Fprintf(w, "Error: %s", err) |
178 | + log.Print(err) |
179 | + return |
180 | + } |
181 | + |
182 | + w.WriteHeader(status) |
183 | + w.Write(bs) |
184 | +} |
185 | + |
186 | +func respond(err error) (msg string, status int) { |
187 | switch err { |
188 | case snappy.ErrAlreadyInstalled: |
189 | status = http.StatusOK |
190 | msg = "Installed" |
191 | case webprogress.ErrPackageInstallInProgress: |
192 | status = http.StatusBadRequest |
193 | - msg = "Installation in progress" |
194 | + msg = "Operation in progress" |
195 | case snappy.ErrPackageNotFound: |
196 | status = http.StatusNotFound |
197 | msg = "Package not found" |
198 | @@ -124,18 +160,7 @@ |
199 | msg = "Processing error" |
200 | } |
201 | |
202 | - response := response{Message: msg, Package: pkgName} |
203 | - bs, err := json.Marshal(response) |
204 | - if err != nil { |
205 | - // giving up on json |
206 | - w.WriteHeader(http.StatusInternalServerError) |
207 | - fmt.Fprintf(w, "Error: %s", err) |
208 | - log.Print(err) |
209 | - return |
210 | - } |
211 | - |
212 | - w.WriteHeader(status) |
213 | - w.Write(bs) |
214 | + return msg, status |
215 | } |
216 | |
217 | // MakeMuxer sets up the handlers multiplexing to handle requests against snappy's |
218 | @@ -158,5 +183,8 @@ |
219 | // Add a package |
220 | m.HandleFunc("/{pkg}", h.add).Methods("PUT") |
221 | |
222 | + // Remove a package |
223 | + m.HandleFunc("/{pkg}", h.remove).Methods("DELETE") |
224 | + |
225 | return m |
226 | } |
227 | |
228 | === modified file 'webprogress/meter.go' |
229 | --- webprogress/meter.go 2015-05-06 15:54:38 +0000 |
230 | +++ webprogress/meter.go 2015-05-06 17:14:56 +0000 |
231 | @@ -19,13 +19,28 @@ |
232 | |
233 | import "launchpad.net/snappy/progress" |
234 | |
235 | +// Operation indicates the desired operation to perform |
236 | +type Operation uint |
237 | + |
238 | +const ( |
239 | + // OperationInstall indicates that a package needs installing |
240 | + OperationInstall Operation = iota |
241 | + // OperationRemove indicates that a package needs uninstalling |
242 | + OperationRemove |
243 | +) |
244 | + |
245 | +// Status indicates the status a package is in. |
246 | +type Status string |
247 | + |
248 | const ( |
249 | // StatusInstalled indicates the package is in an installed state. |
250 | - StatusInstalled = "installed" |
251 | + StatusInstalled Status = "installed" |
252 | // StatusUninstalled indicates the package is in an uninstalled state. |
253 | - StatusUninstalled = "uninstalled" |
254 | + StatusUninstalled Status = "uninstalled" |
255 | // StatusInstalling indicates the package is in an installing state. |
256 | - StatusInstalling = "installing" |
257 | + StatusInstalling Status = "installing" |
258 | + // StatusUninstalling indicates the package is in an uninstalling state. |
259 | + StatusUninstalling Status = "uninstalling" |
260 | ) |
261 | |
262 | // WebProgress show progress on the terminal |
263 | @@ -33,18 +48,30 @@ |
264 | progress.Meter |
265 | total float64 |
266 | current float64 |
267 | - Status string |
268 | + Status Status |
269 | statusMessage string |
270 | notificationMessage string |
271 | Error error |
272 | ErrorChan chan error |
273 | + operation Operation |
274 | } |
275 | |
276 | // NewWebProgress returns a new WebProgress type |
277 | -func NewWebProgress() *WebProgress { |
278 | +func NewWebProgress(op Operation) *WebProgress { |
279 | + var status Status |
280 | + switch op { |
281 | + case OperationInstall: |
282 | + status = StatusInstalling |
283 | + case OperationRemove: |
284 | + status = StatusUninstalling |
285 | + default: |
286 | + panic("Not a valid Operation") |
287 | + } |
288 | + |
289 | t := &WebProgress{ |
290 | ErrorChan: make(chan error), |
291 | - Status: StatusInstalling, |
292 | + Status: status, |
293 | + operation: op, |
294 | } |
295 | |
296 | go func() { |
297 | @@ -54,7 +81,16 @@ |
298 | t.Status = StatusUninstalled |
299 | t.Error = err |
300 | } else { |
301 | - t.Status = StatusInstalled |
302 | + var status Status |
303 | + switch op { |
304 | + case OperationInstall: |
305 | + status = StatusInstalled |
306 | + case OperationRemove: |
307 | + status = StatusUninstalled |
308 | + default: |
309 | + panic("Not a valid Operation") |
310 | + } |
311 | + t.Status = status |
312 | } |
313 | }() |
314 | |
315 | @@ -64,7 +100,6 @@ |
316 | // Start starts showing progress |
317 | func (t *WebProgress) Start(pkgName string, total float64) { |
318 | t.total = total |
319 | - t.Status = StatusInstalling |
320 | } |
321 | |
322 | // Set sets the progress to the current value |
323 | |
324 | === modified file 'webprogress/progress.go' |
325 | --- webprogress/progress.go 2015-05-03 20:46:10 +0000 |
326 | +++ webprogress/progress.go 2015-05-06 17:14:56 +0000 |
327 | @@ -28,19 +28,19 @@ |
328 | ErrPackageInstallInProgress = errors.New("package installion in progress") |
329 | ) |
330 | |
331 | -// Status holds the state of all operations that require progress information. |
332 | -type Status struct { |
333 | +// StatusTracker holds the state of all operations that require progress information. |
334 | +type StatusTracker struct { |
335 | status map[string]*WebProgress |
336 | l sync.Mutex |
337 | } |
338 | |
339 | // New creates a new Status. |
340 | -func New() *Status { |
341 | - return &Status{status: make(map[string]*WebProgress)} |
342 | +func New() *StatusTracker { |
343 | + return &StatusTracker{status: make(map[string]*WebProgress)} |
344 | } |
345 | |
346 | // Add add pkg to the list of progresses to track, it is idempotent |
347 | -func (i *Status) Add(pkg string) (*WebProgress, error) { |
348 | +func (i *StatusTracker) Add(pkg string, op Operation) (*WebProgress, error) { |
349 | i.l.Lock() |
350 | defer i.l.Unlock() |
351 | |
352 | @@ -48,14 +48,14 @@ |
353 | return nil, ErrPackageInstallInProgress |
354 | } |
355 | |
356 | - i.status[pkg] = NewWebProgress() |
357 | + i.status[pkg] = NewWebProgress(op) |
358 | |
359 | return i.status[pkg], nil |
360 | } |
361 | |
362 | // Remove removes pkg to the list of progresses to track, it is a no op |
363 | // to remove multiple times. |
364 | -func (i *Status) Remove(pkg string) { |
365 | +func (i *StatusTracker) Remove(pkg string) { |
366 | i.l.Lock() |
367 | defer i.l.Unlock() |
368 | |
369 | @@ -63,7 +63,7 @@ |
370 | } |
371 | |
372 | // Get returns a *WebProgress corresponding to pkg or nil if not tracked. |
373 | -func (i *Status) Get(pkg string) (*WebProgress, bool) { |
374 | +func (i *StatusTracker) Get(pkg string) (*WebProgress, bool) { |
375 | i.l.Lock() |
376 | defer i.l.Unlock() |
377 |
wfm