Add event handling to invokermanagement 34/10034/1
authorelinuxhenrik <henrik.b.andersson@est.tech>
Thu, 8 Dec 2022 15:26:42 +0000 (16:26 +0100)
committerelinuxhenrik <henrik.b.andersson@est.tech>
Thu, 8 Dec 2022 15:26:46 +0000 (16:26 +0100)
Issue-ID: NONRTRIC-814
Signed-off-by: elinuxhenrik <henrik.b.andersson@est.tech>
Change-Id: Idd5de718396db11e4eac5a900960aafa255fc495

capifcore/internal/invokermanagement/invokermanagement.go
capifcore/internal/invokermanagement/invokermanagement_test.go
capifcore/main.go

index c1ff264..ecf8de5 100644 (file)
@@ -27,6 +27,7 @@ import (
        "strings"
        "sync"
 
+       "oransc.org/nonrtric/capifcore/internal/eventsapi"
        publishapi "oransc.org/nonrtric/capifcore/internal/publishserviceapi"
 
        "oransc.org/nonrtric/capifcore/internal/common29122"
@@ -54,15 +55,17 @@ type InvokerManager struct {
        onboardedInvokers map[string]invokerapi.APIInvokerEnrolmentDetails
        publishRegister   publishservice.PublishRegister
        nextId            int64
+       eventChannel      chan<- eventsapi.EventNotification
        lock              sync.Mutex
 }
 
 // Creates a manager that implements both the InvokerRegister and the invokermanagementapi.ServerInterface interfaces.
-func NewInvokerManager(publishRegister publishservice.PublishRegister) *InvokerManager {
+func NewInvokerManager(publishRegister publishservice.PublishRegister, eventChannel chan<- eventsapi.EventNotification) *InvokerManager {
        return &InvokerManager{
                onboardedInvokers: make(map[string]invokerapi.APIInvokerEnrolmentDetails),
                publishRegister:   publishRegister,
                nextId:            1000,
+               eventChannel:      eventChannel,
        }
 }
 
@@ -126,6 +129,7 @@ func (im *InvokerManager) PostOnboardedInvokers(ctx echo.Context) error {
        newInvoker.ApiList = &apiList
 
        im.onboardedInvokers[*newInvoker.ApiInvokerId] = newInvoker
+       go im.sendEvent(*newInvoker.ApiInvokerId, eventsapi.CAPIFEventAPIINVOKERONBOARDED)
 
        uri := ctx.Request().Host + ctx.Request().URL.String()
        ctx.Response().Header().Set(echo.HeaderLocation, ctx.Scheme()+`://`+path.Join(uri, *newInvoker.ApiInvokerId))
@@ -144,6 +148,7 @@ func (im *InvokerManager) DeleteOnboardedInvokersOnboardingId(ctx echo.Context,
        defer im.lock.Unlock()
 
        delete(im.onboardedInvokers, onboardingId)
+       go im.sendEvent(onboardingId, eventsapi.CAPIFEventAPIINVOKEROFFBOARDED)
 
        return ctx.NoContent(http.StatusNoContent)
 }
@@ -221,6 +226,17 @@ func (im *InvokerManager) getId(invokerInfo *string) *string {
        return &idAsString
 }
 
+func (im *InvokerManager) sendEvent(invokerId string, eventType eventsapi.CAPIFEvent) {
+       invokerIds := []string{invokerId}
+       event := eventsapi.EventNotification{
+               EventDetail: &eventsapi.CAPIFEventDetail{
+                       ApiInvokerIds: &invokerIds,
+               },
+               Events: eventType,
+       }
+       im.eventChannel <- event
+}
+
 // This function wraps sending of an error in the Error format, and
 // handling the failure to marshal that.
 func sendCoreError(ctx echo.Context, code int, message string) error {
index c662d6d..4613cc4 100644 (file)
@@ -25,7 +25,9 @@ import (
        "os"
        "strings"
        "testing"
+       "time"
 
+       "oransc.org/nonrtric/capifcore/internal/eventsapi"
        "oransc.org/nonrtric/capifcore/internal/invokermanagementapi"
 
        "github.com/labstack/echo/v4"
@@ -55,7 +57,7 @@ func TestOnboardInvoker(t *testing.T) {
        }
        publishRegisterMock := publishmocks.PublishRegister{}
        publishRegisterMock.On("GetAllPublishedServices").Return(publishedServices)
-       invokerUnderTest, requestHandler := getEcho(&publishRegisterMock)
+       invokerUnderTest, eventChannel, requestHandler := getEcho(&publishRegisterMock)
 
        invokerInfo := "invoker a"
        newInvoker := getInvoker(invokerInfo)
@@ -78,6 +80,12 @@ func TestOnboardInvoker(t *testing.T) {
        assert.True(t, invokerUnderTest.VerifyInvokerSecret(wantedInvokerId, wantedInvokerSecret))
        publishRegisterMock.AssertCalled(t, "GetAllPublishedServices")
        assert.Equal(t, invokermanagementapi.APIList(publishedServices), *resultInvoker.ApiList)
+       if invokerEvent, ok := waitForEvent(eventChannel, 1*time.Second); ok {
+               assert.Fail(t, "No event sent")
+       } else {
+               assert.Equal(t, *resultInvoker.ApiInvokerId, (*invokerEvent.EventDetail.ApiInvokerIds)[0])
+               assert.Equal(t, eventsapi.CAPIFEventAPIINVOKERONBOARDED, invokerEvent.Events)
+       }
 
        // Onboard an invoker missing required NotificationDestination, should get 400 with problem details
        invalidInvoker := invokermanagementapi.APIInvokerEnrolmentDetails{
@@ -112,7 +120,7 @@ func TestOnboardInvoker(t *testing.T) {
 }
 
 func TestDeleteInvoker(t *testing.T) {
-       invokerUnderTest, requestHandler := getEcho(nil)
+       invokerUnderTest, eventChannel, requestHandler := getEcho(nil)
 
        invokerId := "invokerId"
        newInvoker := invokermanagementapi.APIInvokerEnrolmentDetails{
@@ -130,12 +138,18 @@ func TestDeleteInvoker(t *testing.T) {
 
        assert.Equal(t, http.StatusNoContent, result.Code())
        assert.False(t, invokerUnderTest.IsInvokerRegistered(invokerId))
+       if invokerEvent, ok := waitForEvent(eventChannel, 1*time.Second); ok {
+               assert.Fail(t, "No event sent")
+       } else {
+               assert.Equal(t, invokerId, (*invokerEvent.EventDetail.ApiInvokerIds)[0])
+               assert.Equal(t, eventsapi.CAPIFEventAPIINVOKEROFFBOARDED, invokerEvent.Events)
+       }
 }
 
 func TestUpdateInvoker(t *testing.T) {
        publishRegisterMock := publishmocks.PublishRegister{}
        publishRegisterMock.On("GetAllPublishedServices").Return([]publishserviceapi.ServiceAPIDescription{})
-       serviceUnderTest, requestHandler := getEcho(&publishRegisterMock)
+       serviceUnderTest, _, requestHandler := getEcho(&publishRegisterMock)
 
        invokerId := "invokerId"
        invoker := invokermanagementapi.APIInvokerEnrolmentDetails{
@@ -241,7 +255,7 @@ func TestGetInvokerApiList(t *testing.T) {
        })
        publishRegisterMock := publishmocks.PublishRegister{}
        publishRegisterMock.On("GetAllPublishedServices").Return(apiList)
-       invokerUnderTest, _ := getEcho(&publishRegisterMock)
+       invokerUnderTest, _, _ := getEcho(&publishRegisterMock)
 
        invokerInfo := "invoker a"
        newInvoker := getInvoker(invokerInfo)
@@ -260,7 +274,7 @@ func TestGetInvokerApiList(t *testing.T) {
        assert.Equal(t, apiId, *(*wantedApiList)[0].ApiId)
 }
 
-func getEcho(publishRegister publishservice.PublishRegister) (*InvokerManager, *echo.Echo) {
+func getEcho(publishRegister publishservice.PublishRegister) (*InvokerManager, chan eventsapi.EventNotification, *echo.Echo) {
        swagger, err := invokermanagementapi.GetSwagger()
        if err != nil {
                fmt.Fprintf(os.Stderr, "Error loading swagger spec\n: %s", err)
@@ -269,14 +283,15 @@ func getEcho(publishRegister publishservice.PublishRegister) (*InvokerManager, *
 
        swagger.Servers = nil
 
-       im := NewInvokerManager(publishRegister)
+       eventChannel := make(chan eventsapi.EventNotification)
+       im := NewInvokerManager(publishRegister, eventChannel)
 
        e := echo.New()
        e.Use(echomiddleware.Logger())
        e.Use(middleware.OapiRequestValidator(swagger))
 
        invokermanagementapi.RegisterHandlers(e, im)
-       return im, e
+       return im, eventChannel, e
 }
 
 func getAefProfile(aefId string) publishserviceapi.AefProfile {
@@ -305,3 +320,14 @@ func getInvoker(invokerInfo string) invokermanagementapi.APIInvokerEnrolmentDeta
        }
        return newInvoker
 }
+
+// waitForEvent waits for the channel to receive an event for the specified max timeout.
+// Returns true if waiting timed out.
+func waitForEvent(ch chan eventsapi.EventNotification, timeout time.Duration) (*eventsapi.EventNotification, bool) {
+       select {
+       case event := <-ch:
+               return &event, false // completed normally
+       case <-time.After(timeout):
+               return nil, true // timed out
+       }
+}
index ef15462..2cd5ccc 100644 (file)
@@ -124,7 +124,7 @@ func getEcho() *echo.Echo {
                log.Fatalf("Error loading InvokerManagement swagger spec\n: %s", err)
        }
        invokerManagerSwagger.Servers = nil
-       invokerManager := invokermanagement.NewInvokerManager(publishService)
+       invokerManager := invokermanagement.NewInvokerManager(publishService, eventChannel)
        group = e.Group("/api-invoker-management/v1")
        group.Use(middleware.OapiRequestValidator(invokerManagerSwagger))
        invokermanagementapi.RegisterHandlersWithBaseURL(e, invokerManager, "/api-invoker-management/v1")