Merge "NONRTRIC - Implement DMaaP mediator producer service in Java"
authorHenrik Andersson <henrik.b.andersson@est.tech>
Thu, 23 Sep 2021 14:43:52 +0000 (14:43 +0000)
committerGerrit Code Review <gerrit@o-ran-sc.org>
Thu, 23 Sep 2021 14:43:52 +0000 (14:43 +0000)
34 files changed:
.gitignore
dmaap-adaptor-java/Dockerfile
dmaap-adaptor-java/src/test/java/org/oran/dmaapadapter/ApplicationTest.java
dmaap-adaptor-java/src/test/java/org/oran/dmaapadapter/DmaapSimulatorController.java
dmaap-adaptor-java/src/test/java/org/oran/dmaapadapter/EcsSimulatorController.java
dmaap-adaptor-java/src/test/java/org/oran/dmaapadapter/IntegrationWithEcs.java
dmaap-mediator-producer/.gitignore
dmaap-mediator-producer/configs/STD_Fault_Messages.json [deleted file]
dmaap-mediator-producer/configs/type_config.json [new file with mode: 0644]
dmaap-mediator-producer/internal/config/config.go
dmaap-mediator-producer/internal/config/config_test.go
dmaap-mediator-producer/internal/config/registrator.go
dmaap-mediator-producer/internal/config/registrator_test.go
dmaap-mediator-producer/internal/jobs/jobs.go
dmaap-mediator-producer/internal/jobs/jobs_test.go
dmaap-mediator-producer/internal/restclient/HTTPClient.go
dmaap-mediator-producer/internal/server/server.go
dmaap-mediator-producer/internal/server/server_test.go
dmaap-mediator-producer/main.go
dmaap-mediator-producer/mocks/jobhandler/JobHandler.go [moved from dmaap-mediator-producer/mocks/JobHandler.go with 86% similarity]
dmaap-mediator-producer/simulator/consumersimulator.go [new file with mode: 0644]
test/auto-test/FTC1100.sh
test/auto-test/FTC150.sh
test/auto-test/FTC1800.sh
test/auto-test/FTC2002.sh [new file with mode: 0755]
test/auto-test/testdata/ecs/info-type-info.json [new file with mode: 0644]
test/common/controller_api_functions.sh
test/common/ecs_api_functions.sh
test/common/test_env-onap-honolulu.sh
test/common/test_env-onap-istanbul.sh
test/common/test_env-oran-d-release.sh
test/common/test_env-oran-e-release.sh
test/common/testcase_common.sh
test/simulator-group/policy_agent/application.yaml

index df309a1..5915080 100644 (file)
@@ -18,3 +18,5 @@ infer-out/
 
 .vscode
 .factorypath
+
+coverage.*
index 46dfba5..b2c0c30 100644 (file)
@@ -1,8 +1,8 @@
 #
 # ============LICENSE_START=======================================================
-# ONAP : ccsdk oran
+# O-RAN-SC
 # ================================================================================
-# Copyright (C) 2019-2020 Nordix Foundation. All rights reserved.
+# Copyright (C) 2021 Nordix Foundation. All rights reserved.
 # ================================================================================
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
@@ -40,4 +40,4 @@ ADD /config/truststore.jks /opt/app/dmaap-adaptor-service/etc/cert/truststore.jk
 RUN chmod -R 777 /opt/app/dmaap-adaptor-service/config/
 
 ADD target/${JAR} /opt/app/dmaap-adaptor-service/dmaap-adaptor.jar
-CMD ["java", "-jar", "/opt/app/policy-agent/dmaap-adaptor.jar"]
+CMD ["java", "-jar", "/opt/app/dmaap-adaptor-service/dmaap-adaptor.jar"]
index 2a82ff8..9dd7f8b 100644 (file)
@@ -23,8 +23,6 @@ package org.oran.dmaapadapter;
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.awaitility.Awaitility.await;
 
-import com.google.gson.Gson;
-import com.google.gson.GsonBuilder;
 import com.google.gson.JsonParser;
 
 import java.io.FileOutputStream;
@@ -49,8 +47,6 @@ import org.oran.dmaapadapter.repository.InfoType;
 import org.oran.dmaapadapter.repository.InfoTypes;
 import org.oran.dmaapadapter.repository.Jobs;
 import org.oran.dmaapadapter.tasks.ProducerRegstrationTask;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.boot.test.context.SpringBootTest;
 import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
@@ -72,7 +68,6 @@ import org.springframework.test.context.junit.jupiter.SpringExtension;
         "app.configuration-filepath=./src/test/resources/test_application_configuration.json"//
 })
 class ApplicationTest {
-    private static final Logger logger = LoggerFactory.getLogger(ApplicationTest.class);
 
     @Autowired
     private ApplicationConfig applicationConfig;
@@ -95,8 +90,6 @@ class ApplicationTest {
     @LocalServerPort
     int localServerHttpPort;
 
-    private static Gson gson = new GsonBuilder().create();
-
     static class TestApplicationConfig extends ApplicationConfig {
         @Override
         public String getEcsBaseUrl() {
index aa6220f..fbb600f 100644 (file)
@@ -64,6 +64,7 @@ public class DmaapSimulatorController {
             return ErrorResponse.create("", HttpStatus.NOT_FOUND);
         } else {
             String resp = dmaapResponses.remove(0);
+            logger.info("DMAAP simulator returned: {}", resp);
             return new ResponseEntity<>(resp, HttpStatus.OK);
         }
 
index 7d309cf..c042034 100644 (file)
@@ -102,6 +102,7 @@ public class EcsSimulatorController {
         ProducerJobInfo request =
                 new ProducerJobInfo(job.jobDefinition, "ID", job.infoTypeId, job.jobResultUri, job.owner, "TIMESTAMP");
         String body = gson.toJson(request);
+        logger.info("ECS Simulator PUT job: {}", body);
         restClient.post(url, body).block();
 
     }
index 3dde82e..9ca9413 100644 (file)
@@ -42,8 +42,6 @@ import org.oran.dmaapadapter.repository.InfoType;
 import org.oran.dmaapadapter.repository.InfoTypes;
 import org.oran.dmaapadapter.repository.Jobs;
 import org.oran.dmaapadapter.tasks.ProducerRegstrationTask;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.boot.test.context.SpringBootTest;
 import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
@@ -63,7 +61,6 @@ import org.springframework.test.context.junit.jupiter.SpringExtension;
         "app.ecs-base-url=https://localhost:8434" //
 })
 class IntegrationWithEcs {
-    private static final Logger logger = LoggerFactory.getLogger(ApplicationTest.class);
 
     @Autowired
     private ApplicationConfig applicationConfig;
index 0d08f66..9f5396c 100644 (file)
@@ -4,3 +4,4 @@ coverage.*
 main
 dmaapmediatorproducer
 __debug_bin*
+simulator
diff --git a/dmaap-mediator-producer/configs/STD_Fault_Messages.json b/dmaap-mediator-producer/configs/STD_Fault_Messages.json
deleted file mode 100644 (file)
index b944802..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-{
-  "$schema": "https://json-schema.org/draft/2019-09/schema",
-  "title": "STD_Fault_Messages",
-  "description": "Schema for job delivering fault messages from DMaaP Message Router",
-  "type": "object",
-  "properties": {}
-}
\ No newline at end of file
diff --git a/dmaap-mediator-producer/configs/type_config.json b/dmaap-mediator-producer/configs/type_config.json
new file mode 100644 (file)
index 0000000..983d0f3
--- /dev/null
@@ -0,0 +1,9 @@
+{
+  "types":
+    [
+      {
+        "id": "STD_Fault_Messages",
+        "dmaapTopicUrl": "events/unauthenticated.SEC_FAULT_OUTPUT/dmaapmediatorproducer/STD_Fault_Messages"
+      }
+  ]
+}
\ No newline at end of file
index 3616c58..9b7b1dd 100644 (file)
@@ -28,12 +28,12 @@ import (
 )
 
 type Config struct {
-       LogLevel                            string
-       InfoProducerSupervisionCallbackHost string
-       InfoProducerSupervisionCallbackPort int
-       InfoJobCallbackHost                 string
-       InfoJobCallbackPort                 int
-       InfoCoordinatorAddress              string
+       LogLevel               string
+       InfoProducerHost       string
+       InfoProducerPort       int
+       InfoCoordinatorAddress string
+       MRHost                 string
+       MRPort                 int
 }
 
 type ProducerRegistrationInfo struct {
@@ -44,12 +44,12 @@ type ProducerRegistrationInfo struct {
 
 func New() *Config {
        return &Config{
-               LogLevel:                            getEnv("LOG_LEVEL", "Info"),
-               InfoProducerSupervisionCallbackHost: getEnv("INFO_PRODUCER_SUPERVISION_CALLBACK_HOST", ""),
-               InfoProducerSupervisionCallbackPort: getEnvAsInt("INFO_PRODUCER_SUPERVISION_CALLBACK_PORT", 8085),
-               InfoJobCallbackHost:                 getEnv("INFO_JOB_CALLBACK_HOST", ""),
-               InfoJobCallbackPort:                 getEnvAsInt("INFO_JOB_CALLBACK_PORT", 8086),
-               InfoCoordinatorAddress:              getEnv("INFO_COORD_ADDR", "http://enrichmentservice:8083"),
+               LogLevel:               getEnv("LOG_LEVEL", "Info"),
+               InfoProducerHost:       getEnv("INFO_PRODUCER_HOST", ""),
+               InfoProducerPort:       getEnvAsInt("INFO_PRODUCER_PORT", 8085),
+               InfoCoordinatorAddress: getEnv("INFO_COORD_ADDR", "http://enrichmentservice:8083"),
+               MRHost:                 getEnv("MR_HOST", "http://message-router.onap"),
+               MRPort:                 getEnvAsInt("MR_PORT", 3904),
        }
 }
 
index 4a65dc0..0fcbdd3 100644 (file)
@@ -32,21 +32,21 @@ import (
 
 func TestNew_envVarsSetConfigContainSetValues(t *testing.T) {
        os.Setenv("LOG_LEVEL", "Debug")
-       os.Setenv("INFO_PRODUCER_SUPERVISION_CALLBACK_HOST", "supervisionCallbackHost")
-       os.Setenv("INFO_PRODUCER_SUPERVISION_CALLBACK_PORT", "8095")
-       os.Setenv("INFO_JOB_CALLBACK_HOST", "jobCallbackHost")
-       os.Setenv("INFO_JOB_CALLBACK_PORT", "8096")
+       os.Setenv("INFO_PRODUCER_HOST", "producerHost")
+       os.Setenv("INFO_PRODUCER_PORT", "8095")
        os.Setenv("INFO_COORD_ADDR", "infoCoordAddr")
+       os.Setenv("MR_HOST", "mrHost")
+       os.Setenv("MR_PORT", "3908")
        t.Cleanup(func() {
                os.Clearenv()
        })
        wantConfig := Config{
-               LogLevel:                            "Debug",
-               InfoProducerSupervisionCallbackHost: "supervisionCallbackHost",
-               InfoProducerSupervisionCallbackPort: 8095,
-               InfoJobCallbackHost:                 "jobCallbackHost",
-               InfoJobCallbackPort:                 8096,
-               InfoCoordinatorAddress:              "infoCoordAddr",
+               LogLevel:               "Debug",
+               InfoProducerHost:       "producerHost",
+               InfoProducerPort:       8095,
+               InfoCoordinatorAddress: "infoCoordAddr",
+               MRHost:                 "mrHost",
+               MRPort:                 3908,
        }
        if got := New(); !reflect.DeepEqual(got, &wantConfig) {
                t.Errorf("New() = %v, want %v", got, &wantConfig)
@@ -58,34 +58,34 @@ func TestNew_faultyIntValueSetConfigContainDefaultValueAndWarnInLog(t *testing.T
        var buf bytes.Buffer
        log.SetOutput(&buf)
 
-       os.Setenv("INFO_PRODUCER_SUPERVISION_CALLBACK_PORT", "wrong")
+       os.Setenv("INFO_PRODUCER_PORT", "wrong")
        t.Cleanup(func() {
                log.SetOutput(os.Stderr)
                os.Clearenv()
        })
        wantConfig := Config{
-               LogLevel:                            "Info",
-               InfoProducerSupervisionCallbackHost: "",
-               InfoProducerSupervisionCallbackPort: 8085,
-               InfoJobCallbackHost:                 "",
-               InfoJobCallbackPort:                 8086,
-               InfoCoordinatorAddress:              "http://enrichmentservice:8083",
+               LogLevel:               "Info",
+               InfoProducerHost:       "",
+               InfoProducerPort:       8085,
+               InfoCoordinatorAddress: "http://enrichmentservice:8083",
+               MRHost:                 "http://message-router.onap",
+               MRPort:                 3904,
        }
        if got := New(); !reflect.DeepEqual(got, &wantConfig) {
                t.Errorf("New() = %v, want %v", got, &wantConfig)
        }
        logString := buf.String()
-       assertions.Contains(logString, "Invalid int value: wrong for variable: INFO_PRODUCER_SUPERVISION_CALLBACK_PORT. Default value: 8085 will be used")
+       assertions.Contains(logString, "Invalid int value: wrong for variable: INFO_PRODUCER_PORT. Default value: 8085 will be used")
 }
 
 func TestNew_envVarsNotSetConfigContainDefaultValues(t *testing.T) {
        wantConfig := Config{
-               LogLevel:                            "Info",
-               InfoProducerSupervisionCallbackHost: "",
-               InfoProducerSupervisionCallbackPort: 8085,
-               InfoJobCallbackHost:                 "",
-               InfoJobCallbackPort:                 8086,
-               InfoCoordinatorAddress:              "http://enrichmentservice:8083",
+               LogLevel:               "Info",
+               InfoProducerHost:       "",
+               InfoProducerPort:       8085,
+               InfoCoordinatorAddress: "http://enrichmentservice:8083",
+               MRHost:                 "http://message-router.onap",
+               MRPort:                 3904,
        }
        if got := New(); !reflect.DeepEqual(got, &wantConfig) {
                t.Errorf("New() = %v, want %v", got, &wantConfig)
index 37225ed..db46c54 100644 (file)
@@ -33,9 +33,10 @@ import (
 
 const registerTypePath = "/data-producer/v1/info-types/"
 const registerProducerPath = "/data-producer/v1/info-producers/"
+const typeSchema = `{"type": "object","properties": {},"additionalProperties": false}`
 
 type Registrator interface {
-       RegisterTypes(types []*jobs.Type) error
+       RegisterTypes(types []*jobs.TypeData) error
        RegisterProducer(producerId string, producerInfo *ProducerRegistrationInfo)
 }
 
@@ -49,9 +50,9 @@ func NewRegistratorImpl(infoCoordAddr string) *RegistratorImpl {
        }
 }
 
-func (r RegistratorImpl) RegisterTypes(jobTypes []*jobs.Type) error {
+func (r RegistratorImpl) RegisterTypes(jobTypes []jobs.TypeData) error {
        for _, jobType := range jobTypes {
-               body := fmt.Sprintf(`{"info_job_data_schema": %v}`, jobType.Schema)
+               body := fmt.Sprintf(`{"info_job_data_schema": %v}`, typeSchema)
                if error := restclient.Put(r.infoCoordinatorAddress+registerTypePath+url.PathEscape(jobType.TypeId), []byte(body)); error != nil {
                        return error
                }
index a89c43f..353e9de 100644 (file)
@@ -43,11 +43,10 @@ func TestRegisterTypes(t *testing.T) {
 
        restclient.Client = &clientMock
 
-       type1 := jobs.Type{
+       type1 := jobs.TypeData{
                TypeId: "Type1",
-               Schema: `{"title": "Type 1"}`,
        }
-       types := []*jobs.Type{&type1}
+       types := []jobs.TypeData{type1}
 
        r := NewRegistratorImpl("http://localhost:9990")
        err := r.RegisterTypes(types)
@@ -64,7 +63,7 @@ func TestRegisterTypes(t *testing.T) {
        assertions.Equal("/data-producer/v1/info-types/Type1", actualRequest.URL.Path)
        assertions.Equal("application/json; charset=utf-8", actualRequest.Header.Get("Content-Type"))
        body, _ := ioutil.ReadAll(actualRequest.Body)
-       expectedBody := []byte(`{"info_job_data_schema": {"title": "Type 1"}}`)
+       expectedBody := []byte(`{"info_job_data_schema": {"type": "object","properties": {},"additionalProperties": false}}`)
        assertions.Equal(expectedBody, body)
        clientMock.AssertNumberOfCalls(t, "Do", 1)
 }
index 7347178..09d3891 100644 (file)
 package jobs
 
 import (
+       "encoding/json"
        "fmt"
        "os"
-       "path/filepath"
-       "strings"
+       "sync"
+
+       log "github.com/sirupsen/logrus"
+       "oransc.org/nonrtric/dmaapmediatorproducer/internal/restclient"
 )
 
-type Type struct {
-       TypeId string
-       Schema string
+type TypeDefinitions struct {
+       Types []TypeDefinition `json:"types"`
+}
+type TypeDefinition struct {
+       Id            string `json:"id"`
+       DmaapTopicURL string `json:"dmaapTopicUrl"`
+}
+
+type TypeData struct {
+       TypeId        string `json:"id"`
+       DMaaPTopicURL string `json:"dmaapTopicUrl"`
+       Jobs          map[string]JobInfo
 }
 
 type JobInfo struct {
-       Owner            string `json:"owner"`
-       LastUpdated      string `json:"last_updated"`
-       InfoJobIdentity  string `json:"info_job_identity"`
-       TargetUri        string `json:"target_uri"`
-       InfoJobData      string `json:"info_job_data"`
-       InfoTypeIdentity string `json:"info_type_identity"`
+       Owner            string      `json:"owner"`
+       LastUpdated      string      `json:"last_updated"`
+       InfoJobIdentity  string      `json:"info_job_identity"`
+       TargetUri        string      `json:"target_uri"`
+       InfoJobData      interface{} `json:"info_job_data"`
+       InfoTypeIdentity string      `json:"info_type_identity"`
 }
 
 type JobHandler interface {
@@ -46,9 +58,10 @@ type JobHandler interface {
 }
 
 var (
-       typeDir = "configs"
-       Handler JobHandler
-       allJobs = make(map[string]map[string]JobInfo)
+       mu         sync.Mutex
+       configFile = "configs/type_config.json"
+       Handler    JobHandler
+       allTypes   = make(map[string]TypeData)
 )
 
 func init() {
@@ -62,9 +75,12 @@ func newJobHandlerImpl() *jobHandlerImpl {
 }
 
 func (jh *jobHandlerImpl) AddJob(ji JobInfo) error {
+       mu.Lock()
+       defer mu.Unlock()
        if err := validateJobInfo(ji); err == nil {
-               jobs := allJobs[ji.InfoTypeIdentity]
+               jobs := allTypes[ji.InfoTypeIdentity].Jobs
                jobs[ji.InfoJobIdentity] = ji
+               log.Debug("Added job: ", ji)
                return nil
        } else {
                return err
@@ -72,7 +88,7 @@ func (jh *jobHandlerImpl) AddJob(ji JobInfo) error {
 }
 
 func validateJobInfo(ji JobInfo) error {
-       if _, ok := allJobs[ji.InfoTypeIdentity]; !ok {
+       if _, ok := allTypes[ji.InfoTypeIdentity]; !ok {
                return fmt.Errorf("type not supported: %v", ji.InfoTypeIdentity)
        }
        if ji.InfoJobIdentity == "" {
@@ -85,29 +101,38 @@ func validateJobInfo(ji JobInfo) error {
        return nil
 }
 
-func GetTypes() ([]*Type, error) {
-       types := make([]*Type, 0, 1)
-       err := filepath.Walk(typeDir,
-               func(path string, info os.FileInfo, err error) error {
-                       if err != nil {
-                               return err
-                       }
-                       if strings.Contains(path, ".json") {
-                               if jobType, err := getType(path); err == nil {
-                                       types = append(types, jobType)
-                               }
-                       }
-                       return nil
-               })
+func GetTypes() ([]TypeData, error) {
+       mu.Lock()
+       defer mu.Unlock()
+       types := make([]TypeData, 0, 1)
+       typeDefsByte, err := os.ReadFile(configFile)
+       if err != nil {
+               return nil, err
+       }
+       typeDefs := TypeDefinitions{}
+       err = json.Unmarshal(typeDefsByte, &typeDefs)
        if err != nil {
                return nil, err
        }
+       for _, typeDef := range typeDefs.Types {
+               typeInfo := TypeData{
+                       TypeId:        typeDef.Id,
+                       DMaaPTopicURL: typeDef.DmaapTopicURL,
+                       Jobs:          make(map[string]JobInfo),
+               }
+               if _, ok := allTypes[typeInfo.TypeId]; !ok {
+                       allTypes[typeInfo.TypeId] = typeInfo
+               }
+               types = append(types, typeInfo)
+       }
        return types, nil
 }
 
 func GetSupportedTypes() []string {
+       mu.Lock()
+       defer mu.Unlock()
        supportedTypes := []string{}
-       for k := range allJobs {
+       for k := range allTypes {
                supportedTypes = append(supportedTypes, k)
        }
        return supportedTypes
@@ -117,24 +142,41 @@ func AddJob(job JobInfo) error {
        return Handler.AddJob(job)
 }
 
-func getType(path string) (*Type, error) {
-       fileName := filepath.Base(path)
-       typeName := strings.TrimSuffix(fileName, filepath.Ext(fileName))
+func RunJobs(mRAddress string) {
+       for {
+               pollAndDistributeMessages(mRAddress)
+       }
+}
 
-       if typeSchema, err := os.ReadFile(path); err == nil {
-               typeInfo := Type{
-                       TypeId: typeName,
-                       Schema: string(typeSchema),
+func pollAndDistributeMessages(mRAddress string) {
+       for typeId, typeInfo := range allTypes {
+               log.Debugf("Processing jobs for type: %v", typeId)
+               messagesBody, error := restclient.Get(fmt.Sprintf("%v/%v", mRAddress, typeInfo.DMaaPTopicURL))
+               if error != nil {
+                       log.Warnf("Error getting data from MR. Cause: %v", error)
+                       continue
                }
-               if _, ok := allJobs[typeName]; !ok {
-                       allJobs[typeName] = make(map[string]JobInfo)
+               distributeMessages(messagesBody, typeInfo)
+       }
+}
+
+func distributeMessages(messages []byte, typeInfo TypeData) {
+       if len(messages) > 2 {
+               mu.Lock()
+               for _, jobInfo := range typeInfo.Jobs {
+                       go sendMessagesToConsumer(messages, jobInfo)
                }
-               return &typeInfo, nil
-       } else {
-               return nil, err
+               mu.Unlock()
+       }
+}
+
+func sendMessagesToConsumer(messages []byte, jobInfo JobInfo) {
+       log.Debugf("Processing job: %v", jobInfo.InfoJobIdentity)
+       if postErr := restclient.Post(jobInfo.TargetUri, messages); postErr != nil {
+               log.Warnf("Error posting data for job: %v. Cause: %v", jobInfo, postErr)
        }
 }
 
 func clearAll() {
-       allJobs = make(map[string]map[string]JobInfo)
+       allTypes = make(map[string]TypeData)
 }
index 0941033..3bb2578 100644 (file)
 package jobs
 
 import (
+       "bytes"
+       "io/ioutil"
+       "net/http"
        "os"
        "path/filepath"
+       "sync"
        "testing"
+       "time"
 
        "github.com/stretchr/testify/require"
+       "oransc.org/nonrtric/dmaapmediatorproducer/internal/restclient"
 )
 
-const type1Schema = `{"title": "Type 1"}`
+const typeDefinition = `{"types": [{"id": "type1", "dmaapTopicUrl": "events/unauthenticated.SEC_FAULT_OUTPUT/dmaapmediatorproducer/type1"}]}`
 
 func TestGetTypes_filesOkShouldReturnSliceOfTypesAndProvideSupportedTypes(t *testing.T) {
        assertions := require.New(t)
@@ -40,17 +46,18 @@ func TestGetTypes_filesOkShouldReturnSliceOfTypesAndProvideSupportedTypes(t *tes
                os.RemoveAll(typesDir)
                clearAll()
        })
-       typeDir = typesDir
-       fname := filepath.Join(typesDir, "type1.json")
-       if err = os.WriteFile(fname, []byte(type1Schema), 0666); err != nil {
-               t.Errorf("Unable to create temporary files for types due to: %v", err)
+       fname := filepath.Join(typesDir, "type_config.json")
+       configFile = fname
+       if err = os.WriteFile(fname, []byte(typeDefinition), 0666); err != nil {
+               t.Errorf("Unable to create temporary config file for types due to: %v", err)
        }
        types, err := GetTypes()
-       wantedType := Type{
-               TypeId: "type1",
-               Schema: type1Schema,
+       wantedType := TypeData{
+               TypeId:        "type1",
+               DMaaPTopicURL: "events/unauthenticated.SEC_FAULT_OUTPUT/dmaapmediatorproducer/type1",
+               Jobs:          make(map[string]JobInfo),
        }
-       wantedTypes := []*Type{&wantedType}
+       wantedTypes := []TypeData{wantedType}
        assertions.EqualValues(wantedTypes, types)
        assertions.Nil(err)
 
@@ -60,11 +67,7 @@ func TestGetTypes_filesOkShouldReturnSliceOfTypesAndProvideSupportedTypes(t *tes
 
 func TestAddJobWhenTypeIsSupported_shouldAddJobToAllJobsMap(t *testing.T) {
        assertions := require.New(t)
-       allJobs["type1"] = make(map[string]JobInfo)
-       t.Cleanup(func() {
-               clearAll()
-       })
-       jobInfo := JobInfo{
+       wantedJob := JobInfo{
                Owner:            "owner",
                LastUpdated:      "now",
                InfoJobIdentity:  "job1",
@@ -72,11 +75,18 @@ func TestAddJobWhenTypeIsSupported_shouldAddJobToAllJobsMap(t *testing.T) {
                InfoJobData:      "{}",
                InfoTypeIdentity: "type1",
        }
+       allTypes["type1"] = TypeData{
+               TypeId: "type1",
+               Jobs:   map[string]JobInfo{"job1": wantedJob},
+       }
+       t.Cleanup(func() {
+               clearAll()
+       })
 
-       err := AddJob(jobInfo)
+       err := AddJob(wantedJob)
        assertions.Nil(err)
-       assertions.Equal(1, len(allJobs["type1"]))
-       assertions.Equal(jobInfo, allJobs["type1"]["job1"])
+       assertions.Equal(1, len(allTypes["type1"].Jobs))
+       assertions.Equal(wantedJob, allTypes["type1"].Jobs["job1"])
 }
 
 func TestAddJobWhenTypeIsNotSupported_shouldReturnError(t *testing.T) {
@@ -92,7 +102,9 @@ func TestAddJobWhenTypeIsNotSupported_shouldReturnError(t *testing.T) {
 
 func TestAddJobWhenJobIdMissing_shouldReturnError(t *testing.T) {
        assertions := require.New(t)
-       allJobs["type1"] = make(map[string]JobInfo)
+       allTypes["type1"] = TypeData{
+               TypeId: "type1",
+       }
        t.Cleanup(func() {
                clearAll()
        })
@@ -102,12 +114,14 @@ func TestAddJobWhenJobIdMissing_shouldReturnError(t *testing.T) {
 
        err := AddJob(jobInfo)
        assertions.NotNil(err)
-       assertions.Equal("missing required job identity: {     type1}", err.Error())
+       assertions.Equal("missing required job identity: {    <nil> type1}", err.Error())
 }
 
 func TestAddJobWhenTargetUriMissing_shouldReturnError(t *testing.T) {
        assertions := require.New(t)
-       allJobs["type1"] = make(map[string]JobInfo)
+       allTypes["type1"] = TypeData{
+               TypeId: "type1",
+       }
        jobInfo := JobInfo{
                InfoTypeIdentity: "type1",
                InfoJobIdentity:  "job1",
@@ -115,6 +129,94 @@ func TestAddJobWhenTargetUriMissing_shouldReturnError(t *testing.T) {
 
        err := AddJob(jobInfo)
        assertions.NotNil(err)
-       assertions.Equal("missing required target URI: {  job1   type1}", err.Error())
+       assertions.Equal("missing required target URI: {  job1  <nil> type1}", err.Error())
        clearAll()
 }
+func TestPollAndDistributeMessages(t *testing.T) {
+       assertions := require.New(t)
+       jobInfo := JobInfo{
+               InfoTypeIdentity: "type1",
+               InfoJobIdentity:  "job1",
+               TargetUri:        "http://consumerHost/target",
+       }
+       allTypes["type1"] = TypeData{
+               TypeId:        "type1",
+               DMaaPTopicURL: "topicUrl",
+               Jobs:          map[string]JobInfo{"job1": jobInfo},
+       }
+       t.Cleanup(func() {
+               clearAll()
+       })
+
+       wg := sync.WaitGroup{}
+       wg.Add(2) // Two calls should be made to the server, one to poll and one to distribute
+       messages := `[{"message": {"data": "data"}}]`
+       clientMock := NewTestClient(func(req *http.Request) *http.Response {
+               if req.URL.String() == "http://mrAddr/topicUrl" {
+                       assertions.Equal(req.Method, "GET")
+                       wg.Done()
+                       return &http.Response{
+                               StatusCode: 200,
+                               Body:       ioutil.NopCloser(bytes.NewReader([]byte(messages))),
+                               Header:     make(http.Header), // Must be set to non-nil value or it panics
+                       }
+               } else if req.URL.String() == "http://consumerHost/target" {
+                       assertions.Equal(req.Method, "POST")
+                       assertions.Equal(messages, getBodyAsString(req))
+                       assertions.Equal("application/json; charset=utf-8", req.Header.Get("Content-Type"))
+                       wg.Done()
+                       return &http.Response{
+                               StatusCode: 200,
+                               Body:       ioutil.NopCloser(bytes.NewBufferString(`OK`)),
+                               Header:     make(http.Header), // Must be set to non-nil value or it panics
+                       }
+               }
+               t.Error("Wrong call to client: ", req)
+               t.Fail()
+               return nil
+       })
+
+       restclient.Client = clientMock
+
+       pollAndDistributeMessages("http://mrAddr")
+
+       if waitTimeout(&wg, 100*time.Millisecond) {
+               t.Error("Not all calls to server were made")
+               t.Fail()
+       }
+}
+
+type RoundTripFunc func(req *http.Request) *http.Response
+
+func (f RoundTripFunc) RoundTrip(req *http.Request) (*http.Response, error) {
+       return f(req), nil
+}
+
+//NewTestClient returns *http.Client with Transport replaced to avoid making real calls
+func NewTestClient(fn RoundTripFunc) *http.Client {
+       return &http.Client{
+               Transport: RoundTripFunc(fn),
+       }
+}
+
+// waitTimeout waits for the waitgroup for the specified max timeout.
+// Returns true if waiting timed out.
+func waitTimeout(wg *sync.WaitGroup, timeout time.Duration) bool {
+       c := make(chan struct{})
+       go func() {
+               defer close(c)
+               wg.Wait()
+       }()
+       select {
+       case <-c:
+               return false // completed normally
+       case <-time.After(timeout):
+               return true // timed out
+       }
+}
+
+func getBodyAsString(req *http.Request) string {
+       buf := new(bytes.Buffer)
+       buf.ReadFrom(req.Body)
+       return buf.String()
+}
index 78a02b6..a783f7e 100644 (file)
@@ -73,7 +73,15 @@ func Get(url string) ([]byte, error) {
 }
 
 func Put(url string, body []byte) error {
-       if req, reqErr := http.NewRequest(http.MethodPut, url, bytes.NewBuffer(body)); reqErr == nil {
+       return do(http.MethodPut, url, body)
+}
+
+func Post(url string, body []byte) error {
+       return do(http.MethodPost, url, body)
+}
+
+func do(method string, url string, body []byte) error {
+       if req, reqErr := http.NewRequest(method, url, bytes.NewBuffer(body)); reqErr == nil {
                req.Header.Set("Content-Type", "application/json; charset=utf-8")
                if response, respErr := Client.Do(req); respErr == nil {
                        if isResponseSuccess(response.StatusCode) {
index c3a1331..0b5e5b8 100644 (file)
@@ -29,8 +29,11 @@ import (
        "oransc.org/nonrtric/dmaapmediatorproducer/internal/jobs"
 )
 
+const StatusCallbackPath = "/status"
+const JobsCallbackPath = "/jobs"
+
 func StatusHandler(w http.ResponseWriter, r *http.Request) {
-       if r.URL.Path != "/" {
+       if r.URL.Path != StatusCallbackPath {
                http.Error(w, "404 not found.", http.StatusNotFound)
                return
        }
@@ -44,7 +47,7 @@ func StatusHandler(w http.ResponseWriter, r *http.Request) {
 }
 
 func CreateInfoJobHandler(w http.ResponseWriter, r *http.Request) {
-       if r.URL.Path != "/producer_simulator/info_job" {
+       if r.URL.Path != JobsCallbackPath {
                http.Error(w, "404 not found.", http.StatusNotFound)
                return
        }
@@ -68,14 +71,3 @@ func CreateInfoJobHandler(w http.ResponseWriter, r *http.Request) {
                http.Error(w, fmt.Sprintf("Invalid job info. Cause: %v", err), http.StatusBadRequest)
        }
 }
-
-func CreateServer(port int, handlerFunc func(http.ResponseWriter, *http.Request)) *http.Server {
-
-       mux := http.NewServeMux()
-       mux.HandleFunc("/", handlerFunc)
-       server := http.Server{
-               Addr:    fmt.Sprintf(":%v", port), // :{port}
-               Handler: mux,
-       }
-       return &server
-}
index d221c93..a4b19c4 100644 (file)
@@ -32,7 +32,7 @@ import (
 
        "github.com/stretchr/testify/require"
        "oransc.org/nonrtric/dmaapmediatorproducer/internal/jobs"
-       "oransc.org/nonrtric/dmaapmediatorproducer/mocks"
+       "oransc.org/nonrtric/dmaapmediatorproducer/mocks/jobhandler"
 )
 
 func TestStatusHandler(t *testing.T) {
@@ -51,7 +51,7 @@ func TestStatusHandler(t *testing.T) {
                        name: "StatusHandler with correct path and method, should return OK",
                        args: args{
                                responseRecorder: httptest.NewRecorder(),
-                               r:                newRequest("GET", "/", nil, t),
+                               r:                newRequest("GET", "/status", nil, t),
                        },
                        wantedStatus: http.StatusOK,
                        wantedBody:   "All is well!",
@@ -69,7 +69,7 @@ func TestStatusHandler(t *testing.T) {
                        name: "StatusHandler with incorrect method, should return MethodNotAllowed",
                        args: args{
                                responseRecorder: httptest.NewRecorder(),
-                               r:                newRequest("PUT", "/", nil, t),
+                               r:                newRequest("PUT", "/status", nil, t),
                        },
                        wantedStatus: http.StatusMethodNotAllowed,
                        wantedBody:   "Method is not supported.\n",
@@ -88,7 +88,7 @@ func TestStatusHandler(t *testing.T) {
 
 func TestCreateInfoJobHandler(t *testing.T) {
        assertions := require.New(t)
-       jobHandlerMock := mocks.JobHandler{}
+       jobHandlerMock := jobhandler.JobHandler{}
 
        goodJobInfo := jobs.JobInfo{
                Owner:            "owner",
@@ -119,7 +119,7 @@ func TestCreateInfoJobHandler(t *testing.T) {
                        name: "CreateInfoJobHandler with correct path and method, should return OK",
                        args: args{
                                responseRecorder: httptest.NewRecorder(),
-                               r:                newRequest("POST", "/producer_simulator/info_job", &goodJobInfo, t),
+                               r:                newRequest("POST", "/jobs", &goodJobInfo, t),
                        },
                        wantedStatus: http.StatusOK,
                        wantedBody:   "",
@@ -128,7 +128,7 @@ func TestCreateInfoJobHandler(t *testing.T) {
                        name: "CreateInfoJobHandler with incorrect job info, should return BadRequest",
                        args: args{
                                responseRecorder: httptest.NewRecorder(),
-                               r:                newRequest("POST", "/producer_simulator/info_job", &badJobInfo, t),
+                               r:                newRequest("POST", "/jobs", &badJobInfo, t),
                        },
                        wantedStatus: http.StatusBadRequest,
                        wantedBody:   "Invalid job info. Cause: error",
@@ -146,7 +146,7 @@ func TestCreateInfoJobHandler(t *testing.T) {
                        name: "CreateInfoJobHandler with incorrect method, should return MethodNotAllowed",
                        args: args{
                                responseRecorder: httptest.NewRecorder(),
-                               r:                newRequest("PUT", "/producer_simulator/info_job", nil, t),
+                               r:                newRequest("PUT", "/jobs", nil, t),
                        },
                        wantedStatus: http.StatusMethodNotAllowed,
                        wantedBody:   "Method is not supported.",
index 3fe92dc..79fcb6b 100644 (file)
@@ -22,6 +22,7 @@ package main
 
 import (
        "fmt"
+       "net/http"
        "sync"
 
        log "github.com/sirupsen/logrus"
@@ -31,8 +32,7 @@ import (
 )
 
 var configuration *config.Config
-var supervisionCallbackAddress string
-var jobInfoCallbackAddress string
+var callbackAddress string
 
 func init() {
        configuration = config.New()
@@ -43,15 +43,10 @@ func init() {
        }
 
        log.Debug("Initializing DMaaP Mediator Producer")
-       if configuration.InfoProducerSupervisionCallbackHost == "" {
+       if configuration.InfoProducerHost == "" {
                log.Fatal("Missing INFO_PRODUCER_SUPERVISION_CALLBACK_HOST")
        }
-       supervisionCallbackAddress = fmt.Sprintf("%v:%v", configuration.InfoProducerSupervisionCallbackHost, configuration.InfoProducerSupervisionCallbackPort)
-
-       if configuration.InfoJobCallbackHost == "" {
-               log.Fatal("Missing INFO_JOB_CALLBACK_HOST")
-       }
-       jobInfoCallbackAddress = fmt.Sprintf("%v:%v", configuration.InfoJobCallbackHost, configuration.InfoJobCallbackPort)
+       callbackAddress = fmt.Sprintf("%v:%v", configuration.InfoProducerHost, configuration.InfoProducerPort)
 
        registrator := config.NewRegistratorImpl(configuration.InfoCoordinatorAddress)
        if types, err := jobs.GetTypes(); err == nil {
@@ -62,9 +57,9 @@ func init() {
                log.Fatalf("Unable to get types to register due to: %v", err)
        }
        producer := config.ProducerRegistrationInfo{
-               InfoProducerSupervisionCallbackUrl: supervisionCallbackAddress,
+               InfoProducerSupervisionCallbackUrl: callbackAddress + server.StatusCallbackPath,
                SupportedInfoTypes:                 jobs.GetSupportedTypes(),
-               InfoJobCallbackUrl:                 jobInfoCallbackAddress,
+               InfoJobCallbackUrl:                 callbackAddress + server.JobsCallbackPath,
        }
        if err := registrator.RegisterProducer("DMaaP_Mediator_Producer", &producer); err != nil {
                log.Fatalf("Unable to register producer due to: %v", err)
@@ -75,19 +70,19 @@ func main() {
        log.Debug("Starting DMaaP Mediator Producer")
        wg := new(sync.WaitGroup)
 
-       // add two goroutines to `wg` WaitGroup, one for each avilable server
+       // add two goroutines to `wg` WaitGroup, one for each running go routine
        wg.Add(2)
 
-       log.Debugf("Starting status callback server at port %v", configuration.InfoProducerSupervisionCallbackPort)
+       log.Debugf("Starting callback server at port %v", configuration.InfoProducerPort)
        go func() {
-               server := server.CreateServer(configuration.InfoProducerSupervisionCallbackPort, server.StatusHandler)
-               log.Warn(server.ListenAndServe())
+               http.HandleFunc(server.StatusCallbackPath, server.StatusHandler)
+               http.HandleFunc(server.JobsCallbackPath, server.CreateInfoJobHandler)
+               log.Warn(http.ListenAndServe(fmt.Sprintf(":%v", configuration.InfoProducerPort), nil))
                wg.Done()
        }()
 
        go func() {
-               server := server.CreateServer(configuration.InfoJobCallbackPort, server.CreateInfoJobHandler)
-               log.Warn(server.ListenAndServe())
+               jobs.RunJobs(fmt.Sprintf("%v:%v", configuration.MRHost, configuration.MRPort))
                wg.Done()
        }()
 
@@ -1,10 +1,10 @@
 // Code generated by mockery v2.9.3. DO NOT EDIT.
 
-package mocks
+package jobhandler
 
 import (
        mock "github.com/stretchr/testify/mock"
-       jobs "oransc.org/nonrtric/dmaapmediatorproducer/internal/jobs"
+       "oransc.org/nonrtric/dmaapmediatorproducer/internal/jobs"
 )
 
 // JobHandler is an autogenerated mock type for the JobHandler type
diff --git a/dmaap-mediator-producer/simulator/consumersimulator.go b/dmaap-mediator-producer/simulator/consumersimulator.go
new file mode 100644 (file)
index 0000000..144f56f
--- /dev/null
@@ -0,0 +1,63 @@
+// -
+//   ========================LICENSE_START=================================
+//   O-RAN-SC
+//   %%
+//   Copyright (C) 2021: Nordix Foundation
+//   %%
+//   Licensed under the Apache License, Version 2.0 (the "License");
+//   you may not use this file except in compliance with the License.
+//   You may obtain a copy of the License at
+//
+//        http://www.apache.org/licenses/LICENSE-2.0
+//
+//   Unless required by applicable law or agreed to in writing, software
+//   distributed under the License is distributed on an "AS IS" BASIS,
+//   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//   See the License for the specific language governing permissions and
+//   limitations under the License.
+//   ========================LICENSE_END===================================
+//
+
+package main
+
+import (
+       "encoding/json"
+       "flag"
+       "fmt"
+       "io"
+       http "net/http"
+
+       "oransc.org/nonrtric/dmaapmediatorproducer/internal/restclient"
+)
+
+func main() {
+       port := flag.Int("port", 40935, "The port this consumer will listen on")
+       flag.Parse()
+       http.HandleFunc("/jobs", handleData)
+
+       fmt.Print("Starting consumer on port: ", *port)
+       http.ListenAndServe(fmt.Sprintf(":%v", *port), nil)
+       registerJob(*port)
+}
+
+func registerJob(port int) {
+       jobInfo := struct {
+               JobOwner      string `json:"job_owner"`
+               JobResultUri  string `json:"job_result_uri"`
+               InfoTypeId    string `json:"info_type_id"`
+               JobDefinition string `json:"job_definition"`
+       }{fmt.Sprintf("test%v", port), fmt.Sprintf("http://localhost:%v/jobs", port), "STD_Fault_Messages", "{}"}
+       fmt.Print("Registering consumer: ", jobInfo)
+       body, _ := json.Marshal(jobInfo)
+       putErr := restclient.Put(fmt.Sprintf("http://localhost:8083/data-consumer/v1/info-jobs/job%v", port), body)
+       if putErr != nil {
+               fmt.Printf("Unable to register consumer: %v", putErr)
+       }
+}
+
+func handleData(w http.ResponseWriter, req *http.Request) {
+       defer req.Body.Close()
+       if reqData, err := io.ReadAll(req.Body); err == nil {
+               fmt.Print("Consumer received body: ", string(reqData))
+       }
+}
index b6a2abb..eb687e8 100755 (executable)
@@ -331,9 +331,17 @@ else
     ecs_api_edp_delete_type_2 204 type1
     ecs_api_edp_get_type_2 404 type1
     ecs_api_edp_get_type_ids 200 EMPTY
-    ecs_api_edp_put_type_2 201 type1 testdata/ecs/ei-type-1.json
+    if [[ "$ECS_FEATURE_LEVEL" == *"INFO-TYPE-INFO"* ]]; then
+        ecs_api_edp_put_type_2 201 type1 testdata/ecs/ei-type-1.json testdata/ecs/info-type-info.json
+    else
+        ecs_api_edp_put_type_2 201 type1 testdata/ecs/ei-type-1.json
+    fi
     ecs_api_edp_get_type_ids 200 type1
-    ecs_api_edp_get_type_2 200 type1 testdata/ecs/ei-type-1.json
+    if [[ "$ECS_FEATURE_LEVEL" == *"INFO-TYPE-INFO"* ]]; then
+        ecs_api_edp_get_type_2 200 type1 testdata/ecs/ei-type-1.json testdata/ecs/info-type-info.json
+    else
+        ecs_api_edp_get_type_2 200 type1 testdata/ecs/ei-type-1.json
+    fi
 
     ecs_api_edp_put_producer_2 201 prod-a $CB_JOB/prod-a $CB_SV/prod-a type1
     ecs_api_edp_put_producer_2 200 prod-a $CB_JOB/prod-a $CB_SV/prod-a type1
@@ -359,7 +367,11 @@ ecs_api_edp_get_type_ids 200 type1
 if [ $ECS_VERSION == "V1-1" ]; then
     ecs_api_edp_get_type 200 type1 testdata/ecs/ei-type-1.json prod-a
 else
-    ecs_api_edp_get_type_2 200 type1 testdata/ecs/ei-type-1.json
+    if [[ "$ECS_FEATURE_LEVEL" == *"INFO-TYPE-INFO"* ]]; then
+        ecs_api_edp_get_type_2 200 type1 testdata/ecs/ei-type-1.json testdata/ecs/info-type-info.json
+    else
+        ecs_api_edp_get_type_2 200 type1 testdata/ecs/ei-type-1.json
+    fi
 fi
 
 if [ $ECS_VERSION == "V1-1" ]; then
@@ -513,7 +525,11 @@ if [ $ECS_VERSION == "V1-1" ]; then
     ecs_api_edp_get_type 200 type1 testdata/ecs/ei-type-1.json prod-a
     ecs_api_edp_get_type 200 type2 testdata/ecs/ei-type-2.json prod-b
 else
-    ecs_api_edp_get_type_2 200 type1 testdata/ecs/ei-type-1.json
+    if [[ "$ECS_FEATURE_LEVEL" == *"INFO-TYPE-INFO"* ]]; then
+        ecs_api_edp_get_type_2 200 type1 testdata/ecs/ei-type-1.json testdata/ecs/info-type-info.json
+    else
+        ecs_api_edp_get_type_2 200 type1 testdata/ecs/ei-type-1.json
+    fi
     ecs_api_edp_get_type_2 200 type2 testdata/ecs/ei-type-2.json
 fi
 
@@ -1950,6 +1966,30 @@ else
     cr_equal received_callbacks 12
 fi
 
+# Test job deletion at type delete
+
+if [[ "$ECS_FEATURE_LEVEL" == *"TYPE-SUBSCRIPTIONS"* ]]; then
+
+    ecs_api_edp_delete_type_2 406 type104
+
+    ecs_api_edp_delete_producer 204 prod-id
+
+    ecs_api_edp_delete_type_2 204 type104
+
+    cr_equal received_callbacks 32 30
+    cr_equal received_callbacks?id=info-job108-status 3
+    cr_equal received_callbacks?id=type-status1 19
+    cr_api_check_all_ecs_subscription_events 200 type-status1 type104 testdata/ecs/info-type-4.json DEREGISTERED
+    cr_api_check_all_ecs_events 200 info-job108-status DISABLED
+
+    ecs_api_edp_get_producer 404 prod-id
+
+    ecs_api_idc_get_job 404 job-108
+
+else
+    cr_equal received_callbacks 12
+fi
+
 check_ecs_logs
 
 store_logs END
index 1d80a8c..bcd41cb 100755 (executable)
@@ -103,14 +103,16 @@ for __nb_httpx in $NB_TESTED_PROTOCOLS ; do
         controller_api_get_A1_policy_type 404 OSC ricsim_g1_1 99
 
         RESP=202
-        if [ $FLAVOUR == "ONAP" ]; then
+        if [ $FLAVOUR == "ONAP" ] && [[ "$SDNC_FEATURE_LEVEL" != *"TRANS_RESP_CODE"* ]]; then
+            deviation "SDNC does not return original response code from sim"
             RESP=200
         fi
         controller_api_put_A1_policy $RESP OSC ricsim_g1_1 1 4000 testdata/OSC/pi1_template.json
         controller_api_put_A1_policy 404 OSC ricsim_g1_1 5 1001 testdata/OSC/pi1_template.json
 
         RESP=201
-        if [ $FLAVOUR == "ONAP" ]; then
+        if [ $FLAVOUR == "ONAP" ] && [[ "$SDNC_FEATURE_LEVEL" != *"TRANS_RESP_CODE"* ]]; then
+            deviation "SDNC does not return original response code from sim"
             RESP=200
         fi
         controller_api_put_A1_policy $RESP STD ricsim_g2_1   5000 testdata/STD/pi1_template.json
@@ -126,13 +128,15 @@ for __nb_httpx in $NB_TESTED_PROTOCOLS ; do
         controller_api_get_A1_policy_status 200 STD ricsim_g2_1 5000 "UNDEFINED"
 
         RESP=202
-        if [ $FLAVOUR == "ONAP" ]; then
+        if [ $FLAVOUR == "ONAP" ] && [[ "$SDNC_FEATURE_LEVEL" != *"TRANS_RESP_CODE"* ]]; then
+            deviation "SDNC does not return original response code from sim"
             RESP=200
         fi
         controller_api_delete_A1_policy $RESP OSC ricsim_g1_1 1 4000
 
         RESP=204
-        if [ $FLAVOUR == "ONAP" ]; then
+        if [ $FLAVOUR == "ONAP" ] && [[ "$SDNC_FEATURE_LEVEL" != *"TRANS_RESP_CODE"* ]]; then
+            deviation "SDNC does not return original response code from sim"
             RESP=200
         fi
         controller_api_delete_A1_policy $RESP STD ricsim_g2_1 5000
index 8ad142c..bb9ed60 100755 (executable)
@@ -218,6 +218,39 @@ else
         ecs_api_edp_put_type_2 201 type104 testdata/ecs/info-type-4.json
         ecs_api_edp_put_type_2 201 type105 testdata/ecs/info-type-5.json
 
+
+
+        if [[ "$ECS_FEATURE_LEVEL" == *"TYPE-SUBSCRIPTIONS"* ]]; then
+            cr_equal received_callbacks 20 30
+            cr_equal received_callbacks?id=type-status1 10
+            cr_equal received_callbacks?id=type-status2 10
+
+            cr_api_check_all_ecs_subscription_events 200 type-status1 \
+                type1 testdata/ecs/ei-type-1.json REGISTERED \
+                type2 testdata/ecs/ei-type-2.json REGISTERED \
+                type3 testdata/ecs/ei-type-3.json REGISTERED \
+                type4 testdata/ecs/ei-type-4.json REGISTERED \
+                type5 testdata/ecs/ei-type-5.json REGISTERED \
+                type101 testdata/ecs/info-type-1.json REGISTERED \
+                type102 testdata/ecs/info-type-2.json REGISTERED \
+                type103 testdata/ecs/info-type-3.json REGISTERED \
+                type104 testdata/ecs/info-type-4.json REGISTERED \
+                type105 testdata/ecs/info-type-5.json REGISTERED
+
+            cr_api_check_all_ecs_subscription_events 200 type-status2 \
+                type1 testdata/ecs/ei-type-1.json REGISTERED \
+                type2 testdata/ecs/ei-type-2.json REGISTERED \
+                type3 testdata/ecs/ei-type-3.json REGISTERED \
+                type4 testdata/ecs/ei-type-4.json REGISTERED \
+                type5 testdata/ecs/ei-type-5.json REGISTERED \
+                type101 testdata/ecs/info-type-1.json REGISTERED \
+                type102 testdata/ecs/info-type-2.json REGISTERED \
+                type103 testdata/ecs/info-type-3.json REGISTERED \
+                type104 testdata/ecs/info-type-4.json REGISTERED \
+                type105 testdata/ecs/info-type-5.json REGISTERED
+
+        fi
+
         ecs_api_edp_put_producer_2 200 prod-a $CB_JOB/prod-a $CB_SV/prod-a type1 type101
 
         ecs_api_edp_put_producer_2 200 prod-b $CB_JOB/prod-b $CB_SV/prod-b type1 type2 type101 type102
@@ -332,6 +365,22 @@ else
 
 fi
 
+
+if [[ "$ECS_FEATURE_LEVEL" == *"TYPE-SUBSCRIPTIONS"* ]]; then
+
+    ecs_equal json:/data-consumer/v1/info-type-subscription 2 200
+
+    ecs_api_idc_get_subscription_ids 200 owner1 subscription-id-1
+    ecs_api_idc_get_subscription_ids 200 owner2 subscription-id-2
+
+    if [ $use_info_jobs ]; then
+        ecs_equal json:data-producer/v1/info-types 10 1000
+    else
+        ecs_equal json:ei-producer/v1/eitypes 5 1000
+    fi
+
+fi
+
 stop_ecs
 
 cr_api_reset
@@ -340,28 +389,22 @@ start_stopped_ecs
 
 set_ecs_trace
 
-
 if [[ "$ECS_FEATURE_LEVEL" == *"TYPE-SUBSCRIPTIONS"* ]]; then
 
-    ecs_api_idc_get_subscription_ids 200 NOOWNER EMPTY
-    ecs_api_idc_get_subscription_ids 200 NOOWNER EMPTY
+    ecs_equal json:/data-consumer/v1/info-type-subscription 2 200
+
+    ecs_api_idc_get_subscription_ids 200 owner1 subscription-id-1
+    ecs_api_idc_get_subscription_ids 200 owner2 subscription-id-2
 
     if [ $use_info_jobs ]; then
         ecs_equal json:data-producer/v1/info-types 10 1000
     else
         ecs_equal json:ei-producer/v1/eitypes 5 1000
     fi
-
-    ecs_api_idc_put_subscription 201 subscription-id-1 owner1 $TYPESTATUS1
-
-    ecs_api_idc_get_subscription_ids 200 owner1 subscription-id-1
-
-    ecs_api_idc_put_subscription 201 subscription-id-2 owner2 $TYPESTATUS2
-
-    ecs_api_idc_get_subscription_ids 200 owner2 subscription-id-2
-
 fi
 
+cr_equal received_callbacks 0
+
 for ((i=1; i<=$NUM_JOBS; i++))
 do
     if [ $(($i%5)) -eq 0 ]; then
@@ -735,8 +778,35 @@ if [ $use_info_jobs ]; then
     ecs_equal json:data-consumer/v1/info-jobs?infoTypeId=type105 0
 fi
 
+if [ $use_info_jobs ]; then
+    if [[ "$ECS_FEATURE_LEVEL" == *"TYPE-SUBSCRIPTIONS"* ]]; then
+        ecs_api_edp_put_type_2 200 type101 testdata/ecs/info-type-1.json
+        ecs_api_edp_put_type_2 200 type102 testdata/ecs/info-type-2.json
+        ecs_api_edp_put_type_2 200 type103 testdata/ecs/info-type-3.json
+        ecs_api_edp_put_type_2 200 type104 testdata/ecs/info-type-4.json
+        ecs_api_edp_put_type_2 200 type105 testdata/ecs/info-type-5.json
+    fi
+fi
+
 if [[ "$ECS_FEATURE_LEVEL" == *"TYPE-SUBSCRIPTIONS"* ]]; then
-    cr_equal received_callbacks 0 30
+    cr_equal received_callbacks 10 30
+    cr_equal received_callbacks?id=type-status1 5
+    cr_equal received_callbacks?id=type-status2 5
+
+    cr_api_check_all_ecs_subscription_events 200 type-status1 \
+        type101 testdata/ecs/info-type-1.json REGISTERED \
+        type102 testdata/ecs/info-type-2.json REGISTERED \
+        type103 testdata/ecs/info-type-3.json REGISTERED \
+        type104 testdata/ecs/info-type-4.json REGISTERED \
+        type105 testdata/ecs/info-type-5.json REGISTERED
+
+    cr_api_check_all_ecs_subscription_events 200 type-status2 \
+        type101 testdata/ecs/info-type-1.json REGISTERED \
+        type102 testdata/ecs/info-type-2.json REGISTERED \
+        type103 testdata/ecs/info-type-3.json REGISTERED \
+        type104 testdata/ecs/info-type-4.json REGISTERED \
+        type105 testdata/ecs/info-type-5.json REGISTERED
+
 else
     cr_equal received_callbacks 0 30
 fi
diff --git a/test/auto-test/FTC2002.sh b/test/auto-test/FTC2002.sh
new file mode 100755 (executable)
index 0000000..753cc79
--- /dev/null
@@ -0,0 +1,164 @@
+#!/usr/bin/env bash
+
+#  ============LICENSE_START===============================================
+#  Copyright (C) 2020 Nordix Foundation. All rights reserved.
+#  ========================================================================
+#  Licensed under the Apache License, Version 2.0 (the "License");
+#  you may not use this file except in compliance with the License.
+#  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+#  Unless required by applicable law or agreed to in writing, software
+#  distributed under the License is distributed on an "AS IS" BASIS,
+#  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#  See the License for the specific language governing permissions and
+#  limitations under the License.
+#  ============LICENSE_END=================================================
+#
+
+TC_ONELINE_DESCR="Testing southbound proxy for SDNC - docker only"
+
+#App names to include in the test when running docker, space separated list
+DOCKER_INCLUDED_IMAGES="RICSIM SDNC HTTPPROXY"
+#App names to include in the test when running kubernetes, space separated list
+KUBE_INCLUDED_IMAGES=""
+#Prestarted app (not started by script) to include in the test when running kubernetes, space separated list
+KUBE_PRESTARTED_IMAGES=" "
+
+#Supported test environment profiles
+SUPPORTED_PROFILES="ONAP-ISTANBUL"
+#Supported run modes
+SUPPORTED_RUNMODES="DOCKER"
+
+. ../common/testcase_common.sh  $@
+. ../common/controller_api_functions.sh
+. ../common/ricsimulator_api_functions.sh
+. ../common/kube_proxy_api_functions.sh
+. ../common/http_proxy_api_functions.sh
+
+setup_testenvironment
+
+#### TEST BEGIN ####
+
+generate_policy_uuid
+
+#Test agent and simulator protocol versions (others are http only)
+NB_TESTED_PROTOCOLS="HTTP HTTPS"
+SB_TESTED_PROTOCOLS="HTTP HTTPS"
+
+for __nb_httpx in $NB_TESTED_PROTOCOLS ; do
+    for __sb_httpx in $SB_TESTED_PROTOCOLS ; do
+
+        echo "#####################################################################"
+        echo "#####################################################################"
+        echo "### Testing SDNC using Northbound: $__nb_httpx and Southbound: $__sb_httpx"
+        echo "#####################################################################"
+        echo "#####################################################################"
+
+        if [ $__sb_httpx == "HTTPS" ]; then
+            deviation "Southbound https proxy is currently not supported"
+            break
+        fi
+
+
+        # Clean container and start all needed containers #
+        clean_environment
+
+        start_http_proxy
+
+        start_ric_simulators ricsim_g1 1  OSC_2.1.0
+        start_ric_simulators ricsim_g2 1  STD_1.1.3
+        if [ "$PMS_VERSION" == "V2" ]; then
+            start_ric_simulators ricsim_g3 1  STD_2.0.0
+        fi
+
+        start_sdnc
+
+        if [ $__nb_httpx == "HTTPS" ]; then
+            # "Using secure ports towards SDNC"
+            use_sdnc_https
+        else
+            #"Using non-secure ports towards SDNC"
+            use_sdnc_http
+        fi
+
+        if [ $__sb_httpx == "HTTPS" ]; then
+            # "Using secure ports towards SDNC"
+            use_simulator_https
+            use_http_proxy_https
+        else
+            #"Using non-secure ports towards SDNC"
+            use_simulator_http
+            use_http_proxy_http
+        fi
+
+        echo -e $BOLD"Configure proxy in SDNC"$EBOLD
+        echo ""
+
+        if [ $__sb_httpx == "HTTPS" ]; then
+            echo "
+            sed  -i 's/a1Mediator.proxy.url=/a1Mediator.proxy.url=https:\/\/httpproxy:8433/g' /opt/onap/ccsdk/data/properties/a1-adapter-api-dg.properties
+            " | docker exec -i a1controller bash
+        else
+            echo "
+            sed  -i 's/a1Mediator.proxy.url=/a1Mediator.proxy.url=http:\/\/httpproxy:8080/g' /opt/onap/ccsdk/data/properties/a1-adapter-api-dg.properties
+            " | docker exec -i a1controller bash
+        fi
+
+        # Restart SDNC to use the updated config
+        stop_sdnc
+        start_stopped_sdnc
+
+        # API tests
+
+        controller_api_get_A1_policy_type 404 OSC ricsim_g1_1 1
+
+        sim_put_policy_type 201 ricsim_g1_1 1 testdata/OSC/sim_1.json
+
+
+        controller_api_get_A1_policy_ids 200 OSC ricsim_g1_1 1
+        controller_api_get_A1_policy_ids 200 STD ricsim_g2_1
+
+        controller_api_get_A1_policy_type 200 OSC ricsim_g1_1 1
+        controller_api_get_A1_policy_type 200 OSC ricsim_g1_1 1 testdata/OSC/sim_1.json
+        controller_api_get_A1_policy_type 404 OSC ricsim_g1_1 99
+
+        controller_api_put_A1_policy 202 OSC ricsim_g1_1 1 4000 testdata/OSC/pi1_template.json
+        controller_api_put_A1_policy 404 OSC ricsim_g1_1 5 1001 testdata/OSC/pi1_template.json
+
+        controller_api_put_A1_policy 201 STD ricsim_g2_1   5000 testdata/STD/pi1_template.json
+
+        controller_api_get_A1_policy_ids 200 OSC ricsim_g1_1 1 4000
+        controller_api_get_A1_policy_ids 200 STD ricsim_g2_1 5000
+
+        controller_api_get_A1_policy_status 200 OSC ricsim_g1_1 1 4000
+        controller_api_get_A1_policy_status 200 STD ricsim_g2_1 5000
+
+        VAL='NOT IN EFFECT'
+        controller_api_get_A1_policy_status 200 OSC ricsim_g1_1 1 4000 "$VAL" "false"
+        controller_api_get_A1_policy_status 200 STD ricsim_g2_1 5000 "UNDEFINED"
+
+
+        deviation "SDNC does not return original response code from sim"
+        controller_api_delete_A1_policy 202 OSC ricsim_g1_1 1 4000
+
+        deviation "SDNC does not return original response code from sim"
+        controller_api_delete_A1_policy 204 STD ricsim_g2_1 5000
+
+        sim_contains_str ricsim_g1_1 remote_hosts httpproxy.nonrtric-docker-net
+        sim_contains_str ricsim_g2_1 remote_hosts httpproxy.nonrtric-docker-net
+
+        check_sdnc_logs
+
+        store_logs          "NB_"$__nb_httpx"_SB_"$__sb_httpx
+
+    done
+
+done
+
+#### TEST COMPLETE ####
+
+print_result
+
+auto_clean_environment
\ No newline at end of file
diff --git a/test/auto-test/testdata/ecs/info-type-info.json b/test/auto-test/testdata/ecs/info-type-info.json
new file mode 100644 (file)
index 0000000..88814e7
--- /dev/null
@@ -0,0 +1,3 @@
+{
+    "hint": "periodic"
+}
\ No newline at end of file
index 3ed3933..d703d83 100644 (file)
@@ -272,6 +272,57 @@ start_sdnc() {
     return 0
 }
 
+
+# Stop the sndc
+# args: -
+# args: -
+# (Function for test scripts)
+stop_sdnc() {
+       echo -e $BOLD"Stopping $SDNC_DISPLAY_NAME"$EBOLD
+
+       if [ $RUNMODE == "KUBE" ]; then
+               __log_conf_fail_not_supported " Cannot stop sndc in KUBE mode"
+               return 1
+       else
+               docker stop $SDNC_APP_NAME &> ./tmp/.dockererr
+               if [ $? -ne 0 ]; then
+                       __print_err "Could not stop $SDNC_APP_NAME" $@
+                       cat ./tmp/.dockererr
+                       ((RES_CONF_FAIL++))
+                       return 1
+               fi
+       fi
+       echo -e $BOLD$GREEN"Stopped"$EGREEN$EBOLD
+       echo ""
+       return 0
+}
+
+# Start a previously stopped sdnc
+# args: -
+# (Function for test scripts)
+start_stopped_sdnc() {
+       echo -e $BOLD"Starting (the previously stopped) $SDNC_DISPLAY_NAME"$EBOLD
+
+       if [ $RUNMODE == "KUBE" ]; then
+               __log_conf_fail_not_supported " Cannot restart sndc in KUBE mode"
+               return 1
+       else
+               docker start $SDNC_APP_NAME &> ./tmp/.dockererr
+               if [ $? -ne 0 ]; then
+                       __print_err "Could not start (the stopped) $SDNC_APP_NAME" $@
+                       cat ./tmp/.dockererr
+                       ((RES_CONF_FAIL++))
+                       return 1
+               fi
+       fi
+       __check_service_start $SDNC_APP_NAME $SDNC_PATH$SDNC_ALIVE_URL
+       if [ $? -ne 0 ]; then
+               return 1
+       fi
+       echo ""
+       return 0
+}
+
 # Check the agent logs for WARNINGs and ERRORs
 # args: -
 # (Function for test scripts)
index 805fae4..9bde835 100644 (file)
@@ -1225,7 +1225,7 @@ ecs_api_edp_get_type() {
 
 # API Test function: GET /ei-producer/v1/eitypes/{eiTypeId}
 # API Test function: GET /data-producer/v1/info-types/{infoTypeId}
-# args: (v1_2) <response-code> <type-id> [<job-schema-file> ]
+# args: (v1_2) <response-code> <type-id> [<job-schema-file> [ <info-type-info> ]]
 # (Function for test scripts)
 ecs_api_edp_get_type_2() {
        __log_test_start $@
@@ -1237,8 +1237,13 @@ ecs_api_edp_get_type_2() {
        if [ $# -eq 3 ]; then
                paramError=0
        fi
+       if [[ "$ECS_FEATURE_LEVEL" == *"INFO-TYPE-INFO"* ]]; then
+               if [ $# -eq 4 ]; then
+                       paramError=0
+               fi
+       fi
     if [ $paramError -ne 0 ]; then
-               __print_err "<response-code> <type-id> [<job-schema-file> ]" $@
+               __print_err "<response-code> <type-id> [<job-schema-file> [ <info-type-info> ]]" $@
                return 1
        fi
        if [[ "$ECS_FEATURE_LEVEL" == *"INFO-TYPES"* ]]; then
@@ -1254,7 +1259,7 @@ ecs_api_edp_get_type_2() {
                __log_test_fail_status_code $1 $status
                return 1
        fi
-       if [ $# -eq 3 ]; then
+       if [ $# -ge 3 ]; then
                body=${res:0:${#res}-3}
 
                if [ -f $3 ]; then
@@ -1263,8 +1268,18 @@ ecs_api_edp_get_type_2() {
                        __log_test_fail_general "Job template file "$3", does not exist"
                        return 1
                fi
+               info_data=""
+               if [ $# -gt 3 ]; then
+                       if [ -f $4 ]; then
+                               info_data=$(cat $4)
+                       else
+                               __log_test_fail_general "Info-data file "$4", does not exist"
+                               return 1
+                       fi
+                       info_data=",\"info_type_information\":$info_data"
+               fi
                if [[ "$ECS_FEATURE_LEVEL" == *"INFO-TYPES"* ]]; then
-                       targetJson="{\"info_job_data_schema\":$schema}"
+                       targetJson="{\"info_job_data_schema\":$schema $info_data}"
                else
                        targetJson="{\"ei_job_data_schema\":$schema}"
                fi
@@ -1283,23 +1298,42 @@ ecs_api_edp_get_type_2() {
 
 # API Test function: PUT /ei-producer/v1/eitypes/{eiTypeId}
 # API Test function: PUT /data-producer/v1/info-types/{infoTypeId}
-# args: (v1_2) <response-code> <type-id> <job-schema-file>
+# args: (v1_2) <response-code> <type-id> <job-schema-file> [ <info-type-info> ]
 # (Function for test scripts)
 ecs_api_edp_put_type_2() {
        __log_test_start $@
 
-    if [ $# -ne 3 ]; then
-               __print_err "<response-code> <type-id> <job-schema-file>" $@
-               return 1
+       if [[ "$ECS_FEATURE_LEVEL" == *"INFO-TYPE-INFO"* ]]; then
+               if [ $# -lt 3 ] || [ $# -gt 4 ]; then
+                       __print_err "<response-code> <type-id> <job-schema-file> [ <info-type-info> ]" $@
+                       return 1
+               fi
+       else
+               if [ $# -ne 3 ]; then
+                       __print_err "<response-code> <type-id> <job-schema-file>" $@
+                       return 1
+               fi
        fi
 
        if [ ! -f $3 ]; then
                __log_test_fail_general "Job schema file "$3", does not exist"
                return 1
        fi
+
+       info_data=""
+       if [ $# -gt 3 ]; then
+               if [ -f $4 ]; then
+                       info_data=$(cat $4)
+               else
+                       __log_test_fail_general "Info-data file "$4", does not exist"
+                       return 1
+               fi
+               info_data=",\"info_type_information\":$info_data"
+       fi
+
        if [[ "$ECS_FEATURE_LEVEL" == *"INFO-TYPES"* ]]; then
                schema=$(cat $3)
-               input_json="{\"info_job_data_schema\":$schema}"
+               input_json="{\"info_job_data_schema\":$schema $info_data}"
                file="./tmp/put_type.json"
                echo $input_json > $file
 
index 0797912..54e6fbe 100755 (executable)
@@ -76,10 +76,10 @@ POLICY_AGENT_IMAGE_TAG_REMOTE_RELEASE="1.1.1"
 
 # SDNC A1 Controller remote image and tag
 SDNC_A1_CONTROLLER_IMAGE_BASE="onap/sdnc-image"
-SDNC_A1_CONTROLLER_IMAGE_TAG_LOCAL="2.1.3-SNAPSHOT" ###CHECK THIS
-SDNC_A1_CONTROLLER_IMAGE_TAG_REMOTE_SNAPSHOT="2.1.3-STAGING-latest"
-SDNC_A1_CONTROLLER_IMAGE_TAG_REMOTE="2.1.3-STAGING-latest"  #Will use snapshot repo
-SDNC_A1_CONTROLLER_IMAGE_TAG_REMOTE_RELEASE="2.1.2"
+SDNC_A1_CONTROLLER_IMAGE_TAG_LOCAL="2.1.7-SNAPSHOT" ###CHECK THIS
+SDNC_A1_CONTROLLER_IMAGE_TAG_REMOTE_SNAPSHOT="2.1.7-STAGING-latest"
+SDNC_A1_CONTROLLER_IMAGE_TAG_REMOTE="2.1.7-STAGING-latest"  #Will use snapshot repo
+SDNC_A1_CONTROLLER_IMAGE_TAG_REMOTE_RELEASE="2.1.6"
 
 #SDNC DB remote image and tag
 #The DB is part of SDNC so handled in the same way as SDNC
@@ -320,6 +320,7 @@ SDNC_KUBE_APP_FILE="app2.yaml"
 SDNC_KARAF_LOG="/opt/opendaylight/data/log/karaf.log"    # Path to karaf log
 #SDNC_RESPONSE_JSON_KEY="A1-ADAPTER-API:output"           # Key name for output json in replies from sdnc (for upgraded sdnc)
 SDNC_RESPONSE_JSON_KEY="output"                          # Key name for output json in replies from sdnc
+SDNC_FEATURE_LEVEL=""                                    # Space separated list of features
 
 RAPP_CAT_APP_NAME="rappcatalogueservice"                 # Name for the RAPP Catalogue
 RAPP_CAT_DISPLAY_NAME="RAPP Catalogue Service"
index a99ad9d..4982e19 100644 (file)
@@ -69,9 +69,9 @@ NEXUS_RELEASE_REPO_ONAP=$NEXUS_RELEASE_REPO
 
 # Policy Agent image and tags
 POLICY_AGENT_IMAGE_BASE="onap/ccsdk-oran-a1policymanagementservice"
-POLICY_AGENT_IMAGE_TAG_LOCAL="1.2.1-SNAPSHOT"
-POLICY_AGENT_IMAGE_TAG_REMOTE_SNAPSHOT="1.2.1-SNAPSHOT"
-POLICY_AGENT_IMAGE_TAG_REMOTE="1.2.1-STAGING-latest" #Will use snapshot repo
+POLICY_AGENT_IMAGE_TAG_LOCAL="1.2.2-SNAPSHOT"
+POLICY_AGENT_IMAGE_TAG_REMOTE_SNAPSHOT="1.2-SNAPSHOT"
+POLICY_AGENT_IMAGE_TAG_REMOTE="1.2.2-STAGING-latest" #Will use snapshot repo
 POLICY_AGENT_IMAGE_TAG_REMOTE_RELEASE="1.2.1"
 
 # SDNC A1 Controller remote image and tag
@@ -86,22 +86,25 @@ SDNC_A1_CONTROLLER_IMAGE_TAG_REMOTE_RELEASE="2.2.0"
 SDNC_DB_IMAGE_BASE="mariadb"
 SDNC_DB_IMAGE_TAG_REMOTE_PROXY="10.5"
 
-# ECS image and tag - uses cherry release
+# ECS image and tag - uses d release
 ECS_IMAGE_BASE="o-ran-sc/nonrtric-enrichment-coordinator-service"
-ECS_IMAGE_TAG_REMOTE_RELEASE_ORAN="1.0.1"
+ECS_IMAGE_TAG_REMOTE_RELEASE_ORAN="1.1.0"
 #Note: Update var ECS_FEATURE_LEVEL if image version is changed
 
-# Control Panel image and tag - uses cherry release
+# Control Panel image and tag - uses d release
 CONTROL_PANEL_IMAGE_BASE="o-ran-sc/nonrtric-controlpanel"
-CONTROL_PANEL_IMAGE_TAG_REMOTE_RELEASE_ORAN="2.1.1"
+CONTROL_PANEL_IMAGE_TAG_REMOTE_RELEASE_ORAN="2.2.0"
 
+# Gateway image and tags - uses d release
+NRT_GATEWAY_IMAGE_BASE="o-ran-sc/nonrtric-gateway"
+NRT_GATEWAY_IMAGE_TAG_REMOTE_RELEASE_ORAN="1.0.0"
 
-# RAPP Catalogue image and tags - uses cherry release
+# RAPP Catalogue image and tags - uses d release
 RAPP_CAT_IMAGE_BASE="o-ran-sc/nonrtric-r-app-catalogue"
 RAPP_CAT_IMAGE_TAG_REMOTE_RELEASE_ORAN="1.0.1"
 
 
-# Near RT RIC Simulator image and tags - uses cherry release
+# Near RT RIC Simulator image and tags - uses d release
 RIC_SIM_IMAGE_BASE="o-ran-sc/a1-simulator"
 RIC_SIM_IMAGE_TAG_REMOTE_RELEASE_ORAN="2.1.0"
 
@@ -165,7 +168,7 @@ KUBE_PROXY_IMAGE_TAG_LOCAL="latest"
 PROJECT_IMAGES_APP_NAMES="PA SDNC"
 
 # List of app short names which images pulled from ORAN
-ORAN_IMAGES_APP_NAMES="CP ECS RICSIM RC"
+ORAN_IMAGES_APP_NAMES="CP ECS RICSIM RC NGW"
 
 # List of app short names which images pulled from ONAP
 ONAP_IMAGES_APP_NAMES=""   # Not used
@@ -224,7 +227,7 @@ ECS_COMPOSE_DIR="ecs"                                    # Dir in simulator_grou
 ECS_CONFIG_MOUNT_PATH=/opt/app/enrichment-coordinator-service/config # Internal container path for configuration
 ECS_CONFIG_FILE=application.yaml                         # Config file name
 ECS_VERSION="V1-2"                                       # Version where the types are added in the producer registration
-ECS_FEATURE_LEVEL=""                                     # Space separated list of features
+ECS_FEATURE_LEVEL="INFO-TYPES"                           # Space separated list of features
 
 MR_DMAAP_APP_NAME="dmaap-mr"                             # Name for the Dmaap MR
 MR_STUB_APP_NAME="mr-stub"                               # Name of the MR stub
@@ -320,6 +323,8 @@ SDNC_KUBE_APP_FILE="app2.yaml"
 SDNC_KARAF_LOG="/opt/opendaylight/data/log/karaf.log"    # Path to karaf log
 #SDNC_RESPONSE_JSON_KEY="A1-ADAPTER-API:output"           # Key name for output json in replies from sdnc (for upgraded sdnc)
 SDNC_RESPONSE_JSON_KEY="output"                          # Key name for output json in replies from sdnc
+SDNC_FEATURE_LEVEL="TRANS_RESP_CODE"                     # Space separated list of features
+                                                         # TRANS_RESP_CODE: SDNC return southbound response code
 
 RAPP_CAT_APP_NAME="rappcatalogueservice"                 # Name for the RAPP Catalogue
 RAPP_CAT_DISPLAY_NAME="RAPP Catalogue Service"
@@ -343,6 +348,21 @@ CONTROL_PANEL_CONFIG_MOUNT_PATH=/maven                   # Container internal pa
 CONTROL_PANEL_CONFIG_FILE=application.properties         # Config file name
 CONTROL_PANEL_HOST_MNT_DIR="./mnt"                       # Mounted dir, relative to compose file, on the host
 
+NRT_GATEWAY_APP_NAME="nonrtricgateway"                   # Name of the Gateway container
+NRT_GATEWAY_DISPLAY_NAME="NonRT-RIC Gateway"
+NRT_GATEWAY_EXTERNAL_PORT=9090                           # Gateway container external port (host -> container)
+NRT_GATEWAY_INTERNAL_PORT=9090                           # Gateway container internal port (container -> container)
+NRT_GATEWAY_EXTERNAL_SECURE_PORT=9091                    # Gateway container external port (host -> container)
+NRT_GATEWAY_INTERNAL_SECURE_PORT=9091                    # Gateway container internal port (container -> container)
+NRT_GATEWAY_LOGPATH="/var/log/nonrtric-gateway/application.log" # Path the application log in the Gateway container
+NRT_GATEWAY_HOST_MNT_DIR="./mnt"                         # Mounted dir, relative to compose file, on the host
+NRT_GATEWAY_ALIVE_URL="/actuator/metrics"                # Base path for alive check
+NRT_GATEWAY_COMPOSE_DIR="ngw"                            # Dir in simulator_group for docker-compose
+NRT_GATEWAY_CONFIG_MOUNT_PATH=/opt/app/nonrtric-gateway/config  # Container internal path for config
+NRT_GATEWAY_CONFIG_FILE=application.yaml                 # Config file name
+NRT_GATEWAY_PKG_NAME="org.springframework.cloud.gateway" # Java base package name
+NRT_GATEWAY_ACTUATOR="/actuator/loggers/$NRT_GATEWAY_PKG_NAME" # Url for trace/debug
+
 HTTP_PROXY_APP_NAME="httpproxy"                          # Name of the Http Proxy container
 HTTP_PROXY_DISPLAY_NAME="Http Proxy"
 HTTP_PROXY_EXTERNAL_PORT=8740                            # Http Proxy container external port (host -> container)
index 399f362..385dafe 100755 (executable)
@@ -89,9 +89,9 @@ NRT_GATEWAY_IMAGE_TAG_REMOTE="1.0.0"
 NRT_GATEWAY_IMAGE_TAG_REMOTE_RELEASE="1.0.0"
 
 
-# SDNC A1 Controller image and tags - Note using ONAP image
+# SDNC A1 Controller image and tags - Note using Honolulu ONAP image
 SDNC_A1_CONTROLLER_IMAGE_BASE="onap/sdnc-image"
-SDNC_A1_CONTROLLER_IMAGE_TAG_REMOTE_RELEASE_ONAP="2.1.2"
+SDNC_A1_CONTROLLER_IMAGE_TAG_REMOTE_RELEASE_ONAP="2.1.6"
 #No local image for ONAP SDNC, remote release image always used
 
 # ORAN SDNC adapter kept as reference
@@ -364,6 +364,7 @@ SDNC_KUBE_APP_FILE="app2.yaml"
 SDNC_KARAF_LOG="/opt/opendaylight/data/log/karaf.log"    # Path to karaf log
 #SDNC_RESPONSE_JSON_KEY="A1-ADAPTER-API:output"           # Key name for output json in replies from sdnc (for upgraded sdnc)
 SDNC_RESPONSE_JSON_KEY="output"                          # Key name for output json in replies from sdnc
+SDNC_FEATURE_LEVEL=""                                    # Space separated list of features
 
 RAPP_CAT_APP_NAME="rappcatalogueservice"                 # Name for the RAPP Catalogue
 RAPP_CAT_DISPLAY_NAME="RAPP Catalogue"
index e468d03..0f6e977 100755 (executable)
@@ -89,9 +89,9 @@ NRT_GATEWAY_IMAGE_TAG_REMOTE="1.1.0"
 NRT_GATEWAY_IMAGE_TAG_REMOTE_RELEASE="1.1.0"
 
 
-# SDNC A1 Controller image and tags - Note using ONAP image
+# SDNC A1 Controller image and tags - Note using released honolulu ONAP image
 SDNC_A1_CONTROLLER_IMAGE_BASE="onap/sdnc-image"
-SDNC_A1_CONTROLLER_IMAGE_TAG_REMOTE_RELEASE_ONAP="2.1.2"
+SDNC_A1_CONTROLLER_IMAGE_TAG_REMOTE_RELEASE_ONAP="2.1.6"
 #No local image for ONAP SDNC, remote release image always used
 
 # ORAN SDNC adapter kept as reference
@@ -247,7 +247,7 @@ ECS_COMPOSE_DIR="ecs"                                    # Dir in simulator_grou
 ECS_CONFIG_MOUNT_PATH=/opt/app/enrichment-coordinator-service/config # Internal container path for configuration
 ECS_CONFIG_FILE=application.yaml                         # Config file name
 ECS_VERSION="V1-2"                                       # Version where the types are decoupled from the producer registration
-ECS_FEATURE_LEVEL="INFO-TYPES TYPE-SUBSCRIPTIONS"        # Space separated list of features
+ECS_FEATURE_LEVEL="INFO-TYPES TYPE-SUBSCRIPTIONS INFO-TYPE-INFO"  # Space separated list of features
 
 MR_DMAAP_APP_NAME="dmaap-mr"                             # Name for the Dmaap MR
 MR_STUB_APP_NAME="mr-stub"                               # Name of the MR stub
@@ -364,6 +364,7 @@ SDNC_KUBE_APP_FILE="app2.yaml"
 SDNC_KARAF_LOG="/opt/opendaylight/data/log/karaf.log"    # Path to karaf log
 #SDNC_RESPONSE_JSON_KEY="A1-ADAPTER-API:output"           # Key name for output json in replies from sdnc (for upgraded sdnc)
 SDNC_RESPONSE_JSON_KEY="output"                          # Key name for output json in replies from sdnc
+SDNC_FEATURE_LEVEL=""                                    # Space separated list of features
 
 RAPP_CAT_APP_NAME="rappcatalogueservice"                 # Name for the RAPP Catalogue
 RAPP_CAT_DISPLAY_NAME="RAPP Catalogue"
index 5f1b097..b63d4d1 100755 (executable)
@@ -310,6 +310,14 @@ __log_conf_fail_body() {
        __check_stop_at_error
 }
 
+# Function to log a configuration that is not supported
+__log_conf_fail_not_supported() {
+       echo -e $RED" FAIL, function not supported"$ERED$@
+       ((RES_CONF_FAIL++))
+       __print_current_stats
+       __check_stop_at_error
+}
+
 # Function to log a passed configuration setup
 __log_conf_ok() {
        if [ $# -gt 0 ]; then
index 5c5b08d..75e4200 100644 (file)
@@ -66,3 +66,4 @@ app:
     # The HTTP proxy (if configured) will only be used for accessing NearRT RIC:s
     http.proxy-host: $AGENT_HTTP_PROXY_CONFIG_HOST_NAME
     http.proxy-port: $AGENT_HTTP_PROXY_CONFIG_PORT
+    http.proxy-type: HTTP