diff options
| author | Michael Vogt <mvo@ubuntu.com> | 2022-01-11 09:33:47 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2022-01-11 09:33:47 +0100 |
| commit | 5ccd8a1921c61604d1a4847cd9bd9348da910cab (patch) | |
| tree | 85d0e139f32dda588d716ee1166e865fc7d20202 | |
| parent | 80b86a3ac52b085f114b1614c6b256132e70ffe7 (diff) | |
| parent | 7812114ccfcb061f2d2e410b87e9a3e865da56f7 (diff) | |
Merge pull request #11066 from stolowski/notifications/close-notification
usersession: implement method to close notifications via usersession REST API
| -rw-r--r-- | usersession/agent/export_test.go | 1 | ||||
| -rw-r--r-- | usersession/agent/rest_api.go | 41 | ||||
| -rw-r--r-- | usersession/agent/rest_api_test.go | 27 | ||||
| -rw-r--r-- | usersession/client/client.go | 16 | ||||
| -rw-r--r-- | usersession/client/client_test.go | 17 |
5 files changed, 102 insertions, 0 deletions
diff --git a/usersession/agent/export_test.go b/usersession/agent/export_test.go index 027381d370..b0baf18c21 100644 --- a/usersession/agent/export_test.go +++ b/usersession/agent/export_test.go @@ -28,6 +28,7 @@ var ( SessionInfoCmd = sessionInfoCmd ServiceControlCmd = serviceControlCmd PendingRefreshNotificationCmd = pendingRefreshNotificationCmd + FinishRefreshNotificationCmd = finishRefreshNotificationCmd ) func MockStopTimeouts(stop, kill time.Duration) (restore func()) { diff --git a/usersession/agent/rest_api.go b/usersession/agent/rest_api.go index 2a44096402..d5c7ed3c3a 100644 --- a/usersession/agent/rest_api.go +++ b/usersession/agent/rest_api.go @@ -36,6 +36,7 @@ import ( "github.com/snapcore/snapd/i18n" "github.com/snapcore/snapd/systemd" "github.com/snapcore/snapd/timeout" + "github.com/snapcore/snapd/usersession/client" ) var restApi = []*Command{ @@ -65,6 +66,11 @@ var ( Path: "/v1/notifications/pending-refresh", POST: postPendingRefreshNotification, } + + finishRefreshNotificationCmd = &Command{ + Path: "/v1/notifications/finish-refresh", + POST: postRefreshFinishedNotification, + } ) func sessionInfo(c *Command, r *http.Request) Response { @@ -305,3 +311,38 @@ func postPendingRefreshNotification(c *Command, r *http.Request) Response { } return SyncResponse(nil) } + +func postRefreshFinishedNotification(c *Command, r *http.Request) Response { + if ok, resp := validateJSONRequest(r); !ok { + return resp + } + + decoder := json.NewDecoder(r.Body) + + var finishRefresh client.FinishedSnapRefreshInfo + if err := decoder.Decode(&finishRefresh); err != nil { + return BadRequest("cannot decode request body into finish refresh notification info: %v", err) + } + + // Note that since the connection is shared, we are not closing it. + if c.s.bus == nil { + return SyncResponse(&resp{ + Type: ResponseTypeError, + Status: 500, + Result: &errorResult{ + Message: "cannot connect to the session bus", + }, + }) + } + + if err := c.s.notificationMgr.CloseNotification(notification.ID(finishRefresh.InstanceName)); err != nil { + return SyncResponse(&resp{ + Type: ResponseTypeError, + Status: 500, + Result: &errorResult{ + Message: fmt.Sprintf("cannot send close notification message: %v", err), + }, + }) + } + return SyncResponse(nil) +} diff --git a/usersession/agent/rest_api_test.go b/usersession/agent/rest_api_test.go index 67e3b9024b..b3ab28b2ae 100644 --- a/usersession/agent/rest_api_test.go +++ b/usersession/agent/rest_api_test.go @@ -596,3 +596,30 @@ func (s *restSuite) TestPostPendingRefreshNotificationNotificationServerFailure( c.Check(rsp.Type, Equals, agent.ResponseTypeError) c.Check(rsp.Result, DeepEquals, map[string]interface{}{"message": "cannot send notification message: org.freedesktop.DBus.Error.Failed"}) } + +func (s *restSuite) testPostFinishRefreshNotificationBody(c *C, refreshInfo *client.FinishedSnapRefreshInfo) { + reqBody, err := json.Marshal(refreshInfo) + c.Assert(err, IsNil) + req := httptest.NewRequest("POST", "/v1/notifications/finish-refresh", bytes.NewBuffer(reqBody)) + req.Header.Set("Content-Type", "application/json") + rec := httptest.NewRecorder() + agent.FinishRefreshNotificationCmd.POST(agent.PendingRefreshNotificationCmd, req).ServeHTTP(rec, req) + c.Check(rec.Code, Equals, 200) + c.Check(rec.HeaderMap.Get("Content-Type"), Equals, "application/json") + + var rsp resp + c.Assert(json.Unmarshal(rec.Body.Bytes(), &rsp), IsNil) + c.Check(rsp.Type, Equals, agent.ResponseTypeSync) + c.Check(rsp.Result, IsNil) +} + +func (s *restSuite) TestPostCloseRefreshNotification(c *C) { + // add a notification first + refreshInfo := &client.PendingSnapRefreshInfo{InstanceName: "some-snap"} + s.testPostPendingRefreshNotificationBody(c, refreshInfo) + + closeInfo := &client.FinishedSnapRefreshInfo{InstanceName: "some-snap"} + s.testPostFinishRefreshNotificationBody(c, closeInfo) + notifications := s.notify.GetAll() + c.Assert(notifications, HasLen, 0) +} diff --git a/usersession/client/client.go b/usersession/client/client.go index 9554257fcc..757de57a16 100644 --- a/usersession/client/client.go +++ b/usersession/client/client.go @@ -325,3 +325,19 @@ func (client *Client) PendingRefreshNotification(ctx context.Context, refreshInf _, err = client.doMany(ctx, "POST", "/v1/notifications/pending-refresh", nil, headers, reqBody) return err } + +// FinishedSnapRefreshInfo holds information about a finished refresh provided to userd. +type FinishedSnapRefreshInfo struct { + InstanceName string `json:"instance-name"` +} + +// FinishRefreshNotification closes notification about a snap refresh. +func (client *Client) FinishRefreshNotification(ctx context.Context, closeInfo *FinishedSnapRefreshInfo) error { + headers := map[string]string{"Content-Type": "application/json"} + reqBody, err := json.Marshal(closeInfo) + if err != nil { + return err + } + _, err = client.doMany(ctx, "POST", "/v1/notifications/finish-refresh", nil, headers, reqBody) + return err +} diff --git a/usersession/client/client_test.go b/usersession/client/client_test.go index 299cf5c9b2..ddaefeb92f 100644 --- a/usersession/client/client_test.go +++ b/usersession/client/client_test.go @@ -22,6 +22,7 @@ package client_test import ( "context" "fmt" + "io/ioutil" "net" "net/http" "os" @@ -462,6 +463,22 @@ func (s *clientSuite) TestPendingRefreshNotification(c *C) { c.Check(atomic.LoadInt32(&n), Equals, int32(2)) } +func (s *clientSuite) TestFinishRefreshNotification(c *C) { + var n int32 + s.handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + atomic.AddInt32(&n, 1) + c.Assert(r.URL.Path, Equals, "/v1/notifications/finish-refresh") + body, err := ioutil.ReadAll(r.Body) + c.Check(err, IsNil) + c.Check(string(body), DeepEquals, `{"instance-name":"some-snap"}`) + }) + err := s.cli.FinishRefreshNotification(context.Background(), &client.FinishedSnapRefreshInfo{InstanceName: "some-snap"}) + c.Assert(err, IsNil) + // two calls because clientSuite simulates two user sessions (two + // snapd-session-agent.socket sockets). + c.Check(atomic.LoadInt32(&n), Equals, int32(2)) +} + func (s *clientSuite) TestPendingRefreshNotificationOneClient(c *C) { cli := client.NewForUids(1000) var n int32 |
