2 // ========================LICENSE_START=================================
5 // Copyright (C) 2024: OpenInfra Foundation Europe
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
31 echo "github.com/labstack/echo/v4"
33 "oransc.org/nonrtric/servicemanager/internal/common29122"
34 "oransc.org/nonrtric/servicemanager/internal/envreader"
35 "oransc.org/nonrtric/servicemanager/internal/kongclear"
37 provapi "oransc.org/nonrtric/servicemanager/internal/providermanagementapi"
39 "github.com/deepmap/oapi-codegen/pkg/middleware"
40 "github.com/deepmap/oapi-codegen/pkg/testutil"
41 echomiddleware "github.com/labstack/echo/v4/middleware"
42 log "github.com/sirupsen/logrus"
44 "github.com/stretchr/testify/assert"
46 "oransc.org/nonrtric/capifcore"
47 "oransc.org/nonrtric/servicemanager/mockkong"
51 domainID = "domain_id_Kong"
53 funcInfoAPF = "rApp Kong as APF"
54 funcIdAPF = "APF_id_rApp_Kong_as_APF"
55 funcInfoAEF = "rApp Kong as AEF"
56 funcIdAEF = "AEF_id_rApp_Kong_as_AEF"
60 eServiceManager *echo.Echo
63 mockConfigReader *envreader.MockConfigReader
64 serviceManagerServer *httptest.Server
65 capifServer *httptest.Server
66 mockKongServer *httptest.Server
69 func TestMain(m *testing.M) {
82 func setupTest() error {
83 // Start the mock Kong server
85 mockKong.RegisterHandlers(eKong)
86 mockKongServer = httptest.NewServer(eKong)
88 // Parse the server URL
89 parsedMockKongURL, err := url.Parse(mockKongServer.URL)
91 log.Fatalf("error parsing mock Kong URL: %v", err)
95 // Extract the host and port
96 mockKongHost := parsedMockKongURL.Hostname()
97 mockKongControlPlanePort := parsedMockKongURL.Port()
99 eCapifWeb = echo.New()
100 capifcore.RegisterHandlers(eCapifWeb, nil, nil)
101 capifServer = httptest.NewServer(eCapifWeb)
103 // Parse the server URL
104 parsedCapifURL, err := url.Parse(capifServer.URL)
106 log.Fatalf("error parsing mock Kong URL: %v", err)
110 // Extract the host and port
111 capifHost := parsedCapifURL.Hostname()
112 capifPort := parsedCapifURL.Port()
114 // Set up the mock config reader with the desired configuration for testing
115 mockConfigReader = &envreader.MockConfigReader{
116 MockedConfig: map[string]string{
117 "KONG_DOMAIN": "kong",
118 "KONG_PROTOCOL": "http",
119 "KONG_IPV4": mockKongHost,
120 "KONG_DATA_PLANE_PORT": "32080",
121 "KONG_CONTROL_PLANE_PORT": mockKongControlPlanePort,
122 "CAPIF_PROTOCOL": "http",
123 "CAPIF_IPV4": capifHost,
124 "CAPIF_PORT": capifPort,
126 "SERVICE_MANAGER_PORT": "8095",
127 "TEST_SERVICE_IPV4": "10.101.1.101",
128 "TEST_SERVICE_PORT": "30951",
132 myEnv, myPorts, err := mockConfigReader.ReadDotEnv()
134 log.Fatal("error loading environment file on setupTest")
138 eServiceManager = echo.New()
139 err = registerHandlers(eServiceManager, myEnv, myPorts)
141 log.Fatal("registerHandlers fatal error on setupTest")
144 serviceManagerServer = httptest.NewServer(eServiceManager)
150 func capifCleanUp() {
151 t := new(testing.T) // Create a new testing.T instance for capifCleanUp
153 // Delete the invoker
154 invokerInfo := "invoker a"
155 invokerId := "api_invoker_id_" + strings.Replace(invokerInfo, " ", "_", 1)
157 result := testutil.NewRequest().Delete("/api-invoker-management/v1/onboardedInvokers/"+invokerId).Go(t, eServiceManager)
158 assert.Equal(t, http.StatusNoContent, result.Code())
160 // Delete the original published service
161 apfId := "APF_id_rApp_Kong_as_APF"
163 apiId := "api_id_" + apiName
165 result = testutil.NewRequest().Delete("/published-apis/v1/"+apfId+"/service-apis/"+apiId).Go(t, eServiceManager)
166 assert.Equal(t, http.StatusNoContent, result.Code())
168 // Delete the first published service
169 apfId = "APF_id_rApp_Kong_as_APF"
171 apiId = "api_id_" + apiName
173 result = testutil.NewRequest().Delete("/published-apis/v1/"+apfId+"/service-apis/"+apiId).Go(t, eServiceManager)
174 assert.Equal(t, http.StatusNoContent, result.Code())
176 // Delete the second published service
178 apiId = "api_id_" + apiName
180 result = testutil.NewRequest().Delete("/published-apis/v1/"+apfId+"/service-apis/"+apiId).Go(t, eServiceManager)
181 assert.Equal(t, http.StatusNoContent, result.Code())
183 // Delete the provider
184 result = testutil.NewRequest().Delete("/api-provider-management/v1/registrations/"+domainID).Go(t, eServiceManager)
185 assert.Equal(t, http.StatusNoContent, result.Code())
189 func teardown() error {
190 log.Trace("entering teardown")
192 myEnv, myPorts, err := mockConfigReader.ReadDotEnv()
194 log.Fatal("error loading environment file")
198 err = kongclear.KongClear(myEnv, myPorts)
200 log.Fatal("error clearing Kong on teardown")
203 mockKongServer.Close()
205 serviceManagerServer.Close()
210 func TestRegisterValidProvider(t *testing.T) {
213 // Register a valid provider
214 newProvider := getProvider()
215 result := testutil.NewRequest().Post("/api-provider-management/v1/registrations").WithJsonBody(newProvider).Go(t, eServiceManager)
216 assert.Equal(t, http.StatusCreated, result.Code())
218 var resultProvider provapi.APIProviderEnrolmentDetails
219 err := result.UnmarshalBodyToObject(&resultProvider)
220 assert.NoError(t, err, "error unmarshaling response")
222 assert.NotNil(t, resultProvider.ApiProvDomId, "error reading resultProvider")
224 if resultProvider.ApiProvDomId != nil {
225 assert.Equal(t, *resultProvider.ApiProvDomId, domainID)
227 apiProvFuncAPF := (*resultProvider.ApiProvFuncs)[0]
228 apiProvFuncIdAPF := *apiProvFuncAPF.ApiProvFuncId
229 assert.Equal(t, apiProvFuncIdAPF, funcIdAPF)
231 // We don't handle AMF
232 apiProvFuncAEF := (*resultProvider.ApiProvFuncs)[1]
233 apiProvFuncIdAEF := *apiProvFuncAEF.ApiProvFuncId
234 assert.Equal(t, apiProvFuncIdAEF, funcIdAEF)
236 assert.Empty(t, resultProvider.FailReason)
237 assert.Equal(t, "http://example.com/api-provider-management/v1/registrations/"+*resultProvider.ApiProvDomId, result.Recorder.Header().Get(echo.HeaderLocation))
239 // Register same provider again should result in Forbidden
240 result = testutil.NewRequest().Post("/api-provider-management/v1/registrations").WithJsonBody(newProvider).Go(t, eServiceManager)
242 assert.Equal(t, http.StatusForbidden, result.Code())
244 var errorObj common29122.ProblemDetails
245 err = result.UnmarshalBodyToObject(&errorObj)
246 assert.NoError(t, err, "error unmarshaling response")
247 assert.Equal(t, http.StatusForbidden, *errorObj.Status)
248 assert.Contains(t, *errorObj.Cause, "already registered")
252 func TestUpdateValidProviderWithNewFunction(t *testing.T) {
253 // Modify the provider
254 updatedProvider := getProvider()
255 updatedProvider.ApiProvDomId = &domainID
257 newDomainInfo := "New domain info"
258 updatedProvider.ApiProvDomInfo = &newDomainInfo
259 newFunctionInfo := "New function info"
260 (*updatedProvider.ApiProvFuncs)[0].ApiProvFuncInfo = &newFunctionInfo
261 newFuncInfoAEF := "new func as AEF"
263 testFuncs := append(*updatedProvider.ApiProvFuncs, provapi.APIProviderFunctionDetails{
264 ApiProvFuncInfo: &newFuncInfoAEF,
265 ApiProvFuncRole: provapi.ApiProviderFuncRoleAEF,
266 RegInfo: provapi.RegistrationInformation{
267 ApiProvPubKey: "key",
270 updatedProvider.ApiProvFuncs = &testFuncs
272 result := testutil.NewRequest().Put("/api-provider-management/v1/registrations/"+domainID).WithJsonBody(updatedProvider).Go(t, eServiceManager)
274 var resultProvider provapi.APIProviderEnrolmentDetails
275 assert.Equal(t, http.StatusOK, result.Code())
277 err := result.UnmarshalBodyToObject(&resultProvider)
278 assert.NoError(t, err, "error unmarshaling response")
280 assert.Equal(t, newDomainInfo, *resultProvider.ApiProvDomInfo)
281 assert.Equal(t, newFunctionInfo, *(*resultProvider.ApiProvFuncs)[0].ApiProvFuncInfo)
282 assert.Equal(t, *(*resultProvider.ApiProvFuncs)[2].ApiProvFuncId, "AEF_id_new_func_as_AEF")
283 assert.Empty(t, resultProvider.FailReason)
286 func TestDeleteProvider(t *testing.T) {
287 provider := getProvider()
288 provider.ApiProvDomId = &domainID
289 (*provider.ApiProvFuncs)[0].ApiProvFuncId = &funcIdAPF
290 result := testutil.NewRequest().Delete("/api-provider-management/v1/registrations/"+domainID).Go(t, eServiceManager)
291 assert.Equal(t, http.StatusNoContent, result.Code())
295 func getProvider() provapi.APIProviderEnrolmentDetails {
296 testFuncs := []provapi.APIProviderFunctionDetails{
298 ApiProvFuncInfo: &funcInfoAPF,
299 ApiProvFuncRole: provapi.ApiProviderFuncRoleAPF,
300 RegInfo: provapi.RegistrationInformation{
301 ApiProvPubKey: "APF-PublicKey",
305 ApiProvFuncInfo: &funcInfoAEF,
306 ApiProvFuncRole: provapi.ApiProviderFuncRoleAEF,
307 RegInfo: provapi.RegistrationInformation{
308 ApiProvPubKey: "AEF-PublicKey",
312 return provapi.APIProviderEnrolmentDetails{
314 ApiProvDomInfo: &domainInfo,
315 ApiProvFuncs: &testFuncs,
319 func registerHandlers(e *echo.Echo, myEnv map[string]string, myPorts map[string]int) (err error) {
320 capifProtocol := myEnv["CAPIF_PROTOCOL"]
321 capifIPv4 := common29122.Ipv4Addr(myEnv["CAPIF_IPV4"])
322 capifPort := common29122.Port(myPorts["CAPIF_PORT"])
324 // Register ProviderManagement
325 providerManagerSwagger, err := provapi.GetSwagger()
327 log.Fatalf("Error loading ProviderManagement swagger spec\n: %s", err)
330 providerManagerSwagger.Servers = nil
331 providerManager := NewProviderManager(capifProtocol, capifIPv4, capifPort)
333 group := e.Group("/api-provider-management/v1")
334 group.Use(echomiddleware.Logger())
335 group.Use(middleware.OapiRequestValidator(providerManagerSwagger))
336 provapi.RegisterHandlersWithBaseURL(e, providerManager, "/api-provider-management/v1")