-
Notifications
You must be signed in to change notification settings - Fork 67
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: Create client library for support-notifications (#626)
* feat: Create client library for support-notifications Create clients for Subscription, Notification, and Transmission APIs Close #573 Signed-off-by: weichou <[email protected]> * refactor: Rename the Notification sending func Close #573 Signed-off-by: weichou <[email protected]>
- Loading branch information
1 parent
d9f4bb2
commit ee4e77d
Showing
13 changed files
with
1,508 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,158 @@ | ||
// | ||
// Copyright (C) 2021 IOTech Ltd | ||
// | ||
// SPDX-License-Identifier: Apache-2.0 | ||
|
||
package http | ||
|
||
import ( | ||
"context" | ||
"net/url" | ||
"path" | ||
"strconv" | ||
|
||
"github.com/edgexfoundry/go-mod-core-contracts/v2/errors" | ||
"github.com/edgexfoundry/go-mod-core-contracts/v2/v2" | ||
"github.com/edgexfoundry/go-mod-core-contracts/v2/v2/clients/http/utils" | ||
"github.com/edgexfoundry/go-mod-core-contracts/v2/v2/clients/interfaces" | ||
"github.com/edgexfoundry/go-mod-core-contracts/v2/v2/dtos/common" | ||
"github.com/edgexfoundry/go-mod-core-contracts/v2/v2/dtos/requests" | ||
"github.com/edgexfoundry/go-mod-core-contracts/v2/v2/dtos/responses" | ||
) | ||
|
||
type NotificationClient struct { | ||
baseUrl string | ||
} | ||
|
||
// NewNotificationClient creates an instance of NotificationClient | ||
func NewNotificationClient(baseUrl string) interfaces.NotificationClient { | ||
return &NotificationClient{ | ||
baseUrl: baseUrl, | ||
} | ||
} | ||
|
||
// SendNotification sends new notifications. | ||
func (client *NotificationClient) SendNotification(ctx context.Context, reqs []requests.AddNotificationRequest) (res []common.BaseWithIdResponse, err errors.EdgeX) { | ||
err = utils.PostRequestWithRawData(ctx, &res, client.baseUrl+v2.ApiNotificationRoute, reqs) | ||
if err != nil { | ||
return res, errors.NewCommonEdgeXWrapper(err) | ||
} | ||
return res, nil | ||
} | ||
|
||
// NotificationById query notification by id. | ||
func (client *NotificationClient) NotificationById(ctx context.Context, id string) (res responses.NotificationResponse, err errors.EdgeX) { | ||
path := path.Join(v2.ApiNotificationRoute, v2.Id, url.QueryEscape(id)) | ||
err = utils.GetRequest(ctx, &res, client.baseUrl, path, nil) | ||
if err != nil { | ||
return res, errors.NewCommonEdgeXWrapper(err) | ||
} | ||
return res, nil | ||
} | ||
|
||
// DeleteNotificationById deletes a notification by id. | ||
func (client *NotificationClient) DeleteNotificationById(ctx context.Context, id string) (res common.BaseResponse, err errors.EdgeX) { | ||
path := path.Join(v2.ApiNotificationRoute, v2.Id, url.QueryEscape(id)) | ||
err = utils.DeleteRequest(ctx, &res, client.baseUrl, path) | ||
if err != nil { | ||
return res, errors.NewCommonEdgeXWrapper(err) | ||
} | ||
return res, nil | ||
} | ||
|
||
// NotificationsByCategory queries notifications with category, offset and limit | ||
func (client *NotificationClient) NotificationsByCategory(ctx context.Context, category string, offset int, limit int) (res responses.MultiNotificationsResponse, err errors.EdgeX) { | ||
requestPath := path.Join(v2.ApiNotificationRoute, v2.Category, url.QueryEscape(category)) | ||
requestParams := url.Values{} | ||
requestParams.Set(v2.Offset, strconv.Itoa(offset)) | ||
requestParams.Set(v2.Limit, strconv.Itoa(limit)) | ||
err = utils.GetRequest(ctx, &res, client.baseUrl, requestPath, requestParams) | ||
if err != nil { | ||
return res, errors.NewCommonEdgeXWrapper(err) | ||
} | ||
return res, nil | ||
} | ||
|
||
// NotificationsByLabel queries notifications with label, offset and limit | ||
func (client *NotificationClient) NotificationsByLabel(ctx context.Context, label string, offset int, limit int) (res responses.MultiNotificationsResponse, err errors.EdgeX) { | ||
requestPath := path.Join(v2.ApiNotificationRoute, v2.Label, url.QueryEscape(label)) | ||
requestParams := url.Values{} | ||
requestParams.Set(v2.Offset, strconv.Itoa(offset)) | ||
requestParams.Set(v2.Limit, strconv.Itoa(limit)) | ||
err = utils.GetRequest(ctx, &res, client.baseUrl, requestPath, requestParams) | ||
if err != nil { | ||
return res, errors.NewCommonEdgeXWrapper(err) | ||
} | ||
return res, nil | ||
} | ||
|
||
// NotificationsByStatus queries notifications with status, offset and limit | ||
func (client *NotificationClient) NotificationsByStatus(ctx context.Context, status string, offset int, limit int) (res responses.MultiNotificationsResponse, err errors.EdgeX) { | ||
requestPath := path.Join(v2.ApiNotificationRoute, v2.Status, url.QueryEscape(status)) | ||
requestParams := url.Values{} | ||
requestParams.Set(v2.Offset, strconv.Itoa(offset)) | ||
requestParams.Set(v2.Limit, strconv.Itoa(limit)) | ||
err = utils.GetRequest(ctx, &res, client.baseUrl, requestPath, requestParams) | ||
if err != nil { | ||
return res, errors.NewCommonEdgeXWrapper(err) | ||
} | ||
return res, nil | ||
} | ||
|
||
// NotificationsByTimeRange query notifications with time range, offset and limit | ||
func (client *NotificationClient) NotificationsByTimeRange(ctx context.Context, start int, end int, offset int, limit int) (res responses.MultiNotificationsResponse, err errors.EdgeX) { | ||
requestPath := path.Join(v2.ApiNotificationRoute, v2.Start, strconv.Itoa(start), v2.End, strconv.Itoa(end)) | ||
requestParams := url.Values{} | ||
requestParams.Set(v2.Offset, strconv.Itoa(offset)) | ||
requestParams.Set(v2.Limit, strconv.Itoa(limit)) | ||
err = utils.GetRequest(ctx, &res, client.baseUrl, requestPath, requestParams) | ||
if err != nil { | ||
return res, errors.NewCommonEdgeXWrapper(err) | ||
} | ||
return res, nil | ||
} | ||
|
||
// NotificationsBySubscriptionName query notifications with subscriptionName, offset and limit | ||
func (client *NotificationClient) NotificationsBySubscriptionName(ctx context.Context, subscriptionName string, offset int, limit int) (res responses.MultiNotificationsResponse, err errors.EdgeX) { | ||
requestPath := path.Join(v2.ApiNotificationRoute, v2.Subscription, v2.Name, url.QueryEscape(subscriptionName)) | ||
requestParams := url.Values{} | ||
requestParams.Set(v2.Offset, strconv.Itoa(offset)) | ||
requestParams.Set(v2.Limit, strconv.Itoa(limit)) | ||
err = utils.GetRequest(ctx, &res, client.baseUrl, requestPath, requestParams) | ||
if err != nil { | ||
return res, errors.NewCommonEdgeXWrapper(err) | ||
} | ||
return res, nil | ||
} | ||
|
||
// CleanupNotificationsByAge removes notifications that are older than age. And the corresponding transmissions will also be deleted. | ||
// Age is supposed in milliseconds since modified timestamp | ||
func (client *NotificationClient) CleanupNotificationsByAge(ctx context.Context, age int) (res common.BaseResponse, err errors.EdgeX) { | ||
path := path.Join(v2.ApiNotificationCleanupRoute, v2.Age, strconv.Itoa(age)) | ||
err = utils.DeleteRequest(ctx, &res, client.baseUrl, path) | ||
if err != nil { | ||
return res, errors.NewCommonEdgeXWrapper(err) | ||
} | ||
return res, nil | ||
} | ||
|
||
// CleanupNotifications removes notifications and the corresponding transmissions. | ||
func (client *NotificationClient) CleanupNotifications(ctx context.Context) (res common.BaseResponse, err errors.EdgeX) { | ||
err = utils.DeleteRequest(ctx, &res, client.baseUrl, v2.ApiNotificationCleanupRoute) | ||
if err != nil { | ||
return res, errors.NewCommonEdgeXWrapper(err) | ||
} | ||
return res, nil | ||
} | ||
|
||
// DeleteProcessedNotificationsByAge removes processed notifications that are older than age. And the corresponding transmissions will also be deleted. | ||
// Age is supposed in milliseconds since modified timestamp | ||
// Please notice that this API is only for processed notifications (status = PROCESSED). If the deletion purpose includes each kind of notifications, please refer to cleanup API. | ||
func (client *NotificationClient) DeleteProcessedNotificationsByAge(ctx context.Context, age int) (res common.BaseResponse, err errors.EdgeX) { | ||
path := path.Join(v2.ApiNotificationRoute, v2.Age, strconv.Itoa(age)) | ||
err = utils.DeleteRequest(ctx, &res, client.baseUrl, path) | ||
if err != nil { | ||
return res, errors.NewCommonEdgeXWrapper(err) | ||
} | ||
return res, nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,153 @@ | ||
// | ||
// Copyright (C) 2021 IOTech Ltd | ||
// | ||
// SPDX-License-Identifier: Apache-2.0 | ||
|
||
package http | ||
|
||
import ( | ||
"context" | ||
"net/http" | ||
"path" | ||
"strconv" | ||
"testing" | ||
|
||
"github.com/edgexfoundry/go-mod-core-contracts/v2/v2" | ||
"github.com/edgexfoundry/go-mod-core-contracts/v2/v2/dtos" | ||
"github.com/edgexfoundry/go-mod-core-contracts/v2/v2/dtos/common" | ||
"github.com/edgexfoundry/go-mod-core-contracts/v2/v2/dtos/requests" | ||
"github.com/edgexfoundry/go-mod-core-contracts/v2/v2/dtos/responses" | ||
"github.com/edgexfoundry/go-mod-core-contracts/v2/v2/models" | ||
|
||
"github.com/stretchr/testify/require" | ||
) | ||
|
||
func addNotificationRequest() requests.AddNotificationRequest { | ||
return requests.NewAddNotificationRequest( | ||
dtos.Notification{ | ||
Id: ExampleUUID, | ||
Content: "testContent", | ||
Sender: "testSender", | ||
Labels: []string{TestLabel}, | ||
Severity: models.Critical, | ||
}, | ||
) | ||
} | ||
|
||
func TestNotificationClient_SendNotification(t *testing.T) { | ||
ts := newTestServer(http.MethodPost, v2.ApiNotificationRoute, []common.BaseWithIdResponse{}) | ||
defer ts.Close() | ||
client := NewNotificationClient(ts.URL) | ||
res, err := client.SendNotification(context.Background(), []requests.AddNotificationRequest{addNotificationRequest()}) | ||
require.NoError(t, err) | ||
require.IsType(t, []common.BaseWithIdResponse{}, res) | ||
} | ||
|
||
func TestNotificationClient_NotificationById(t *testing.T) { | ||
testId := ExampleUUID | ||
path := path.Join(v2.ApiNotificationRoute, v2.Id, testId) | ||
ts := newTestServer(http.MethodGet, path, responses.NotificationResponse{}) | ||
defer ts.Close() | ||
client := NewNotificationClient(ts.URL) | ||
res, err := client.NotificationById(context.Background(), testId) | ||
require.NoError(t, err) | ||
require.IsType(t, responses.NotificationResponse{}, res) | ||
} | ||
|
||
func TestNotificationClient_NotificationsByCategory(t *testing.T) { | ||
category := TestCategory | ||
urlPath := path.Join(v2.ApiNotificationRoute, v2.Category, category) | ||
ts := newTestServer(http.MethodGet, urlPath, responses.MultiNotificationsResponse{}) | ||
defer ts.Close() | ||
client := NewNotificationClient(ts.URL) | ||
res, err := client.NotificationsByCategory(context.Background(), category, 0, 10) | ||
require.NoError(t, err) | ||
require.IsType(t, responses.MultiNotificationsResponse{}, res) | ||
} | ||
|
||
func TestNotificationClient_NotificationsByLabel(t *testing.T) { | ||
label := TestLabel | ||
urlPath := path.Join(v2.ApiNotificationRoute, v2.Label, label) | ||
ts := newTestServer(http.MethodGet, urlPath, responses.MultiNotificationsResponse{}) | ||
defer ts.Close() | ||
client := NewNotificationClient(ts.URL) | ||
res, err := client.NotificationsByLabel(context.Background(), label, 0, 10) | ||
require.NoError(t, err) | ||
require.IsType(t, responses.MultiNotificationsResponse{}, res) | ||
} | ||
|
||
func TestNotificationClient_NotificationsByStatus(t *testing.T) { | ||
status := models.Processed | ||
urlPath := path.Join(v2.ApiNotificationRoute, v2.Status, status) | ||
ts := newTestServer(http.MethodGet, urlPath, responses.MultiNotificationsResponse{}) | ||
defer ts.Close() | ||
client := NewNotificationClient(ts.URL) | ||
res, err := client.NotificationsByStatus(context.Background(), status, 0, 10) | ||
require.NoError(t, err) | ||
require.IsType(t, responses.MultiNotificationsResponse{}, res) | ||
} | ||
|
||
func TestNotificationClient_NotificationsBySubscriptionName(t *testing.T) { | ||
subscriptionName := TestSubscriptionName | ||
urlPath := path.Join(v2.ApiNotificationRoute, v2.Subscription, v2.Name, subscriptionName) | ||
ts := newTestServer(http.MethodGet, urlPath, responses.MultiNotificationsResponse{}) | ||
defer ts.Close() | ||
client := NewNotificationClient(ts.URL) | ||
res, err := client.NotificationsBySubscriptionName(context.Background(), subscriptionName, 0, 10) | ||
require.NoError(t, err) | ||
require.IsType(t, responses.MultiNotificationsResponse{}, res) | ||
} | ||
|
||
func TestNotificationClient_NotificationsByTimeRange(t *testing.T) { | ||
start := 1 | ||
end := 10 | ||
urlPath := path.Join(v2.ApiNotificationRoute, v2.Start, strconv.Itoa(start), v2.End, strconv.Itoa(end)) | ||
ts := newTestServer(http.MethodGet, urlPath, responses.MultiNotificationsResponse{}) | ||
defer ts.Close() | ||
client := NewNotificationClient(ts.URL) | ||
res, err := client.NotificationsByTimeRange(context.Background(), start, end, 0, 10) | ||
require.NoError(t, err) | ||
require.IsType(t, responses.MultiNotificationsResponse{}, res) | ||
} | ||
|
||
func TestNotificationClient_CleanupNotifications(t *testing.T) { | ||
ts := newTestServer(http.MethodDelete, v2.ApiNotificationCleanupRoute, common.BaseResponse{}) | ||
defer ts.Close() | ||
client := NewNotificationClient(ts.URL) | ||
res, err := client.CleanupNotifications(context.Background()) | ||
require.NoError(t, err) | ||
require.IsType(t, common.BaseResponse{}, res) | ||
} | ||
|
||
func TestNotificationClient_CleanupNotificationsByAge(t *testing.T) { | ||
age := 0 | ||
path := path.Join(v2.ApiNotificationCleanupRoute, v2.Age, strconv.Itoa(age)) | ||
ts := newTestServer(http.MethodDelete, path, common.BaseResponse{}) | ||
defer ts.Close() | ||
client := NewNotificationClient(ts.URL) | ||
res, err := client.CleanupNotificationsByAge(context.Background(), age) | ||
require.NoError(t, err) | ||
require.IsType(t, common.BaseResponse{}, res) | ||
} | ||
|
||
func TestNotificationClient_DeleteNotificationById(t *testing.T) { | ||
id := ExampleUUID | ||
path := path.Join(v2.ApiNotificationRoute, v2.Id, id) | ||
ts := newTestServer(http.MethodDelete, path, common.BaseResponse{}) | ||
defer ts.Close() | ||
client := NewNotificationClient(ts.URL) | ||
res, err := client.DeleteNotificationById(context.Background(), id) | ||
require.NoError(t, err) | ||
require.IsType(t, common.BaseResponse{}, res) | ||
} | ||
|
||
func TestNotificationClient_DeleteProcessedNotificationsByAge(t *testing.T) { | ||
age := 0 | ||
path := path.Join(v2.ApiNotificationRoute, v2.Age, strconv.Itoa(age)) | ||
ts := newTestServer(http.MethodDelete, path, common.BaseResponse{}) | ||
defer ts.Close() | ||
client := NewNotificationClient(ts.URL) | ||
res, err := client.DeleteProcessedNotificationsByAge(context.Background(), age) | ||
require.NoError(t, err) | ||
require.IsType(t, common.BaseResponse{}, res) | ||
} |
Oops, something went wrong.