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_CONTROL_PLANE_IPV4": mockKongHost,
120 "KONG_CONTROL_PLANE_PORT": mockKongControlPlanePort,
121 "KONG_DATA_PLANE_IPV4": "10.101.1.101",
122 "KONG_DATA_PLANE_PORT": "32080",
123 "CAPIF_PROTOCOL": "http",
124 "CAPIF_IPV4": capifHost,
125 "CAPIF_PORT": capifPort,
127 "SERVICE_MANAGER_PORT": "8095",
128 "TEST_SERVICE_IPV4": "10.101.1.101",
129 "TEST_SERVICE_PORT": "30951",
133 myEnv, myPorts, err := mockConfigReader.ReadDotEnv()
135 log.Fatal("error loading environment file on setupTest")
139 eServiceManager = echo.New()
140 err = registerHandlers(eServiceManager, myEnv, myPorts)
142 log.Fatal("registerHandlers fatal error on setupTest")
145 serviceManagerServer = httptest.NewServer(eServiceManager)
151 func capifCleanUp() {
152 t := new(testing.T) // Create a new testing.T instance for capifCleanUp
154 // Delete the invoker
155 invokerInfo := "invoker a"
156 invokerId := "api_invoker_id_" + strings.Replace(invokerInfo, " ", "_", 1)
158 result := testutil.NewRequest().Delete("/api-invoker-management/v1/onboardedInvokers/"+invokerId).Go(t, eServiceManager)
159 assert.Equal(t, http.StatusNoContent, result.Code())
161 // Delete the original published service
162 apfId := "APF_id_rApp_Kong_as_APF"
164 apiId := "api_id_" + apiName
166 result = testutil.NewRequest().Delete("/published-apis/v1/"+apfId+"/service-apis/"+apiId).Go(t, eServiceManager)
167 assert.Equal(t, http.StatusNoContent, result.Code())
169 // Delete the first published service
170 apfId = "APF_id_rApp_Kong_as_APF"
172 apiId = "api_id_" + apiName
174 result = testutil.NewRequest().Delete("/published-apis/v1/"+apfId+"/service-apis/"+apiId).Go(t, eServiceManager)
175 assert.Equal(t, http.StatusNoContent, result.Code())
177 // Delete the second published service
179 apiId = "api_id_" + apiName
181 result = testutil.NewRequest().Delete("/published-apis/v1/"+apfId+"/service-apis/"+apiId).Go(t, eServiceManager)
182 assert.Equal(t, http.StatusNoContent, result.Code())
184 // Delete the provider
185 result = testutil.NewRequest().Delete("/api-provider-management/v1/registrations/"+domainID).Go(t, eServiceManager)
186 assert.Equal(t, http.StatusNoContent, result.Code())
190 func teardown() error {
191 log.Trace("entering teardown")
193 myEnv, myPorts, err := mockConfigReader.ReadDotEnv()
195 log.Fatal("error loading environment file")
199 err = kongclear.KongClear(myEnv, myPorts)
201 log.Fatal("error clearing Kong on teardown")
204 mockKongServer.Close()
206 serviceManagerServer.Close()
211 func TestRegisterValidProvider(t *testing.T) {
214 // Register a valid provider
215 newProvider := getProvider()
216 result := testutil.NewRequest().Post("/api-provider-management/v1/registrations").WithJsonBody(newProvider).Go(t, eServiceManager)
217 assert.Equal(t, http.StatusCreated, result.Code())
219 var resultProvider provapi.APIProviderEnrolmentDetails
220 err := result.UnmarshalBodyToObject(&resultProvider)
221 assert.NoError(t, err, "error unmarshaling response")
223 assert.NotNil(t, resultProvider.ApiProvDomId, "error reading resultProvider")
225 if resultProvider.ApiProvDomId != nil {
226 assert.Equal(t, *resultProvider.ApiProvDomId, domainID)
228 apiProvFuncAPF := (*resultProvider.ApiProvFuncs)[0]
229 apiProvFuncIdAPF := *apiProvFuncAPF.ApiProvFuncId
230 assert.Equal(t, apiProvFuncIdAPF, funcIdAPF)
232 // We don't handle AMF
233 apiProvFuncAEF := (*resultProvider.ApiProvFuncs)[1]
234 apiProvFuncIdAEF := *apiProvFuncAEF.ApiProvFuncId
235 assert.Equal(t, apiProvFuncIdAEF, funcIdAEF)
237 assert.Empty(t, resultProvider.FailReason)
238 assert.Equal(t, "http://example.com/api-provider-management/v1/registrations/"+*resultProvider.ApiProvDomId, result.Recorder.Header().Get(echo.HeaderLocation))
240 // Register same provider again should result in Forbidden
241 result = testutil.NewRequest().Post("/api-provider-management/v1/registrations").WithJsonBody(newProvider).Go(t, eServiceManager)
243 assert.Equal(t, http.StatusForbidden, result.Code())
245 var errorObj common29122.ProblemDetails
246 err = result.UnmarshalBodyToObject(&errorObj)
247 assert.NoError(t, err, "error unmarshaling response")
248 assert.Equal(t, http.StatusForbidden, *errorObj.Status)
249 assert.Contains(t, *errorObj.Cause, "already registered")
253 func TestUpdateValidProviderWithNewFunction(t *testing.T) {
254 // Modify the provider
255 updatedProvider := getProvider()
256 updatedProvider.ApiProvDomId = &domainID
258 newDomainInfo := "New domain info"
259 updatedProvider.ApiProvDomInfo = &newDomainInfo
260 newFunctionInfo := "New function info"
261 (*updatedProvider.ApiProvFuncs)[0].ApiProvFuncInfo = &newFunctionInfo
262 newFuncInfoAEF := "new func as AEF"
264 testFuncs := append(*updatedProvider.ApiProvFuncs, provapi.APIProviderFunctionDetails{
265 ApiProvFuncInfo: &newFuncInfoAEF,
266 ApiProvFuncRole: provapi.ApiProviderFuncRoleAEF,
267 RegInfo: provapi.RegistrationInformation{
268 ApiProvPubKey: "key",
271 updatedProvider.ApiProvFuncs = &testFuncs
273 result := testutil.NewRequest().Put("/api-provider-management/v1/registrations/"+domainID).WithJsonBody(updatedProvider).Go(t, eServiceManager)
275 var resultProvider provapi.APIProviderEnrolmentDetails
276 assert.Equal(t, http.StatusOK, result.Code())
278 err := result.UnmarshalBodyToObject(&resultProvider)
279 assert.NoError(t, err, "error unmarshaling response")
281 assert.Equal(t, newDomainInfo, *resultProvider.ApiProvDomInfo)
282 assert.Equal(t, newFunctionInfo, *(*resultProvider.ApiProvFuncs)[0].ApiProvFuncInfo)
283 assert.Equal(t, *(*resultProvider.ApiProvFuncs)[2].ApiProvFuncId, "AEF_id_new_func_as_AEF")
284 assert.Empty(t, resultProvider.FailReason)
287 func TestDeleteProvider(t *testing.T) {
288 provider := getProvider()
289 provider.ApiProvDomId = &domainID
290 (*provider.ApiProvFuncs)[0].ApiProvFuncId = &funcIdAPF
291 result := testutil.NewRequest().Delete("/api-provider-management/v1/registrations/"+domainID).Go(t, eServiceManager)
292 assert.Equal(t, http.StatusNoContent, result.Code())
296 func getProvider() provapi.APIProviderEnrolmentDetails {
297 testFuncs := []provapi.APIProviderFunctionDetails{
299 ApiProvFuncInfo: &funcInfoAPF,
300 ApiProvFuncRole: provapi.ApiProviderFuncRoleAPF,
301 RegInfo: provapi.RegistrationInformation{
302 ApiProvPubKey: "APF-PublicKey",
306 ApiProvFuncInfo: &funcInfoAEF,
307 ApiProvFuncRole: provapi.ApiProviderFuncRoleAEF,
308 RegInfo: provapi.RegistrationInformation{
309 ApiProvPubKey: "AEF-PublicKey",
313 return provapi.APIProviderEnrolmentDetails{
315 ApiProvDomInfo: &domainInfo,
316 ApiProvFuncs: &testFuncs,
320 func registerHandlers(e *echo.Echo, myEnv map[string]string, myPorts map[string]int) (err error) {
321 capifProtocol := myEnv["CAPIF_PROTOCOL"]
322 capifIPv4 := common29122.Ipv4Addr(myEnv["CAPIF_IPV4"])
323 capifPort := common29122.Port(myPorts["CAPIF_PORT"])
325 // Register ProviderManagement
326 providerManagerSwagger, err := provapi.GetSwagger()
328 log.Fatalf("Error loading ProviderManagement swagger spec\n: %s", err)
331 providerManagerSwagger.Servers = nil
332 providerManager := NewProviderManager(capifProtocol, capifIPv4, capifPort)
334 group := e.Group("/api-provider-management/v1")
335 group.Use(echomiddleware.Logger())
336 group.Use(middleware.OapiRequestValidator(providerManagerSwagger))
337 provapi.RegisterHandlersWithBaseURL(e, providerManager, "/api-provider-management/v1")