From d0199885b0bc379f22dbb7012545f0049f979bac Mon Sep 17 00:00:00 2001 From: elinuxhenrik Date: Thu, 10 Nov 2022 08:06:51 +0100 Subject: [PATCH] Change discovery servic to get APIs from invoker service Issue-ID: NONRTRIC-814 Signed-off-by: elinuxhenrik Change-Id: I42214960fc556a54c4b0cc4194fbb74746d8d214 --- .../internal/discoverservice/discoverservice.go | 77 +++++++----- .../discoverservice/discoverservice_test.go | 137 +++++++++++++-------- capifcore/main.go | 22 ++-- capifcore/main_test.go | 2 +- 4 files changed, 147 insertions(+), 91 deletions(-) diff --git a/capifcore/internal/discoverservice/discoverservice.go b/capifcore/internal/discoverservice/discoverservice.go index a0d1f47..797eaa7 100644 --- a/capifcore/internal/discoverservice/discoverservice.go +++ b/capifcore/internal/discoverservice/discoverservice.go @@ -23,9 +23,9 @@ package discoverservice import ( "net/http" + "oransc.org/nonrtric/capifcore/internal/common29122" discoverapi "oransc.org/nonrtric/capifcore/internal/discoverserviceapi" - - "oransc.org/nonrtric/capifcore/internal/publishservice" + "oransc.org/nonrtric/capifcore/internal/invokermanagement" "github.com/labstack/echo/v4" @@ -33,20 +33,23 @@ import ( ) type DiscoverService struct { - apiRegister publishservice.APIRegister + invokerRegister invokermanagement.InvokerRegister } -func NewDiscoverService(apiRegister publishservice.APIRegister) *DiscoverService { +func NewDiscoverService(invokerRegister invokermanagement.InvokerRegister) *DiscoverService { return &DiscoverService{ - apiRegister: apiRegister, + invokerRegister: invokerRegister, } } func (ds *DiscoverService) GetAllServiceAPIs(ctx echo.Context, params discoverapi.GetAllServiceAPIsParams) error { - allApis := *ds.apiRegister.GetAPIs() + allApis := ds.invokerRegister.GetInvokerApiList(params.ApiInvokerId) + if allApis == nil { + return sendCoreError(ctx, http.StatusNotFound, "Invoker not registered") + } filteredApis := []publishapi.ServiceAPIDescription{} gatewayDomain := "r1-expo-func-aef" - for _, api := range allApis { + for _, api := range *allApis { if !matchesFilter(api, params) { continue } @@ -77,42 +80,33 @@ func matchesFilter(api publishapi.ServiceAPIDescription, filter discoverapi.GetA return false } profiles := *api.AefProfiles - aefIdMatch := true - protocolMatch := true - dataFormatMatch := true - versionMatch := true for _, profile := range profiles { - if filter.AefId != nil { - aefIdMatch = *filter.AefId == profile.AefId - } - if filter.ApiVersion != nil || filter.CommType != nil { - versionMatch = checkVersionAndCommType(profile, filter.ApiVersion, filter.CommType) - } - if filter.Protocol != nil { - protocolMatch = profile.Protocol != nil && *filter.Protocol == *profile.Protocol - } - if filter.DataFormat != nil { - dataFormatMatch = profile.DataFormat != nil && *filter.DataFormat == *profile.DataFormat - } - if aefIdMatch && versionMatch && protocolMatch && dataFormatMatch { + if checkAefId(filter, profile) && checkVersionAndCommType(profile, filter) && checkProtocol(filter, profile) && checkDataFormat(filter, profile) { return true } } return false } -func checkVersionAndCommType(profile publishapi.AefProfile, wantedVersion *string, commType *publishapi.CommunicationType) bool { +func checkAefId(filter discoverapi.GetAllServiceAPIsParams, profile publishapi.AefProfile) bool { + if filter.AefId != nil { + return *filter.AefId == profile.AefId + } + return true +} + +func checkVersionAndCommType(profile publishapi.AefProfile, filter discoverapi.GetAllServiceAPIsParams) bool { match := false - if wantedVersion != nil { + if filter.ApiVersion != nil { for _, version := range profile.Versions { - match = checkVersion(version, wantedVersion, commType) + match = checkVersion(version, filter.ApiVersion, filter.CommType) if match { break } } - } else if commType != nil { + } else if filter.CommType != nil { for _, version := range profile.Versions { - match = checkCommType(version.Resources, commType) + match = checkCommType(version.Resources, filter.CommType) } } else { match = true @@ -120,6 +114,20 @@ func checkVersionAndCommType(profile publishapi.AefProfile, wantedVersion *strin return match } +func checkProtocol(filter discoverapi.GetAllServiceAPIsParams, profile publishapi.AefProfile) bool { + if filter.Protocol != nil { + return profile.Protocol != nil && *filter.Protocol == *profile.Protocol + } + return true +} + +func checkDataFormat(filter discoverapi.GetAllServiceAPIsParams, profile publishapi.AefProfile) bool { + if filter.DataFormat != nil { + return profile.DataFormat != nil && *filter.DataFormat == *profile.DataFormat + } + return true +} + func checkVersion(version publishapi.Version, wantedVersion *string, commType *publishapi.CommunicationType) bool { match := false if *wantedVersion == version.ApiVersion { @@ -146,3 +154,14 @@ func checkCommType(resources *[]publishapi.Resource, commType *publishapi.Commun } return match } + +// 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 +} diff --git a/capifcore/internal/discoverservice/discoverservice_test.go b/capifcore/internal/discoverservice/discoverservice_test.go index fdb9c59..61235b7 100644 --- a/capifcore/internal/discoverservice/discoverservice_test.go +++ b/capifcore/internal/discoverservice/discoverservice_test.go @@ -26,15 +26,16 @@ import ( "os" "testing" + "oransc.org/nonrtric/capifcore/internal/common29122" "oransc.org/nonrtric/capifcore/internal/discoverserviceapi" - - "oransc.org/nonrtric/capifcore/internal/publishservice" + "oransc.org/nonrtric/capifcore/internal/invokermanagement" + "oransc.org/nonrtric/capifcore/internal/invokermanagementapi" "github.com/labstack/echo/v4" publishapi "oransc.org/nonrtric/capifcore/internal/publishserviceapi" - "oransc.org/nonrtric/capifcore/internal/publishservice/mocks" + "oransc.org/nonrtric/capifcore/internal/invokermanagement/mocks" "github.com/deepmap/oapi-codegen/pkg/middleware" "github.com/deepmap/oapi-codegen/pkg/testutil" @@ -52,12 +53,12 @@ func TestGetAllServiceAPIs(t *testing.T) { getAPI("apiName1", "aefId", "apiCategory", "v1", nil, nil, ""), getAPI("apiName2", "aefId", "apiCategory", "v1", nil, nil, ""), } - apiRegisterMock := mocks.APIRegister{} - apiRegisterMock.On("GetAPIs").Return(&apiList) - requestHandler := getEcho(&apiRegisterMock) + invokerId := "api_invoker_id" + invokerRegisterrMock := getInvokerRegisterMock(invokerId, apiList) + requestHandler := getEcho(invokerRegisterrMock) // Get all APIs, without any filter - result := testutil.NewRequest().Get("/allServiceAPIs?api-invoker-id=api_invoker_id").Go(t, requestHandler) + result := testutil.NewRequest().Get("/allServiceAPIs?api-invoker-id="+invokerId).Go(t, requestHandler) assert.Equal(t, http.StatusOK, result.Code()) var resultInvoker discoverserviceapi.DiscoveredAPIs @@ -66,23 +67,42 @@ func TestGetAllServiceAPIs(t *testing.T) { assert.Equal(t, 2, len(*resultInvoker.ServiceAPIDescriptions)) assert.Equal(t, "apiName1", (*resultInvoker.ServiceAPIDescriptions)[0].ApiName) assert.Equal(t, "apiName2", (*resultInvoker.ServiceAPIDescriptions)[1].ApiName) - apiRegisterMock.AssertCalled(t, "GetAPIs") assert.Equal(t, 2, len(*resultInvoker.ServiceAPIDescriptions)) } +func TestGetAllServiceAPIsWhenMissingProvider(t *testing.T) { + invokerId := "unregistered" + invokerRegisterrMock := getInvokerRegisterMock(invokerId, nil) + + requestHandler := getEcho(invokerRegisterrMock) + + // Get all APIs, without any filter + result := testutil.NewRequest().Get("/allServiceAPIs?api-invoker-id="+invokerId).Go(t, requestHandler) + + assert.Equal(t, http.StatusNotFound, result.Code()) + var problemDetails common29122.ProblemDetails + err := result.UnmarshalBodyToObject(&problemDetails) + assert.NoError(t, err, "error unmarshaling response") + notFound := http.StatusNotFound + assert.Equal(t, ¬Found, problemDetails.Status) + errMsg := "Invoker not registered" + assert.Equal(t, &errMsg, problemDetails.Cause) +} + func TestFilterApiName(t *testing.T) { var err error + apiName := "apiName1" apiList := []publishapi.ServiceAPIDescription{ - getAPI("apiName1", "", "", "", nil, nil, ""), + getAPI(apiName, "", "", "", nil, nil, ""), getAPI("apiName2", "", "", "", nil, nil, ""), } - apiRegisterMock := mocks.APIRegister{} - apiRegisterMock.On("GetAPIs").Return(&apiList) - requestHandler := getEcho(&apiRegisterMock) + invokerId := "api_invoker_id" + invokerRegisterrMock := getInvokerRegisterMock(invokerId, apiList) + requestHandler := getEcho(invokerRegisterrMock) // Get APIs with filter - result := testutil.NewRequest().Get("/allServiceAPIs?api-name=apiName1&api-invoker-id=api_invoker_id").Go(t, requestHandler) + result := testutil.NewRequest().Get("/allServiceAPIs?api-invoker-id="+invokerId+"&api-name="+apiName).Go(t, requestHandler) assert.Equal(t, http.StatusOK, result.Code()) var resultInvoker discoverserviceapi.DiscoveredAPIs @@ -95,16 +115,17 @@ func TestFilterApiName(t *testing.T) { func TestFilterAefId(t *testing.T) { var err error + aefId := "aefId" apiList := []publishapi.ServiceAPIDescription{ - getAPI("apiName1", "aefId", "", "", nil, nil, ""), + getAPI("apiName1", aefId, "", "", nil, nil, ""), getAPI("apiName2", "otherAefId", "", "", nil, nil, ""), } - apiRegisterMock := mocks.APIRegister{} - apiRegisterMock.On("GetAPIs").Return(&apiList) - requestHandler := getEcho(&apiRegisterMock) + invokerId := "api_invoker_id" + invokerRegisterrMock := getInvokerRegisterMock(invokerId, apiList) + requestHandler := getEcho(invokerRegisterrMock) // Get APIs with filter - result := testutil.NewRequest().Get("/allServiceAPIs?api-invoker-id=api_invoker_id&aef-id=aefId").Go(t, requestHandler) + result := testutil.NewRequest().Get("/allServiceAPIs?api-invoker-id="+invokerId+"&aef-id="+aefId).Go(t, requestHandler) assert.Equal(t, http.StatusOK, result.Code()) var resultInvoker discoverserviceapi.DiscoveredAPIs @@ -117,16 +138,17 @@ func TestFilterAefId(t *testing.T) { func TestFilterVersion(t *testing.T) { var err error + version := "v1" apiList := []publishapi.ServiceAPIDescription{ - getAPI("apiName1", "", "", "v1", nil, nil, ""), + getAPI("apiName1", "", "", version, nil, nil, ""), getAPI("apiName2", "", "", "v2", nil, nil, ""), } - apiRegisterMock := mocks.APIRegister{} - apiRegisterMock.On("GetAPIs").Return(&apiList) - requestHandler := getEcho(&apiRegisterMock) + invokerId := "api_invoker_id" + invokerRegisterrMock := getInvokerRegisterMock(invokerId, apiList) + requestHandler := getEcho(invokerRegisterrMock) // Get APIs with filter - result := testutil.NewRequest().Get("/allServiceAPIs?api-version=v1&api-invoker-id=api_invoker_id").Go(t, requestHandler) + result := testutil.NewRequest().Get("/allServiceAPIs?api-invoker-id="+invokerId+"&api-version="+version).Go(t, requestHandler) assert.Equal(t, http.StatusOK, result.Code()) var resultInvoker discoverserviceapi.DiscoveredAPIs @@ -139,16 +161,17 @@ func TestFilterVersion(t *testing.T) { func TestFilterCommType(t *testing.T) { var err error + commType := publishapi.CommunicationTypeREQUESTRESPONSE apiList := []publishapi.ServiceAPIDescription{ - getAPI("apiName1", "", "", "", nil, nil, publishapi.CommunicationTypeREQUESTRESPONSE), + getAPI("apiName1", "", "", "", nil, nil, commType), getAPI("apiName2", "", "", "", nil, nil, publishapi.CommunicationTypeSUBSCRIBENOTIFY), } - apiRegisterMock := mocks.APIRegister{} - apiRegisterMock.On("GetAPIs").Return(&apiList) - requestHandler := getEcho(&apiRegisterMock) + invokerId := "api_invoker_id" + invokerRegisterrMock := getInvokerRegisterMock(invokerId, apiList) + requestHandler := getEcho(invokerRegisterrMock) // Get APIs with filter - result := testutil.NewRequest().Get("/allServiceAPIs?api-invoker-id=api_invoker_id&comm-type=REQUEST_RESPONSE").Go(t, requestHandler) + result := testutil.NewRequest().Get("/allServiceAPIs?api-invoker-id="+invokerId+"&comm-type="+string(commType)).Go(t, requestHandler) assert.Equal(t, http.StatusOK, result.Code()) var resultInvoker discoverserviceapi.DiscoveredAPIs @@ -161,17 +184,19 @@ func TestFilterCommType(t *testing.T) { func TestFilterVersionAndCommType(t *testing.T) { var err error + version := "v1" + commType := publishapi.CommunicationTypeSUBSCRIBENOTIFY apiList := []publishapi.ServiceAPIDescription{ - getAPI("apiName1", "", "", "v1", nil, nil, publishapi.CommunicationTypeREQUESTRESPONSE), - getAPI("apiName2", "", "", "v1", nil, nil, publishapi.CommunicationTypeSUBSCRIBENOTIFY), - getAPI("apiName3", "", "", "v2", nil, nil, publishapi.CommunicationTypeSUBSCRIBENOTIFY), + getAPI("apiName1", "", "", version, nil, nil, publishapi.CommunicationTypeREQUESTRESPONSE), + getAPI("apiName2", "", "", version, nil, nil, commType), + getAPI("apiName3", "", "", "v2", nil, nil, commType), } - apiRegisterMock := mocks.APIRegister{} - apiRegisterMock.On("GetAPIs").Return(&apiList) - requestHandler := getEcho(&apiRegisterMock) + invokerId := "api_invoker_id" + invokerRegisterrMock := getInvokerRegisterMock(invokerId, apiList) + requestHandler := getEcho(invokerRegisterrMock) // Get APIs with filter - result := testutil.NewRequest().Get("/allServiceAPIs?api-invoker-id=api_invoker_id&api-version=v1&comm-type=SUBSCRIBE_NOTIFY").Go(t, requestHandler) + result := testutil.NewRequest().Get("/allServiceAPIs?api-invoker-id="+invokerId+"&api-version="+version+"&comm-type="+string(commType)).Go(t, requestHandler) assert.Equal(t, http.StatusOK, result.Code()) var resultInvoker discoverserviceapi.DiscoveredAPIs @@ -184,16 +209,17 @@ func TestFilterVersionAndCommType(t *testing.T) { func TestFilterAPICategory(t *testing.T) { var err error + apiCategory := "apiCategory" apiList := []publishapi.ServiceAPIDescription{ - getAPI("apiName1", "", "apiCategory", "", nil, nil, ""), + getAPI("apiName1", "", apiCategory, "", nil, nil, ""), getAPI("apiName2", "", "", "", nil, nil, ""), } - apiRegisterMock := mocks.APIRegister{} - apiRegisterMock.On("GetAPIs").Return(&apiList) - requestHandler := getEcho(&apiRegisterMock) + invokerId := "api_invoker_id" + invokerRegisterrMock := getInvokerRegisterMock(invokerId, apiList) + requestHandler := getEcho(invokerRegisterrMock) // Get APIs with filter - result := testutil.NewRequest().Get("/allServiceAPIs?api-invoker-id=api_invoker_id&api-cat=apiCategory").Go(t, requestHandler) + result := testutil.NewRequest().Get("/allServiceAPIs?api-invoker-id="+invokerId+"&api-cat="+apiCategory).Go(t, requestHandler) assert.Equal(t, http.StatusOK, result.Code()) var resultInvoker discoverserviceapi.DiscoveredAPIs @@ -210,12 +236,12 @@ func TestFilterProtocol(t *testing.T) { getAPI("apiName1", "", "", "", &protocolHTTP11, nil, ""), getAPI("apiName2", "", "", "", nil, nil, ""), } - apiRegisterMock := mocks.APIRegister{} - apiRegisterMock.On("GetAPIs").Return(&apiList) - requestHandler := getEcho(&apiRegisterMock) + invokerId := "api_invoker_id" + invokerRegisterrMock := getInvokerRegisterMock(invokerId, apiList) + requestHandler := getEcho(invokerRegisterrMock) // Get APIs with filter - result := testutil.NewRequest().Get("/allServiceAPIs?api-invoker-id=api_invoker_id&protocol=HTTP_1_1").Go(t, requestHandler) + result := testutil.NewRequest().Get("/allServiceAPIs?api-invoker-id="+invokerId+"&protocol="+string(protocolHTTP11)).Go(t, requestHandler) assert.Equal(t, http.StatusOK, result.Code()) var resultInvoker discoverserviceapi.DiscoveredAPIs @@ -234,12 +260,12 @@ func TestFilterDataFormat(t *testing.T) { getAPI("apiName1", "", "", "", nil, &dataFormatJSON, ""), getAPI("apiName2", "", "", "", nil, nil, ""), } - apiRegisterMock := mocks.APIRegister{} - apiRegisterMock.On("GetAPIs").Return(&apiList) - requestHandler := getEcho(&apiRegisterMock) + invokerId := "api_invoker_id" + invokerRegisterrMock := getInvokerRegisterMock(invokerId, apiList) + requestHandler := getEcho(invokerRegisterrMock) // Get APIs with filter - result := testutil.NewRequest().Get("/allServiceAPIs?api-invoker-id=api_invoker_id&data-format=JSON").Go(t, requestHandler) + result := testutil.NewRequest().Get("/allServiceAPIs?api-invoker-id="+invokerId+"&data-format="+string(dataFormatJSON)).Go(t, requestHandler) assert.Equal(t, http.StatusOK, result.Code()) var resultInvoker discoverserviceapi.DiscoveredAPIs @@ -249,7 +275,7 @@ func TestFilterDataFormat(t *testing.T) { assert.Equal(t, "apiName1", (*resultInvoker.ServiceAPIDescriptions)[0].ApiName) } -func getEcho(apiRegister publishservice.APIRegister) *echo.Echo { +func getEcho(invokerManager invokermanagement.InvokerRegister) *echo.Echo { swagger, err := discoverserviceapi.GetSwagger() if err != nil { fmt.Fprintf(os.Stderr, "Error loading swagger spec\n: %s", err) @@ -258,7 +284,7 @@ func getEcho(apiRegister publishservice.APIRegister) *echo.Echo { swagger.Servers = nil - ds := NewDiscoverService(apiRegister) + ds := NewDiscoverService(invokerManager) e := echo.New() e.Use(echomiddleware.Logger()) @@ -268,6 +294,17 @@ func getEcho(apiRegister publishservice.APIRegister) *echo.Echo { return e } +func getInvokerRegisterMock(invokerId string, apisToReturn []publishapi.ServiceAPIDescription) *mocks.InvokerRegister { + apiList := invokermanagementapi.APIList(apisToReturn) + invokerRegisterrMock := mocks.InvokerRegister{} + if apisToReturn != nil { + invokerRegisterrMock.On("GetInvokerApiList", invokerId).Return(&apiList) + } else { + invokerRegisterrMock.On("GetInvokerApiList", invokerId).Return(nil) + } + return &invokerRegisterrMock +} + func getAPI(apiName, aefId, apiCategory, apiVersion string, protocol *publishapi.Protocol, dataFormat *publishapi.DataFormat, commType publishapi.CommunicationType) publishapi.ServiceAPIDescription { apiId := "apiId_" + apiName description := "description" diff --git a/capifcore/main.go b/capifcore/main.go index cf41699..7a3f96f 100644 --- a/capifcore/main.go +++ b/capifcore/main.go @@ -103,17 +103,6 @@ func getEcho() *echo.Echo { group.Use(middleware.OapiRequestValidator(publishServiceSwagger)) publishserviceapi.RegisterHandlersWithBaseURL(e, publishService, "/published-apis/v1") - // Register DiscoverService - discoverServiceSwagger, err := discoverserviceapi.GetSwagger() - if err != nil { - log.Fatalf("Error loading DiscoverService swagger spec\n: %s", err) - } - discoverServiceSwagger.Servers = nil - discoverService := discoverservice.NewDiscoverService(publishService) - group = e.Group("/service-apis/v1") - group.Use(middleware.OapiRequestValidator(discoverServiceSwagger)) - discoverserviceapi.RegisterHandlersWithBaseURL(e, discoverService, "/service-apis/v1") - // Register InvokerManagement invokerManagerSwagger, err := invokermanagementapi.GetSwagger() if err != nil { @@ -125,6 +114,17 @@ func getEcho() *echo.Echo { group.Use(middleware.OapiRequestValidator(invokerManagerSwagger)) invokermanagementapi.RegisterHandlersWithBaseURL(e, invokerManager, "/api-invoker-management/v1") + // Register DiscoverService + discoverServiceSwagger, err := discoverserviceapi.GetSwagger() + if err != nil { + log.Fatalf("Error loading DiscoverService swagger spec\n: %s", err) + } + discoverServiceSwagger.Servers = nil + discoverService := discoverservice.NewDiscoverService(invokerManager) + group = e.Group("/service-apis/v1") + group.Use(middleware.OapiRequestValidator(discoverServiceSwagger)) + discoverserviceapi.RegisterHandlersWithBaseURL(e, discoverService, "/service-apis/v1") + // Register Security securitySwagger, err := publishserviceapi.GetSwagger() if err != nil { diff --git a/capifcore/main_test.go b/capifcore/main_test.go index 383c5aa..1894516 100644 --- a/capifcore/main_test.go +++ b/capifcore/main_test.go @@ -71,7 +71,7 @@ func Test_routing(t *testing.T) { name: "Discover path", args: args{ url: "/service-apis/v1/allServiceAPIs?api-invoker-id=api_invoker_id", - returnStatus: http.StatusOK, + returnStatus: http.StatusNotFound, method: "GET", }, }, -- 2.16.6