X-Git-Url: https://gerrit.o-ran-sc.org/r/gitweb?a=blobdiff_plain;f=capifcore%2Finternal%2Fpublishservice%2Fpublishservice.go;h=b4e38e76d518c5342c49679f135486f294228807;hb=d17ee019461493f52df06074ce95a6cb951ffdc4;hp=5cea538f1f59f76dcbefa8aad33571fea1f0b0dc;hpb=f62685e5a2187fb58c7f27cdd1f14dd2c152880d;p=nonrtric%2Fplt%2Fsme.git diff --git a/capifcore/internal/publishservice/publishservice.go b/capifcore/internal/publishservice/publishservice.go index 5cea538..b4e38e7 100644 --- a/capifcore/internal/publishservice/publishservice.go +++ b/capifcore/internal/publishservice/publishservice.go @@ -2,7 +2,8 @@ // ========================LICENSE_START================================= // O-RAN-SC // %% -// Copyright (C) 2022: Nordix Foundation +// Copyright (C) 2022-2023: Nordix Foundation +// Copyright (C) 2024: OpenInfra Foundation Europe // %% // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -27,7 +28,7 @@ import ( "strings" "sync" - "github.com/labstack/echo/v4" + echo "github.com/labstack/echo/v4" "k8s.io/utils/strings/slices" "oransc.org/nonrtric/capifcore/internal/common29122" @@ -42,9 +43,6 @@ import ( //go:generate mockery --name PublishRegister type PublishRegister interface { - // Checks if the provided APIs are published. - // Returns true if all provided APIs have been published, false otherwise. - AreAPIsPublished(serviceDescriptions *[]publishapi.ServiceAPIDescription) bool // Checks if the provided API is published. // Returns true if the provided API has been published, false otherwise. IsAPIPublished(aefId, path string) bool @@ -71,15 +69,6 @@ func NewPublishService(serviceRegister providermanagement.ServiceRegister, hm he } } -func (ps *PublishService) AreAPIsPublished(serviceDescriptions *[]publishapi.ServiceAPIDescription) bool { - - if serviceDescriptions != nil { - registeredApis := ps.getAllAefIds() - return checkNewDescriptions(*serviceDescriptions, registeredApis) - } - return true -} - func (ps *PublishService) getAllAefIds() []string { ps.lock.Lock() defer ps.lock.Unlock() @@ -87,46 +76,12 @@ func (ps *PublishService) getAllAefIds() []string { allIds := []string{} for _, descriptions := range ps.publishedServices { for _, description := range descriptions { - allIds = append(allIds, getIdsFromDescription(description)...) - } - } - return allIds -} - -func getIdsFromDescription(description publishapi.ServiceAPIDescription) []string { - allIds := []string{} - if description.AefProfiles != nil { - for _, aefProfile := range *description.AefProfiles { - allIds = append(allIds, aefProfile.AefId) + allIds = append(allIds, description.GetAefIds()...) } } return allIds } -func checkNewDescriptions(newDescriptions []publishapi.ServiceAPIDescription, registeredAefIds []string) bool { - registered := true - for _, newApi := range newDescriptions { - if !checkProfiles(newApi.AefProfiles, registeredAefIds) { - registered = false - break - } - } - return registered -} - -func checkProfiles(newProfiles *[]publishapi.AefProfile, registeredAefIds []string) bool { - allRegistered := true - if newProfiles != nil { - for _, profile := range *newProfiles { - if !slices.Contains(registeredAefIds, profile.AefId) { - allRegistered = false - break - } - } - } - return allRegistered -} - func (ps *PublishService) IsAPIPublished(aefId, path string) bool { return slices.Contains(ps.getAllAefIds(), aefId) } @@ -141,17 +96,17 @@ func (ps *PublishService) GetAllPublishedServices() []publishapi.ServiceAPIDescr // Retrieve all published APIs. func (ps *PublishService) GetApfIdServiceApis(ctx echo.Context, apfId string) error { - serviceDescriptions, ok := ps.publishedServices[apfId] - if ok { - err := ctx.JSON(http.StatusOK, serviceDescriptions) - if err != nil { - // Something really bad happened, tell Echo that our handler failed - return err - } - } else { - return sendCoreError(ctx, http.StatusNotFound, fmt.Sprintf("Provider %s not registered", apfId)) + if !ps.serviceRegister.IsPublishingFunctionRegistered(apfId) { + errorMsg := fmt.Sprintf("Unable to get the service due to %s api is only available for publishers", apfId) + return sendCoreError(ctx, http.StatusNotFound, errorMsg) } + serviceDescriptions := ps.publishedServices[apfId] + err := ctx.JSON(http.StatusOK, serviceDescriptions) + if err != nil { + // Something really bad happened, tell Echo that our handler failed + return err + } return nil } @@ -164,8 +119,12 @@ func (ps *PublishService) PostApfIdServiceApis(ctx echo.Context, apfId string) e return sendCoreError(ctx, http.StatusBadRequest, fmt.Sprintf(errorMsg, "invalid format for service "+apfId)) } - if ps.isServicePublished(newServiceAPIDescription) { - return sendCoreError(ctx, http.StatusForbidden, fmt.Sprintf(errorMsg, "service already published")) + if !ps.serviceRegister.IsPublishingFunctionRegistered(apfId) { + return sendCoreError(ctx, http.StatusForbidden, fmt.Sprintf(errorMsg, "api is only available for publishers "+apfId)) + } + + if err := ps.isServicePublished(newServiceAPIDescription); err != nil { + return sendCoreError(ctx, http.StatusForbidden, fmt.Sprintf(errorMsg, err)) } if err := newServiceAPIDescription.Validate(); err != nil { @@ -181,8 +140,7 @@ func (ps *PublishService) PostApfIdServiceApis(ctx echo.Context, apfId string) e } } - newId := "api_id_" + newServiceAPIDescription.ApiName - newServiceAPIDescription.ApiId = &newId + newServiceAPIDescription.PrepareNewService() shouldReturn, returnValue := ps.installHelmChart(newServiceAPIDescription, ctx) if shouldReturn { @@ -208,15 +166,15 @@ func (ps *PublishService) PostApfIdServiceApis(ctx echo.Context, apfId string) e return nil } -func (ps *PublishService) isServicePublished(newService publishapi.ServiceAPIDescription) bool { +func (ps *PublishService) isServicePublished(newService publishapi.ServiceAPIDescription) error { for _, services := range ps.publishedServices { for _, service := range services { - if newService.ApiName == service.ApiName { - return true + if err := service.ValidateAlreadyPublished(newService); err != nil { + return err } } } - return false + return nil } func (ps *PublishService) installHelmChart(newServiceAPIDescription publishapi.ServiceAPIDescription, ctx echo.Context) (bool, error) { @@ -299,21 +257,33 @@ func (ps *PublishService) PutApfIdServiceApisServiceApiId(ctx echo.Context, apfI ps.lock.Lock() defer ps.lock.Unlock() errMsg := "Unable to update service due to %s." + pos, publishedService, err := ps.checkIfServiceIsPublished(apfId, serviceApiId, ctx) if err != nil { return sendCoreError(ctx, http.StatusBadRequest, fmt.Sprintf(errMsg, err)) } + updatedServiceDescription, err := getServiceFromRequest(ctx) if err != nil { return sendCoreError(ctx, http.StatusBadRequest, fmt.Sprintf(errMsg, err)) } - ps.updateDescription(pos, apfId, &updatedServiceDescription, &publishedService) + + // Additional validation for PUT + if (updatedServiceDescription.ApiId == nil) || (*updatedServiceDescription.ApiId != serviceApiId) { + errDetail := "ServiceAPIDescription ApiId doesn't match path parameter" + return sendCoreError(ctx, http.StatusBadRequest, fmt.Sprintf(errMsg, errDetail)) + } + err = ps.checkProfilesRegistered(apfId, *updatedServiceDescription.AefProfiles) if err != nil { return sendCoreError(ctx, http.StatusBadRequest, fmt.Sprintf(errMsg, err)) } + + ps.updateDescription(pos, apfId, &updatedServiceDescription, &publishedService) + publishedService.AefProfiles = updatedServiceDescription.AefProfiles ps.publishedServices[apfId][pos] = publishedService + err = ctx.JSON(http.StatusOK, publishedService) if err != nil { // Something really bad happened, tell Echo that our handler failed @@ -321,6 +291,7 @@ func (ps *PublishService) PutApfIdServiceApisServiceApiId(ctx echo.Context, apfI } return nil } + func (ps *PublishService) checkIfServiceIsPublished(apfId string, serviceApiId string, ctx echo.Context) (int, publishapi.ServiceAPIDescription, error) { publishedServices, ok := ps.publishedServices[apfId] if !ok { @@ -334,6 +305,7 @@ func (ps *PublishService) checkIfServiceIsPublished(apfId string, serviceApiId s } return 0, publishapi.ServiceAPIDescription{}, fmt.Errorf("service must be published before updating it") } + func getServiceFromRequest(ctx echo.Context) (publishapi.ServiceAPIDescription, error) { var updatedServiceDescription publishapi.ServiceAPIDescription err := ctx.Bind(&updatedServiceDescription) @@ -342,6 +314,7 @@ func getServiceFromRequest(ctx echo.Context) (publishapi.ServiceAPIDescription, } return updatedServiceDescription, nil } + func (ps *PublishService) updateDescription(pos int, apfId string, updatedServiceDescription, publishedService *publishapi.ServiceAPIDescription) { if updatedServiceDescription.Description != nil { publishedService.Description = updatedServiceDescription.Description