2 // ========================LICENSE_START=================================
5 // Copyright (C) 2022: Nordix Foundation
7 // Licensed under the Apache License, Version 2.0 (the "License");
8 // you may not use this file except in compliance with the License.
9 // You may obtain a copy of the License at
11 // http://www.apache.org/licenses/LICENSE-2.0
13 // Unless required by applicable law or agreed to in writing, software
14 // distributed under the License is distributed on an "AS IS" BASIS,
15 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 // See the License for the specific language governing permissions and
17 // limitations under the License.
18 // ========================LICENSE_END===================================
21 package providermanagement
30 "github.com/labstack/echo/v4"
32 "oransc.org/nonrtric/capifcore/internal/common29122"
33 provapi "oransc.org/nonrtric/capifcore/internal/providermanagementapi"
35 log "github.com/sirupsen/logrus"
38 //go:generate mockery --name ServiceRegister
39 type ServiceRegister interface {
40 IsFunctionRegistered(functionId string) bool
41 GetAefsForPublisher(apfId string) []string
44 type ProviderManager struct {
45 onboardedProviders map[string]provapi.APIProviderEnrolmentDetails
49 func NewProviderManager() *ProviderManager {
50 return &ProviderManager{
51 onboardedProviders: make(map[string]provapi.APIProviderEnrolmentDetails),
55 func (pm *ProviderManager) IsFunctionRegistered(functionId string) bool {
58 for _, provider := range pm.onboardedProviders {
59 for _, registeredFunc := range *provider.ApiProvFuncs {
60 if *registeredFunc.ApiProvFuncId == functionId {
70 func (pm *ProviderManager) GetAefsForPublisher(apfId string) []string {
71 for _, provider := range pm.onboardedProviders {
72 for _, registeredFunc := range *provider.ApiProvFuncs {
73 if *registeredFunc.ApiProvFuncId == apfId && registeredFunc.ApiProvFuncRole == provapi.ApiProviderFuncRoleAPF {
74 return getExposedFuncs(provider.ApiProvFuncs)
81 func getExposedFuncs(providerFuncs *[]provapi.APIProviderFunctionDetails) []string {
82 exposedFuncs := []string{}
83 for _, registeredFunc := range *providerFuncs {
84 if registeredFunc.ApiProvFuncRole == provapi.ApiProviderFuncRoleAEF {
85 exposedFuncs = append(exposedFuncs, *registeredFunc.ApiProvFuncId)
91 func (pm *ProviderManager) PostRegistrations(ctx echo.Context) error {
92 var newProvider provapi.APIProviderEnrolmentDetails
93 err := ctx.Bind(&newProvider)
95 return sendCoreError(ctx, http.StatusBadRequest, "Invalid format for provider")
98 if newProvider.ApiProvDomInfo == nil || *newProvider.ApiProvDomInfo == "" {
99 return sendCoreError(ctx, http.StatusBadRequest, "Provider missing required ApiProvDomInfo")
103 defer pm.lock.Unlock()
105 newProvider.ApiProvDomId = pm.getDomainId(newProvider.ApiProvDomInfo)
107 pm.registerFunctions(newProvider.ApiProvFuncs)
108 pm.onboardedProviders[*newProvider.ApiProvDomId] = newProvider
110 uri := ctx.Request().Host + ctx.Request().URL.String()
111 ctx.Response().Header().Set(echo.HeaderLocation, ctx.Scheme()+`://`+path.Join(uri, *newProvider.ApiProvDomId))
112 err = ctx.JSON(http.StatusCreated, newProvider)
114 // Something really bad happened, tell Echo that our handler failed
121 func (pm *ProviderManager) DeleteRegistrationsRegistrationId(ctx echo.Context, registrationId string) error {
123 defer pm.lock.Unlock()
125 log.Debug(pm.onboardedProviders)
126 if _, ok := pm.onboardedProviders[registrationId]; ok {
127 log.Debug("Deleting provider", registrationId)
128 delete(pm.onboardedProviders, registrationId)
131 return ctx.NoContent(http.StatusNoContent)
134 func (pm *ProviderManager) PutRegistrationsRegistrationId(ctx echo.Context, registrationId string) error {
136 defer pm.lock.Unlock()
138 errMsg := "Unable to update provider due to %s."
139 registeredProvider, err := pm.checkIfProviderIsRegistered(registrationId, ctx)
141 return sendCoreError(ctx, http.StatusBadRequest, fmt.Sprintf(errMsg, err))
144 updatedProvider, err := getProviderFromRequest(ctx)
146 return sendCoreError(ctx, http.StatusBadRequest, fmt.Sprintf(errMsg, err))
149 updateDomainInfo(&updatedProvider, registeredProvider)
151 registeredProvider.ApiProvFuncs, err = updateFuncs(updatedProvider.ApiProvFuncs, registeredProvider.ApiProvFuncs)
153 return sendCoreError(ctx, http.StatusBadRequest, fmt.Sprintf(errMsg, err))
156 pm.onboardedProviders[*registeredProvider.ApiProvDomId] = *registeredProvider
157 err = ctx.JSON(http.StatusOK, *registeredProvider)
159 // Something really bad happened, tell Echo that our handler failed
166 func (pm *ProviderManager) checkIfProviderIsRegistered(registrationId string, ctx echo.Context) (*provapi.APIProviderEnrolmentDetails, error) {
167 registeredProvider, ok := pm.onboardedProviders[registrationId]
169 return nil, fmt.Errorf("provider not onboarded")
171 return ®isteredProvider, nil
174 func getProviderFromRequest(ctx echo.Context) (provapi.APIProviderEnrolmentDetails, error) {
175 var updatedProvider provapi.APIProviderEnrolmentDetails
176 err := ctx.Bind(&updatedProvider)
178 return provapi.APIProviderEnrolmentDetails{}, fmt.Errorf("invalid format for provider")
180 return updatedProvider, nil
183 func updateDomainInfo(updatedProvider, registeredProvider *provapi.APIProviderEnrolmentDetails) {
184 if updatedProvider.ApiProvDomInfo != nil {
185 registeredProvider.ApiProvDomInfo = updatedProvider.ApiProvDomInfo
189 func updateFuncs(updatedFuncs, registeredFuncs *[]provapi.APIProviderFunctionDetails) (*[]provapi.APIProviderFunctionDetails, error) {
190 addedFuncs := []provapi.APIProviderFunctionDetails{}
191 changedFuncs := []provapi.APIProviderFunctionDetails{}
192 for _, function := range *updatedFuncs {
193 if function.ApiProvFuncId == nil {
194 function.ApiProvFuncId = getFuncId(function.ApiProvFuncRole, function.ApiProvFuncInfo)
195 addedFuncs = append(addedFuncs, function)
197 registeredFunction, ok := getApiFunc(*function.ApiProvFuncId, registeredFuncs)
199 return nil, fmt.Errorf("function with ID %s is not registered for the provider", *function.ApiProvFuncId)
201 if function.ApiProvFuncInfo != nil {
202 registeredFunction.ApiProvFuncInfo = function.ApiProvFuncInfo
204 changedFuncs = append(changedFuncs, function)
207 modifiedFuncs := append(changedFuncs, addedFuncs...)
208 return &modifiedFuncs, nil
211 func getApiFunc(funcId string, apiFunctions *[]provapi.APIProviderFunctionDetails) (provapi.APIProviderFunctionDetails, bool) {
212 for _, function := range *apiFunctions {
213 if *function.ApiProvFuncId == funcId {
214 return function, true
217 return provapi.APIProviderFunctionDetails{}, false
220 func (pm *ProviderManager) ModifyIndApiProviderEnrolment(ctx echo.Context, registrationId string) error {
221 return ctx.NoContent(http.StatusNotImplemented)
224 func (pm *ProviderManager) registerFunctions(provFuncs *[]provapi.APIProviderFunctionDetails) {
225 if provFuncs == nil {
228 for i, provFunc := range *provFuncs {
229 (*provFuncs)[i].ApiProvFuncId = getFuncId(provFunc.ApiProvFuncRole, provFunc.ApiProvFuncInfo)
233 func (pm *ProviderManager) getDomainId(domainInfo *string) *string {
234 idAsString := "domain_id_" + strings.ReplaceAll(*domainInfo, " ", "_")
238 func getFuncId(role provapi.ApiProviderFuncRole, funcInfo *string) *string {
241 case provapi.ApiProviderFuncRoleAPF:
243 case provapi.ApiProviderFuncRoleAMF:
245 case provapi.ApiProviderFuncRoleAEF:
248 idPrefix = "function_id_"
250 idAsString := idPrefix + strings.ReplaceAll(*funcInfo, " ", "_")
254 // This function wraps sending of an error in the Error format, and
255 // handling the failure to marshal that.
256 func sendCoreError(ctx echo.Context, code int, message string) error {
257 pd := common29122.ProblemDetails{
261 err := ctx.JSON(code, pd)