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
29 echo "github.com/labstack/echo/v4"
30 log "github.com/sirupsen/logrus"
32 "oransc.org/nonrtric/capifcore/internal/common29122"
33 provapi "oransc.org/nonrtric/capifcore/internal/providermanagementapi"
36 //go:generate mockery --name ServiceRegister
37 type ServiceRegister interface {
38 IsFunctionRegistered(functionId string) bool
39 GetAefsForPublisher(apfId string) []string
40 IsPublishingFunctionRegistered(apiProvFuncId string) bool
43 type ProviderManager struct {
44 registeredProviders map[string]provapi.APIProviderEnrolmentDetails
48 func NewProviderManager() *ProviderManager {
49 return &ProviderManager{
50 registeredProviders: make(map[string]provapi.APIProviderEnrolmentDetails),
54 func (pm *ProviderManager) IsFunctionRegistered(functionId string) bool {
55 for _, provider := range pm.registeredProviders {
56 if provider.IsFunctionRegistered(functionId) {
63 func (pm *ProviderManager) GetAefsForPublisher(apfId string) []string {
64 for _, provider := range pm.registeredProviders {
65 if aefs := provider.GetExposingFunctionIdsForPublisher(apfId); aefs != nil {
72 func (pm *ProviderManager) IsPublishingFunctionRegistered(apiProvFuncId string) bool {
73 for _, provider := range pm.registeredProviders {
74 if provider.IsPublishingFunctionRegistered(apiProvFuncId) {
81 func (pm *ProviderManager) PostRegistrations(ctx echo.Context) error {
82 var newProvider provapi.APIProviderEnrolmentDetails
83 errMsg := "Unable to register provider due to %s"
84 if err := ctx.Bind(&newProvider); err != nil {
85 return sendCoreError(ctx, http.StatusBadRequest, fmt.Sprintf(errMsg, "invalid format for provider"))
88 if err := pm.isProviderRegistered(newProvider); err != nil {
89 return sendCoreError(ctx, http.StatusForbidden, fmt.Sprintf(errMsg, err))
92 if err := newProvider.Validate(); err != nil {
93 return sendCoreError(ctx, http.StatusBadRequest, fmt.Sprintf(errMsg, err))
96 pm.prepareNewProvider(&newProvider)
98 uri := ctx.Request().Host + ctx.Request().URL.String()
99 ctx.Response().Header().Set(echo.HeaderLocation, ctx.Scheme()+`://`+path.Join(uri, *newProvider.ApiProvDomId))
100 if err := ctx.JSON(http.StatusCreated, newProvider); err != nil {
101 // Something really bad happened, tell Echo that our handler failed
107 func (pm *ProviderManager) isProviderRegistered(newProvider provapi.APIProviderEnrolmentDetails) error {
108 for _, prov := range pm.registeredProviders {
109 if err := prov.ValidateAlreadyRegistered(newProvider); err != nil {
116 func (pm *ProviderManager) prepareNewProvider(newProvider *provapi.APIProviderEnrolmentDetails) {
118 defer pm.lock.Unlock()
120 newProvider.PrepareNewProvider()
121 pm.registeredProviders[*newProvider.ApiProvDomId] = *newProvider
124 func (pm *ProviderManager) DeleteRegistrationsRegistrationId(ctx echo.Context, registrationId string) error {
125 log.Debug(pm.registeredProviders)
126 if _, ok := pm.registeredProviders[registrationId]; ok {
127 pm.deleteProvider(registrationId)
129 return ctx.NoContent(http.StatusNoContent)
132 func (pm *ProviderManager) deleteProvider(registrationId string) {
133 log.Debug("Deleting provider", registrationId)
135 defer pm.lock.Unlock()
136 delete(pm.registeredProviders, registrationId)
139 func (pm *ProviderManager) PutRegistrationsRegistrationId(ctx echo.Context, registrationId string) error {
140 errMsg := "Unable to update provider due to %s."
141 registeredProvider, err := pm.checkIfProviderIsRegistered(registrationId, ctx)
143 return sendCoreError(ctx, http.StatusBadRequest, fmt.Sprintf(errMsg, err))
146 updatedProvider, err := getProviderFromRequest(ctx)
148 return sendCoreError(ctx, http.StatusBadRequest, fmt.Sprintf(errMsg, err))
151 if updatedProvider.Validate() != nil {
152 return sendCoreError(ctx, http.StatusBadRequest, fmt.Sprintf(errMsg, err))
155 // Additional validation for PUT
156 if (updatedProvider.ApiProvDomId == nil) || (*updatedProvider.ApiProvDomId != registrationId) {
157 errDetail := "APIProviderEnrolmentDetails ApiProvDomId doesn't match path parameter"
158 return sendCoreError(ctx, http.StatusBadRequest, fmt.Sprintf(errMsg, errDetail))
161 if err = pm.updateProvider(updatedProvider, registeredProvider); err != nil {
162 return sendCoreError(ctx, http.StatusBadRequest, fmt.Sprintf(errMsg, err))
165 if err = ctx.JSON(http.StatusOK, updatedProvider); err != nil {
166 // Something really bad happened, tell Echo that our handler failed
172 func (pm *ProviderManager) ModifyIndApiProviderEnrolment(ctx echo.Context, registrationId string) error {
173 return ctx.NoContent(http.StatusNotImplemented)
176 func (pm *ProviderManager) checkIfProviderIsRegistered(registrationId string, ctx echo.Context) (*provapi.APIProviderEnrolmentDetails, error) {
177 registeredProvider, ok := pm.registeredProviders[registrationId]
179 return nil, fmt.Errorf("provider not onboarded")
181 return ®isteredProvider, nil
184 func getProviderFromRequest(ctx echo.Context) (provapi.APIProviderEnrolmentDetails, error) {
185 var updatedProvider provapi.APIProviderEnrolmentDetails
186 err := ctx.Bind(&updatedProvider)
188 return provapi.APIProviderEnrolmentDetails{}, fmt.Errorf("invalid format for provider")
190 return updatedProvider, nil
193 func (pm *ProviderManager) updateProvider(updatedProvider provapi.APIProviderEnrolmentDetails, registeredProvider *provapi.APIProviderEnrolmentDetails) error {
195 defer pm.lock.Unlock()
197 if err := updatedProvider.UpdateFuncs(*registeredProvider); err == nil {
198 pm.registeredProviders[*updatedProvider.ApiProvDomId] = updatedProvider
205 // This function wraps sending of an error in the Error format, and
206 // handling the failure to marshal that.
207 func sendCoreError(ctx echo.Context, code int, message string) error {
208 pd := common29122.ProblemDetails{
212 err := ctx.JSON(code, pd)