--- /dev/null
+// -
+// ========================LICENSE_START=================================
+// O-RAN-SC
+// %%
+// Copyright (C) 2022: Nordix Foundation
+// %%
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+// ========================LICENSE_END===================================
+//
+
+package providermanagement
+
+import (
+ "net/http"
+ "path"
+ "strings"
+ "sync"
+
+ "github.com/labstack/echo/v4"
+
+ "oransc.org/nonrtric/sme/internal/common29122"
+ provapi "oransc.org/nonrtric/sme/internal/providermanagementapi"
+
+ log "github.com/sirupsen/logrus"
+)
+
+//go:generate mockery --name ServiceRegister
+type ServiceRegister interface {
+ IsFunctionRegistered(aefId string) bool
+}
+
+type ProviderManager struct {
+ onboardedProviders map[string]provapi.APIProviderEnrolmentDetails
+ lock sync.Mutex
+}
+
+func NewProviderManager() *ProviderManager {
+ return &ProviderManager{
+ onboardedProviders: make(map[string]provapi.APIProviderEnrolmentDetails),
+ }
+}
+
+func (pm *ProviderManager) IsFunctionRegistered(aefId string) bool {
+ registered := false
+out:
+ for _, provider := range pm.onboardedProviders {
+ for _, registeredFunc := range *provider.ApiProvFuncs {
+ if *registeredFunc.ApiProvFuncId == aefId {
+ registered = true
+ break out
+ }
+ }
+ }
+
+ return registered
+}
+
+func (pm *ProviderManager) PostRegistrations(ctx echo.Context) error {
+ var newProvider provapi.APIProviderEnrolmentDetails
+ err := ctx.Bind(&newProvider)
+ if err != nil {
+ return sendCoreError(ctx, http.StatusBadRequest, "Invalid format for provider")
+ }
+
+ if newProvider.ApiProvDomInfo == nil || *newProvider.ApiProvDomInfo == "" {
+ return sendCoreError(ctx, http.StatusBadRequest, "Provider missing required ApiProvDomInfo")
+ }
+
+ pm.lock.Lock()
+ defer pm.lock.Unlock()
+
+ newProvider.ApiProvDomId = pm.getDomainId(newProvider.ApiProvDomInfo)
+
+ pm.registerFunctions(newProvider.ApiProvFuncs)
+ pm.onboardedProviders[*newProvider.ApiProvDomId] = newProvider
+
+ uri := ctx.Request().Host + ctx.Request().URL.String()
+ ctx.Response().Header().Set(echo.HeaderLocation, ctx.Scheme()+`://`+path.Join(uri, *newProvider.ApiProvDomId))
+ err = ctx.JSON(http.StatusCreated, newProvider)
+ if err != nil {
+ // Something really bad happened, tell Echo that our handler failed
+ return err
+ }
+
+ return nil
+}
+
+func (pm *ProviderManager) DeleteRegistrationsRegistrationId(ctx echo.Context, registrationId string) error {
+ pm.lock.Lock()
+ defer pm.lock.Unlock()
+
+ log.Debug(pm.onboardedProviders)
+ if _, ok := pm.onboardedProviders[registrationId]; ok {
+ log.Debug("Deleting provider", registrationId)
+ delete(pm.onboardedProviders, registrationId)
+ }
+
+ return ctx.NoContent(http.StatusNoContent)
+}
+
+func (pm *ProviderManager) PutRegistrationsRegistrationId(ctx echo.Context, registrationId string) error {
+ registeredProvider, ok := pm.onboardedProviders[registrationId]
+ if !ok {
+ return sendCoreError(ctx, http.StatusBadRequest, "Provider must be onboarded before updating it")
+
+ }
+
+ var updatedProvider provapi.APIProviderEnrolmentDetails
+ err := ctx.Bind(&updatedProvider)
+ if err != nil {
+ return sendCoreError(ctx, http.StatusBadRequest, "Invalid format for provider")
+ }
+
+ for _, function := range *updatedProvider.ApiProvFuncs {
+ if function.ApiProvFuncId == nil {
+ function.ApiProvFuncId = pm.getFuncId(function.ApiProvFuncRole, function.ApiProvFuncInfo)
+ registeredFuncs := *registeredProvider.ApiProvFuncs
+ newFuncs := append(registeredFuncs, function)
+ registeredProvider.ApiProvFuncs = &newFuncs
+ pm.onboardedProviders[*registeredProvider.ApiProvDomId] = registeredProvider
+ }
+ }
+
+ err = ctx.JSON(http.StatusOK, registeredProvider)
+ if err != nil {
+ // Something really bad happened, tell Echo that our handler failed
+ return err
+ }
+
+ return nil
+}
+
+func (pm *ProviderManager) ModifyIndApiProviderEnrolment(ctx echo.Context, registrationId string) error {
+ return ctx.NoContent(http.StatusNotImplemented)
+}
+
+func (pm *ProviderManager) registerFunctions(provFuncs *[]provapi.APIProviderFunctionDetails) {
+ if provFuncs == nil {
+ return
+ }
+ for i, provFunc := range *provFuncs {
+ (*provFuncs)[i].ApiProvFuncId = pm.getFuncId(provFunc.ApiProvFuncRole, provFunc.ApiProvFuncInfo)
+ }
+}
+
+func (pm *ProviderManager) getDomainId(domainInfo *string) *string {
+ idAsString := "domain_id_" + strings.ReplaceAll(*domainInfo, " ", "_")
+ return &idAsString
+}
+
+func (pm *ProviderManager) getFuncId(role provapi.ApiProviderFuncRole, funcInfo *string) *string {
+ var idPrefix string
+ switch role {
+ case provapi.ApiProviderFuncRoleAPF:
+ idPrefix = "APF_id_"
+ case provapi.ApiProviderFuncRoleAMF:
+ idPrefix = "AMF_id_"
+ case provapi.ApiProviderFuncRoleAEF:
+ idPrefix = "AEF_id_"
+ default:
+ idPrefix = "function_id_"
+ }
+ idAsString := idPrefix + strings.ReplaceAll(*funcInfo, " ", "_")
+ return &idAsString
+}
+
+// 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 {
+ pd := common29122.ProblemDetails{
+ Cause: &message,
+ Status: &code,
+ }
+ err := ctx.JSON(code, pd)
+ return err
+}