"strings"
"sync"
+ "oransc.org/nonrtric/capifcore/internal/eventsapi"
publishapi "oransc.org/nonrtric/capifcore/internal/publishserviceapi"
"oransc.org/nonrtric/capifcore/internal/common29122"
//go:generate mockery --name InvokerRegister
type InvokerRegister interface {
+ // Checks if the invoker is registered.
+ // Returns true of the provided invoker is registered, false otherwise.
IsInvokerRegistered(invokerId string) bool
+ // Verifies that the provided secret is the invoker's registered secret.
+ // Returns true if the provided secret is the registered invoker's secret, false otherwise.
VerifyInvokerSecret(invokerId, secret string) bool
+ // Gets the provided invoker's registered APIs.
+ // Returns a list of all the invoker's registered APIs.
GetInvokerApiList(invokerId string) *invokerapi.APIList
}
type InvokerManager struct {
onboardedInvokers map[string]invokerapi.APIInvokerEnrolmentDetails
- apiRegister publishservice.APIRegister
+ publishRegister publishservice.PublishRegister
nextId int64
+ eventChannel chan<- eventsapi.EventNotification
lock sync.Mutex
}
-func NewInvokerManager(apiRegister publishservice.APIRegister) *InvokerManager {
+// Creates a manager that implements both the InvokerRegister and the invokermanagementapi.ServerInterface interfaces.
+func NewInvokerManager(publishRegister publishservice.PublishRegister, eventChannel chan<- eventsapi.EventNotification) *InvokerManager {
return &InvokerManager{
onboardedInvokers: make(map[string]invokerapi.APIInvokerEnrolmentDetails),
- apiRegister: apiRegister,
+ publishRegister: publishRegister,
nextId: 1000,
+ eventChannel: eventChannel,
}
}
func (im *InvokerManager) GetInvokerApiList(invokerId string) *invokerapi.APIList {
invoker, ok := im.onboardedInvokers[invokerId]
if ok {
- return invoker.ApiList
+ var apiList invokerapi.APIList = im.publishRegister.GetAllPublishedServices()
+ im.lock.Lock()
+ defer im.lock.Unlock()
+ invoker.ApiList = &apiList
+ return &apiList
}
return nil
}
+// Creates a new individual API Invoker profile.
func (im *InvokerManager) PostOnboardedInvokers(ctx echo.Context) error {
var newInvoker invokerapi.APIInvokerEnrolmentDetails
err := ctx.Bind(&newInvoker)
return sendCoreError(ctx, http.StatusBadRequest, "Invalid format for invoker")
}
- coreError := im.validateInvoker(newInvoker, ctx)
- if coreError != nil {
+ shouldReturn, coreError := im.validateInvoker(newInvoker, ctx)
+ if shouldReturn {
return coreError
}
}
newInvoker.OnboardingInformation.OnboardingSecret = &onboardingSecret
+ var apiList invokerapi.APIList = im.publishRegister.GetAllPublishedServices()
+ 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))
return nil
}
+// Deletes an individual API Invoker.
func (im *InvokerManager) DeleteOnboardedInvokersOnboardingId(ctx echo.Context, onboardingId string) error {
im.lock.Lock()
defer im.lock.Unlock()
delete(im.onboardedInvokers, onboardingId)
+ go im.sendEvent(onboardingId, eventsapi.CAPIFEventAPIINVOKEROFFBOARDED)
return ctx.NoContent(http.StatusNoContent)
}
+// Updates an individual API invoker details.
func (im *InvokerManager) PutOnboardedInvokersOnboardingId(ctx echo.Context, onboardingId string) error {
var invoker invokerapi.APIInvokerEnrolmentDetails
err := ctx.Bind(&invoker)
return sendCoreError(ctx, http.StatusBadRequest, "Invoker ApiInvokerId not matching")
}
- coreError := im.validateInvoker(invoker, ctx)
- if coreError != nil {
+ shouldReturn, coreError := im.validateInvoker(invoker, ctx)
+ if shouldReturn {
return coreError
}
return ctx.NoContent(http.StatusNotImplemented)
}
-func (im *InvokerManager) validateInvoker(invoker invokerapi.APIInvokerEnrolmentDetails, ctx echo.Context) error {
+func (im *InvokerManager) validateInvoker(invoker invokerapi.APIInvokerEnrolmentDetails, ctx echo.Context) (bool, error) {
if invoker.NotificationDestination == "" {
- return sendCoreError(ctx, http.StatusBadRequest, "Invoker missing required NotificationDestination")
+ return true, sendCoreError(ctx, http.StatusBadRequest, "Invoker missing required NotificationDestination")
}
if invoker.OnboardingInformation.ApiInvokerPublicKey == "" {
- return sendCoreError(ctx, http.StatusBadRequest, "Invoker missing required OnboardingInformation.ApiInvokerPublicKey")
+ return true, sendCoreError(ctx, http.StatusBadRequest, "Invoker missing required OnboardingInformation.ApiInvokerPublicKey")
}
- if !im.areAPIsRegistered(invoker.ApiList) {
- return sendCoreError(ctx, http.StatusBadRequest, "Some APIs needed by invoker are not registered")
+ if !im.areAPIsPublished(invoker.ApiList) {
+ return true, sendCoreError(ctx, http.StatusBadRequest, "Some APIs needed by invoker are not registered")
}
- return nil
+ return false, nil
}
-func (im *InvokerManager) areAPIsRegistered(apis *invokerapi.APIList) bool {
+func (im *InvokerManager) areAPIsPublished(apis *invokerapi.APIList) bool {
if apis == nil {
return true
}
- return im.apiRegister.AreAPIsRegistered((*[]publishapi.ServiceAPIDescription)(apis))
+ return im.publishRegister.AreAPIsPublished((*[]publishapi.ServiceAPIDescription)(apis))
}
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 {