"strings"
"sync"
+ "oransc.org/nonrtric/capifcore/internal/eventsapi"
publishapi "oransc.org/nonrtric/capifcore/internal/publishserviceapi"
"oransc.org/nonrtric/capifcore/internal/common29122"
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,
}
}
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))
defer im.lock.Unlock()
delete(im.onboardedInvokers, onboardingId)
+ go im.sendEvent(onboardingId, eventsapi.CAPIFEventAPIINVOKEROFFBOARDED)
return ctx.NoContent(http.StatusNoContent)
}
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 {
"os"
"strings"
"testing"
+ "time"
+ "oransc.org/nonrtric/capifcore/internal/eventsapi"
"oransc.org/nonrtric/capifcore/internal/invokermanagementapi"
"github.com/labstack/echo/v4"
}
publishRegisterMock := publishmocks.PublishRegister{}
publishRegisterMock.On("GetAllPublishedServices").Return(publishedServices)
- invokerUnderTest, requestHandler := getEcho(&publishRegisterMock)
+ invokerUnderTest, eventChannel, requestHandler := getEcho(&publishRegisterMock)
invokerInfo := "invoker a"
newInvoker := getInvoker(invokerInfo)
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{
}
func TestDeleteInvoker(t *testing.T) {
- invokerUnderTest, requestHandler := getEcho(nil)
+ invokerUnderTest, eventChannel, requestHandler := getEcho(nil)
invokerId := "invokerId"
newInvoker := invokermanagementapi.APIInvokerEnrolmentDetails{
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{
})
publishRegisterMock := publishmocks.PublishRegister{}
publishRegisterMock.On("GetAllPublishedServices").Return(apiList)
- invokerUnderTest, _ := getEcho(&publishRegisterMock)
+ invokerUnderTest, _, _ := getEcho(&publishRegisterMock)
invokerInfo := "invoker a"
newInvoker := getInvoker(invokerInfo)
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)
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 {
}
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
+ }
+}