2 // ========================LICENSE_START=================================
5 // Copyright (C) 2022-2023: Nordix Foundation
6 // Copyright (C) 2024: OpenInfra Foundation Europe
8 // Licensed under the Apache License, Version 2.0 (the "License");
9 // you may not use this file except in compliance with the License.
10 // You may obtain a copy of the License at
12 // http://www.apache.org/licenses/LICENSE-2.0
14 // Unless required by applicable law or agreed to in writing, software
15 // distributed under the License is distributed on an "AS IS" BASIS,
16 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 // See the License for the specific language governing permissions and
18 // limitations under the License.
19 // ========================LICENSE_END===================================
22 package providermanagement
30 echo "github.com/labstack/echo/v4"
31 log "github.com/sirupsen/logrus"
33 "oransc.org/nonrtric/capifcore/internal/common29122"
34 provapi "oransc.org/nonrtric/capifcore/internal/providermanagementapi"
37 //go:generate mockery --name ServiceRegister
38 type ServiceRegister interface {
39 IsFunctionRegistered(functionId string) bool
40 GetAefsForPublisher(apfId string) []string
41 IsPublishingFunctionRegistered(apiProvFuncId string) bool
44 type ProviderManager struct {
45 registeredProviders map[string]provapi.APIProviderEnrolmentDetails
49 func NewProviderManager() *ProviderManager {
50 return &ProviderManager{
51 registeredProviders: make(map[string]provapi.APIProviderEnrolmentDetails),
55 func (pm *ProviderManager) IsFunctionRegistered(functionId string) bool {
56 for _, provider := range pm.registeredProviders {
57 if provider.IsFunctionRegistered(functionId) {
64 func (pm *ProviderManager) GetAefsForPublisher(apfId string) []string {
65 for _, provider := range pm.registeredProviders {
66 if aefs := provider.GetExposingFunctionIdsForPublisher(apfId); aefs != nil {
73 func (pm *ProviderManager) IsPublishingFunctionRegistered(apiProvFuncId string) bool {
74 for _, provider := range pm.registeredProviders {
75 if provider.IsPublishingFunctionRegistered(apiProvFuncId) {
82 func (pm *ProviderManager) PostRegistrations(ctx echo.Context) error {
83 var newProvider provapi.APIProviderEnrolmentDetails
84 errMsg := "Unable to register provider due to %s"
85 if err := ctx.Bind(&newProvider); err != nil {
86 return sendCoreError(ctx, http.StatusBadRequest, fmt.Sprintf(errMsg, "invalid format for provider"))
89 if err := pm.isProviderRegistered(newProvider); err != nil {
90 return sendCoreError(ctx, http.StatusForbidden, fmt.Sprintf(errMsg, err))
93 if err := newProvider.Validate(); err != nil {
94 return sendCoreError(ctx, http.StatusBadRequest, fmt.Sprintf(errMsg, err))
97 pm.prepareNewProvider(&newProvider)
99 uri := ctx.Request().Host + ctx.Request().URL.String()
100 ctx.Response().Header().Set(echo.HeaderLocation, ctx.Scheme()+`://`+path.Join(uri, *newProvider.ApiProvDomId))
101 if err := ctx.JSON(http.StatusCreated, newProvider); err != nil {
102 // Something really bad happened, tell Echo that our handler failed
108 func (pm *ProviderManager) isProviderRegistered(newProvider provapi.APIProviderEnrolmentDetails) error {
109 for _, prov := range pm.registeredProviders {
110 if err := prov.ValidateAlreadyRegistered(newProvider); err != nil {
117 func (pm *ProviderManager) prepareNewProvider(newProvider *provapi.APIProviderEnrolmentDetails) {
119 defer pm.lock.Unlock()
121 newProvider.PrepareNewProvider()
122 pm.registeredProviders[*newProvider.ApiProvDomId] = *newProvider
125 func (pm *ProviderManager) DeleteRegistrationsRegistrationId(ctx echo.Context, registrationId string) error {
126 log.Debug(pm.registeredProviders)
127 if _, ok := pm.registeredProviders[registrationId]; ok {
128 pm.deleteProvider(registrationId)
130 return ctx.NoContent(http.StatusNoContent)
133 func (pm *ProviderManager) deleteProvider(registrationId string) {
134 log.Debug("Deleting provider", registrationId)
136 defer pm.lock.Unlock()
137 delete(pm.registeredProviders, registrationId)
140 func (pm *ProviderManager) PutRegistrationsRegistrationId(ctx echo.Context, registrationId string) error {
141 errMsg := "Unable to update provider due to %s."
142 registeredProvider, err := pm.checkIfProviderIsRegistered(registrationId)
144 return sendCoreError(ctx, http.StatusBadRequest, fmt.Sprintf(errMsg, err))
147 updatedProvider, err := getProviderFromRequest(ctx)
149 return sendCoreError(ctx, http.StatusBadRequest, fmt.Sprintf(errMsg, err))
152 if updatedProvider.Validate() != nil {
153 return sendCoreError(ctx, http.StatusBadRequest, fmt.Sprintf(errMsg, err))
156 // Additional validation for PUT
157 if (updatedProvider.ApiProvDomId == nil) || (*updatedProvider.ApiProvDomId != registrationId) {
158 errDetail := "APIProviderEnrolmentDetails ApiProvDomId doesn't match path parameter"
159 return sendCoreError(ctx, http.StatusBadRequest, fmt.Sprintf(errMsg, errDetail))
162 if err = pm.updateProvider(updatedProvider, registeredProvider); err != nil {
163 return sendCoreError(ctx, http.StatusBadRequest, fmt.Sprintf(errMsg, err))
166 if err = ctx.JSON(http.StatusOK, updatedProvider); err != nil {
167 // Something really bad happened, tell Echo that our handler failed
173 func (pm *ProviderManager) ModifyIndApiProviderEnrolment(ctx echo.Context, registrationId string) error {
174 return ctx.NoContent(http.StatusNotImplemented)
177 func (pm *ProviderManager) checkIfProviderIsRegistered(registrationId string) (*provapi.APIProviderEnrolmentDetails, error) {
178 registeredProvider, ok := pm.registeredProviders[registrationId]
180 return nil, fmt.Errorf("provider not onboarded")
182 return ®isteredProvider, nil
185 func getProviderFromRequest(ctx echo.Context) (provapi.APIProviderEnrolmentDetails, error) {
186 var updatedProvider provapi.APIProviderEnrolmentDetails
187 err := ctx.Bind(&updatedProvider)
189 return provapi.APIProviderEnrolmentDetails{}, fmt.Errorf("invalid format for provider")
191 return updatedProvider, nil
194 func (pm *ProviderManager) updateProvider(updatedProvider provapi.APIProviderEnrolmentDetails, registeredProvider *provapi.APIProviderEnrolmentDetails) error {
196 defer pm.lock.Unlock()
198 if err := updatedProvider.UpdateFuncs(*registeredProvider); err == nil {
199 pm.registeredProviders[*updatedProvider.ApiProvDomId] = updatedProvider
206 // This function wraps sending of an error in the Error format, and
207 // handling the failure to marshal that.
208 func sendCoreError(ctx echo.Context, code int, message string) error {
209 pd := common29122.ProblemDetails{
213 err := ctx.JSON(code, pd)