NONRTRIC-946: Servicemanager - add Kong data plane and control plane
[nonrtric/plt/sme.git] / servicemanager / internal / publishservice / publishservice_test.go
index bd5264d..c42cba7 100644 (file)
@@ -23,6 +23,8 @@ package publishservice
 import (
        "fmt"
        "net/http"
+       "net/http/httptest"
+       "net/url"
        "os"
        "strings"
        "testing"
@@ -34,15 +36,27 @@ import (
        log "github.com/sirupsen/logrus"
        "github.com/stretchr/testify/assert"
 
-       "oransc.org/nonrtric/servicemanager/internal/common29122"
        "oransc.org/nonrtric/servicemanager/internal/envreader"
        "oransc.org/nonrtric/servicemanager/internal/kongclear"
+
+       "oransc.org/nonrtric/servicemanager/internal/common29122"
        "oransc.org/nonrtric/servicemanager/internal/providermanagement"
        provapi "oransc.org/nonrtric/servicemanager/internal/providermanagementapi"
        publishapi "oransc.org/nonrtric/servicemanager/internal/publishserviceapi"
+
+       "oransc.org/nonrtric/capifcore"
+       mockKong "oransc.org/nonrtric/servicemanager/mockkong"
 )
 
-var requestHandler *echo.Echo
+var (
+       eServiceManager      *echo.Echo
+       eCapifWeb            *echo.Echo
+       eKong                *echo.Echo
+       mockConfigReader     *envreader.MockConfigReader
+       serviceManagerServer *httptest.Server
+       capifServer          *httptest.Server
+       mockKongServer       *httptest.Server
+)
 
 func TestMain(m *testing.M) {
        err := setupTest()
@@ -58,23 +72,70 @@ func TestMain(m *testing.M) {
 }
 
 func setupTest() error {
-       myEnv, myPorts, err := envreader.ReadDotEnv()
+       // Start the mock Kong server
+       eKong = echo.New()
+       mockKong.RegisterHandlers(eKong)
+       mockKongServer = httptest.NewServer(eKong)
+
+       // Parse the server URL
+       parsedMockKongURL, err := url.Parse(mockKongServer.URL)
        if err != nil {
-               log.Fatal("error loading environment file on setupTest")
+               log.Fatalf("error parsing mock Kong URL: %v", err)
                return err
        }
 
-       requestHandler, err = getEcho(myEnv, myPorts)
+       // Extract the host and port
+       mockKongHost := parsedMockKongURL.Hostname()
+       mockKongControlPlanePort := parsedMockKongURL.Port()
+
+       eCapifWeb = echo.New()
+       capifcore.RegisterHandlers(eCapifWeb, nil, nil)
+       capifServer = httptest.NewServer(eCapifWeb)
+
+       // Parse the server URL
+       parsedCapifURL, err := url.Parse(capifServer.URL)
        if err != nil {
-               log.Fatal("getEcho fatal error on setupTest")
+               log.Fatalf("error parsing mock Kong URL: %v", err)
                return err
        }
-       err = teardown()
+
+       // Extract the host and port
+       capifHost := parsedCapifURL.Hostname()
+       capifPort := parsedCapifURL.Port()
+
+       // Set up the mock config reader with the desired configuration for testing
+       mockConfigReader = &envreader.MockConfigReader{
+               MockedConfig: map[string]string{
+                       "KONG_DOMAIN":             "kong",
+                       "KONG_PROTOCOL":           "http",
+                       "KONG_CONTROL_PLANE_IPV4": mockKongHost,
+                       "KONG_CONTROL_PLANE_PORT": mockKongControlPlanePort,
+                       "KONG_DATA_PLANE_IPV4":    "10.101.1.101",
+                       "KONG_DATA_PLANE_PORT":    "32080",
+                       "CAPIF_PROTOCOL":          "http",
+                       "CAPIF_IPV4":              capifHost,
+                       "CAPIF_PORT":              capifPort,
+                       "LOG_LEVEL":               "Info",
+                       "SERVICE_MANAGER_PORT":    "8095",
+                       "TEST_SERVICE_IPV4":       "10.101.1.101",
+                       "TEST_SERVICE_PORT":       "30951",
+               },
+       }
+
+       // Use the mock implementation for testing
+       myEnv, myPorts, err := mockConfigReader.ReadDotEnv()
        if err != nil {
-               log.Fatal("getEcho fatal error on teardown")
-               return err
+               log.Fatalf("error reading mock config: %v", err)
        }
 
+       eServiceManager = echo.New()
+       err = registerHandlers(eServiceManager, myEnv, myPorts)
+       if err != nil {
+               log.Fatal("registerHandlers fatal error on setupTest")
+               return err
+       }
+       serviceManagerServer = httptest.NewServer(eServiceManager)
+       capifCleanUp()
        return err
 }
 
@@ -108,16 +169,14 @@ func getProvider() provapi.APIProviderEnrolmentDetails {
        }
 }
 
-func teardown() error {
-       log.Trace("entering teardown")
-
-       t := new(testing.T) // Create a new testing.T instance for teardown
+func capifCleanUp() {
+       t := new(testing.T) // Create a new testing.T instance for capifCleanUp
 
        // Delete the invoker
        invokerInfo := "invoker a"
        invokerId := "api_invoker_id_" + strings.Replace(invokerInfo, " ", "_", 1)
 
-       result := testutil.NewRequest().Delete("/api-invoker-management/v1/onboardedInvokers/"+invokerId).Go(t, requestHandler)
+       result := testutil.NewRequest().Delete("/api-invoker-management/v1/onboardedInvokers/"+invokerId).Go(t, eServiceManager)
        assert.Equal(t, http.StatusNoContent, result.Code())
 
        // Delete the original published service
@@ -125,7 +184,7 @@ func teardown() error {
        apiName := "apiName"
        apiId := "api_id_" + apiName
 
-       result = testutil.NewRequest().Delete("/published-apis/v1/"+apfId+"/service-apis/"+apiId).Go(t, requestHandler)
+       result = testutil.NewRequest().Delete("/published-apis/v1/"+apfId+"/service-apis/"+apiId).Go(t, eServiceManager)
        assert.Equal(t, http.StatusNoContent, result.Code())
 
        // Delete the first published service
@@ -133,22 +192,26 @@ func teardown() error {
        apiName = "apiName1"
        apiId = "api_id_" + apiName
 
-       result = testutil.NewRequest().Delete("/published-apis/v1/"+apfId+"/service-apis/"+apiId).Go(t, requestHandler)
+       result = testutil.NewRequest().Delete("/published-apis/v1/"+apfId+"/service-apis/"+apiId).Go(t, eServiceManager)
        assert.Equal(t, http.StatusNoContent, result.Code())
 
        // Delete the second published service
        apiName = "apiName2"
        apiId = "api_id_" + apiName
 
-       result = testutil.NewRequest().Delete("/published-apis/v1/"+apfId+"/service-apis/"+apiId).Go(t, requestHandler)
+       result = testutil.NewRequest().Delete("/published-apis/v1/"+apfId+"/service-apis/"+apiId).Go(t, eServiceManager)
        assert.Equal(t, http.StatusNoContent, result.Code())
 
        // Delete the provider
        domainID := "domain_id_Kong"
-       result = testutil.NewRequest().Delete("/api-provider-management/v1/registrations/"+domainID).Go(t, requestHandler)
+       result = testutil.NewRequest().Delete("/api-provider-management/v1/registrations/"+domainID).Go(t, eServiceManager)
        assert.Equal(t, http.StatusNoContent, result.Code())
+}
+
+func teardown() error {
+       log.Trace("entering teardown")
 
-       myEnv, myPorts, err := envreader.ReadDotEnv()
+       myEnv, myPorts, err := mockConfigReader.ReadDotEnv()
        if err != nil {
                log.Fatal("error loading environment file")
                return err
@@ -158,17 +221,21 @@ func teardown() error {
        if err != nil {
                log.Fatal("error clearing Kong on teardown")
        }
-       return err
+
+       mockKongServer.Close()
+       capifServer.Close()
+       serviceManagerServer.Close()
+
+       return nil
 }
 
 func TestPostUnpublishedServiceWithUnregisteredPublisher(t *testing.T) {
-       teardown()
+       capifCleanUp()
 
        apfId := "APF_id_rApp_Kong_as_APF"
-       apiName := "apiName"
 
        // Check no services published
-       result := testutil.NewRequest().Get("/published-apis/v1/"+apfId+"/service-apis").Go(t, requestHandler)
+       result := testutil.NewRequest().Get("/published-apis/v1/"+apfId+"/service-apis").Go(t, eServiceManager)
        assert.Equal(t, http.StatusNotFound, result.Code())
 
        var resultError common29122.ProblemDetails
@@ -185,7 +252,7 @@ func TestPostUnpublishedServiceWithUnregisteredPublisher(t *testing.T) {
        releaseName := "releaseName"
        description := fmt.Sprintf("Description,%s,%s,%s,%s", namespace, repoName, chartName, releaseName)
 
-       myEnv, myPorts, err := envreader.ReadDotEnv()
+       myEnv, myPorts, err := mockConfigReader.ReadDotEnv()
        assert.Nil(t, err, "error reading env file")
 
        testServiceIpv4 := common29122.Ipv4Addr(myEnv["TEST_SERVICE_IPV4"])
@@ -194,10 +261,11 @@ func TestPostUnpublishedServiceWithUnregisteredPublisher(t *testing.T) {
        assert.NotEmpty(t, testServiceIpv4, "TEST_SERVICE_IPV4 is required in .env file for unit testing")
        assert.NotZero(t, testServicePort, "TEST_SERVICE_PORT is required in .env file for unit testing")
 
+       apiName := "apiName"
        newServiceDescription := getServiceAPIDescription(aefId, apiName, description, testServiceIpv4, testServicePort)
 
        // Attempt to publish a service for provider
-       result = testutil.NewRequest().Post("/published-apis/v1/"+apfId+"/service-apis").WithJsonBody(newServiceDescription).Go(t, requestHandler)
+       result = testutil.NewRequest().Post("/published-apis/v1/"+apfId+"/service-apis").WithJsonBody(newServiceDescription).Go(t, eServiceManager)
        assert.Equal(t, http.StatusForbidden, result.Code())
 
        // var resultError common29122.ProblemDetails
@@ -212,7 +280,7 @@ func TestRegisterValidProvider(t *testing.T) {
        newProvider := getProvider()
 
        // Register a valid provider
-       result := testutil.NewRequest().Post("/api-provider-management/v1/registrations").WithJsonBody(newProvider).Go(t, requestHandler)
+       result := testutil.NewRequest().Post("/api-provider-management/v1/registrations").WithJsonBody(newProvider).Go(t, eServiceManager)
        assert.Equal(t, http.StatusCreated, result.Code())
 
        var resultProvider provapi.APIProviderEnrolmentDetails
@@ -223,9 +291,8 @@ func TestRegisterValidProvider(t *testing.T) {
 func TestPublishUnpublishService(t *testing.T) {
        apfId := "APF_id_rApp_Kong_as_APF"
        apiName := "apiName"
-       newApiId := "api_id_" + apiName
 
-       myEnv, myPorts, err := envreader.ReadDotEnv()
+       myEnv, myPorts, err := mockConfigReader.ReadDotEnv()
        assert.Nil(t, err, "error reading env file")
 
        testServiceIpv4 := common29122.Ipv4Addr(myEnv["TEST_SERVICE_IPV4"])
@@ -235,7 +302,7 @@ func TestPublishUnpublishService(t *testing.T) {
        assert.NotZero(t, testServicePort, "TEST_SERVICE_PORT is required in .env file for unit testing")
 
        // Check no services published
-       result := testutil.NewRequest().Get("/published-apis/v1/"+apfId+"/service-apis").Go(t, requestHandler)
+       result := testutil.NewRequest().Get("/published-apis/v1/"+apfId+"/service-apis").Go(t, eServiceManager)
        assert.Equal(t, http.StatusOK, result.Code())
 
        // Parse JSON from the response body
@@ -256,7 +323,7 @@ func TestPublishUnpublishService(t *testing.T) {
        newServiceDescription := getServiceAPIDescriptionMissingInterface(aefId, apiName, description)
 
        // Publish a service for provider
-       result = testutil.NewRequest().Post("/published-apis/v1/"+apfId+"/service-apis").WithJsonBody(newServiceDescription).Go(t, requestHandler)
+       result = testutil.NewRequest().Post("/published-apis/v1/"+apfId+"/service-apis").WithJsonBody(newServiceDescription).Go(t, eServiceManager)
        assert.Equal(t, http.StatusBadRequest, result.Code())
 
        var resultError common29122.ProblemDetails
@@ -268,7 +335,7 @@ func TestPublishUnpublishService(t *testing.T) {
        newServiceDescription = getServiceAPIDescription(aefId, apiName, description, testServiceIpv4, testServicePort)
 
        // Publish a service for provider
-       result = testutil.NewRequest().Post("/published-apis/v1/"+apfId+"/service-apis").WithJsonBody(newServiceDescription).Go(t, requestHandler)
+       result = testutil.NewRequest().Post("/published-apis/v1/"+apfId+"/service-apis").WithJsonBody(newServiceDescription).Go(t, eServiceManager)
        assert.Equal(t, http.StatusCreated, result.Code())
 
        if result.Code() != http.StatusCreated {
@@ -279,12 +346,13 @@ func TestPublishUnpublishService(t *testing.T) {
        var resultService publishapi.ServiceAPIDescription
        err = result.UnmarshalJsonToObject(&resultService)
        assert.NoError(t, err, "error unmarshaling response")
+       newApiId := "api_id_" + apiName
        assert.Equal(t, newApiId, *resultService.ApiId)
 
        assert.Equal(t, "http://example.com/published-apis/v1/"+apfId+"/service-apis/"+*resultService.ApiId, result.Recorder.Header().Get(echo.HeaderLocation))
 
        // Check that the service is published for the provider
-       result = testutil.NewRequest().Get("/published-apis/v1/"+apfId+"/service-apis/"+newApiId).Go(t, requestHandler)
+       result = testutil.NewRequest().Get("/published-apis/v1/"+apfId+"/service-apis/"+newApiId).Go(t, eServiceManager)
        assert.Equal(t, http.StatusOK, result.Code())
 
        err = result.UnmarshalJsonToObject(&resultService)
@@ -297,18 +365,18 @@ func TestPublishUnpublishService(t *testing.T) {
        resultServiceIpv4 := *interfaceDescription.Ipv4Addr
        resultServicePort := *interfaceDescription.Port
 
-       kongIPv4 := common29122.Ipv4Addr(myEnv["KONG_IPV4"])
+       kongDataPlaneIPv4 := common29122.Ipv4Addr(myEnv["KONG_DATA_PLANE_IPV4"])
        kongDataPlanePort := common29122.Port(myPorts["KONG_DATA_PLANE_PORT"])
 
-       assert.NotEmpty(t, kongIPv4, "KONG_IPV4 is required in .env file for unit testing")
+       assert.NotEmpty(t, kongDataPlaneIPv4, "KONG_DATA_PLANE_IPV4 is required in .env file for unit testing")
        assert.NotZero(t, kongDataPlanePort, "KONG_DATA_PLANE_PORT is required in .env file for unit testing")
 
-       assert.Equal(t, kongIPv4, resultServiceIpv4)
+       assert.Equal(t, kongDataPlaneIPv4, resultServiceIpv4)
        assert.Equal(t, kongDataPlanePort, resultServicePort)
 
        // Publish the same service again should result in Forbidden
        newServiceDescription.ApiId = &newApiId
-       result = testutil.NewRequest().Post("/published-apis/v1/"+apfId+"/service-apis").WithJsonBody(newServiceDescription).Go(t, requestHandler)
+       result = testutil.NewRequest().Post("/published-apis/v1/"+apfId+"/service-apis").WithJsonBody(newServiceDescription).Go(t, eServiceManager)
        assert.Equal(t, http.StatusForbidden, result.Code())
 
        err = result.UnmarshalBodyToObject(&resultError)
@@ -317,11 +385,11 @@ func TestPublishUnpublishService(t *testing.T) {
        assert.Equal(t, http.StatusForbidden, *resultError.Status)
 
        // Delete the service
-       result = testutil.NewRequest().Delete("/published-apis/v1/"+apfId+"/service-apis/"+newApiId).Go(t, requestHandler)
+       result = testutil.NewRequest().Delete("/published-apis/v1/"+apfId+"/service-apis/"+newApiId).Go(t, eServiceManager)
        assert.Equal(t, http.StatusNoContent, result.Code())
 
        // Check no services published
-       result = testutil.NewRequest().Get("/published-apis/v1/"+apfId+"/service-apis").Go(t, requestHandler)
+       result = testutil.NewRequest().Get("/published-apis/v1/"+apfId+"/service-apis").Go(t, eServiceManager)
        assert.Equal(t, http.StatusOK, result.Code())
 
        // Parse JSON from the response body
@@ -330,26 +398,25 @@ func TestPublishUnpublishService(t *testing.T) {
 
        // Check if the parsed array is empty
        assert.Zero(t, len(resultServices))
-       teardown()
+       capifCleanUp()
 }
 
-func getEcho(myEnv map[string]string, myPorts map[string]int) (*echo.Echo, error) {
+func registerHandlers(e *echo.Echo, myEnv map[string]string, myPorts map[string]int) (err error) {
        capifProtocol := myEnv["CAPIF_PROTOCOL"]
        capifIPv4 := common29122.Ipv4Addr(myEnv["CAPIF_IPV4"])
        capifPort := common29122.Port(myPorts["CAPIF_PORT"])
        kongDomain := myEnv["KONG_DOMAIN"]
        kongProtocol := myEnv["KONG_PROTOCOL"]
-       kongIPv4 := common29122.Ipv4Addr(myEnv["KONG_IPV4"])
-       kongDataPlanePort := common29122.Port(myPorts["KONG_DATA_PLANE_PORT"])
+       kongControlPlaneIPv4 := common29122.Ipv4Addr(myEnv["KONG_CONTROL_PLANE_IPV4"])
        kongControlPlanePort := common29122.Port(myPorts["KONG_CONTROL_PLANE_PORT"])
-
-       e := echo.New()
+       kongDataPlaneIPv4 := common29122.Ipv4Addr(myEnv["KONG_DATA_PLANE_IPV4"])
+       kongDataPlanePort := common29122.Port(myPorts["KONG_DATA_PLANE_PORT"])
 
        // Register ProviderManagement
        providerManagerSwagger, err := provapi.GetSwagger()
        if err != nil {
                log.Fatalf("error loading ProviderManagement swagger spec\n: %s", err)
-               return nil, err
+               return err
        }
        providerManagerSwagger.Servers = nil
        providerManager := providermanagement.NewProviderManager(capifProtocol, capifIPv4, capifPort)
@@ -363,20 +430,23 @@ func getEcho(myEnv map[string]string, myPorts map[string]int) (*echo.Echo, error
        publishServiceSwagger, err := publishapi.GetSwagger()
        if err != nil {
                fmt.Fprintf(os.Stderr, "Error loading PublishService swagger spec\n: %s", err)
-               return nil, err
+               return err
        }
 
        publishServiceSwagger.Servers = nil
 
-       ps := NewPublishService(kongDomain, kongProtocol, kongIPv4, kongDataPlanePort, kongControlPlanePort, capifProtocol, capifIPv4, capifPort)
+       ps := NewPublishService(
+               kongDomain, kongProtocol,
+               kongControlPlaneIPv4, kongControlPlanePort,
+               kongDataPlaneIPv4, kongDataPlanePort,
+               capifProtocol, capifIPv4, capifPort)
 
        group = e.Group("/published-apis/v1")
        group.Use(echomiddleware.Logger())
        group.Use(middleware.OapiRequestValidator(publishServiceSwagger))
        publishapi.RegisterHandlersWithBaseURL(e, ps, "/published-apis/v1")
 
-       // return ps, eventChannel, e
-       return e, err
+       return err
 }
 
 func getServiceAPIDescription(aefId, apiName, description string, testServiceIpv4 common29122.Ipv4Addr, testServicePort common29122.Port) publishapi.ServiceAPIDescription {