t.Fail()
return nil
})
+
handlerUnderTest := NewJobHandlerImpl("", pollClientMock, distributeClientMock)
+
jobInfo := JobInfo{
InfoTypeIdentity: "type1",
InfoJobIdentity: "job1",
func TestNewRouter(t *testing.T) {
assertions := require.New(t)
+
r := NewRouter(nil)
statusRoute := r.Get("status")
assertions.NotNil(statusRoute)
supportedMethods, err := statusRoute.GetMethods()
assertions.Equal([]string{http.MethodGet}, supportedMethods)
assertions.Nil(err)
+ path, _ := statusRoute.GetPathTemplate()
+ assertions.Equal("/status", path)
addJobRoute := r.Get("add")
assertions.NotNil(addJobRoute)
supportedMethods, err = addJobRoute.GetMethods()
assertions.Equal([]string{http.MethodPost}, supportedMethods)
assertions.Nil(err)
+ path, _ = addJobRoute.GetPathTemplate()
+ assertions.Equal("/jobs", path)
deleteJobRoute := r.Get("delete")
assertions.NotNil(deleteJobRoute)
supportedMethods, err = deleteJobRoute.GetMethods()
assertions.Equal([]string{http.MethodDelete}, supportedMethods)
assertions.Nil(err)
+ path, _ = deleteJobRoute.GetPathTemplate()
+ assertions.Equal("/jobs/{infoJobId}", path)
notFoundHandler := r.NotFoundHandler
handler := http.HandlerFunc(notFoundHandler.ServeHTTP)
func TestStatusHandler(t *testing.T) {
assertions := require.New(t)
+
+ handler := http.HandlerFunc(statusHandler)
responseRecorder := httptest.NewRecorder()
r := newRequest(http.MethodGet, "/status", nil, t)
- handler := http.HandlerFunc(statusHandler)
+
handler.ServeHTTP(responseRecorder, r)
- assertions.Equal(http.StatusOK, responseRecorder.Code)
+ assertions.Equal(http.StatusOK, responseRecorder.Code)
assertions.Equal("", responseRecorder.Body.String())
}
wantedBody string
}{
{
- name: "AddInfoJobHandler with correct path and method, should return OK",
+ name: "AddInfoJobHandler with correct job, should return OK",
args: args{
job: jobs.JobInfo{
Owner: "owner",
t.Run(tt.name, func(t *testing.T) {
jobHandlerMock := jobhandler.JobHandler{}
jobHandlerMock.On("AddJob", tt.args.job).Return(tt.args.mockReturn)
+
callbackHandlerUnderTest := NewProducerCallbackHandler(&jobHandlerMock)
handler := http.HandlerFunc(callbackHandlerUnderTest.addInfoJobHandler)
func TestDeleteJob(t *testing.T) {
assertions := require.New(t)
jobHandlerMock := jobhandler.JobHandler{}
-
jobHandlerMock.On("DeleteJob", mock.Anything).Return(nil)
+
callbackHandlerUnderTest := NewProducerCallbackHandler(&jobHandlerMock)
responseRecorder := httptest.NewRecorder()
###
mysql -uroot -p$MYSQL_ROOT_PASSWORD -f < /docker-entrypoint-initdb.d/create-db.sql
-mysql -uroot -p$MYSQL_ROOT_PASSWORD --execute "CREATE USER 'policy'@'%' IDENTIFIED BY 'P01icY';"
-mysql -uroot -p$MYSQL_ROOT_PASSWORD --execute "GRANT ALL PRIVILEGES ON controlloop.* TO 'policy'@'%';"
\ No newline at end of file
+mysql -uroot -p$MYSQL_ROOT_PASSWORD --execute "CREATE USER 'policy_user'@'%' IDENTIFIED BY 'policy_user';"
+mysql -uroot -p$MYSQL_ROOT_PASSWORD --execute "GRANT ALL PRIVILEGES ON controlloop.* TO 'policy_user'@'%';"
\ No newline at end of file
"port": 6969,
"userName": "healthcheck",
"password": "zb!XztG34",
- "https": true,
+ "https": false,
"aaf": false
},
"pdpParameters": {
+++ /dev/null
-{
- "name": "ControlLoopRuntimeGroup",
- "supervisionScannerIntervalSec": 1000,
- "participantStateChangeIntervalSec": 1000,
- "participantClUpdateIntervalSec": 1000,
- "participantClStateChangeIntervalSec": 1000,
- "restServerParameters": {
- "host": "0.0.0.0",
- "port": 6969,
- "userName": "healthcheck",
- "password": "zb!XztG34",
- "https": true,
- "aaf": false
- },
- "participantParameters": {
- "heartBeatMs": 120000,
- "updateParameters": {
- "maxRetryCount": 1,
- "maxWaitMs": 30000
- },
- "stateChangeParameters": {
- "maxRetryCount": 1,
- "maxWaitMs": 30000
- }
- },
- "databaseProviderParameters": {
- "name": "PolicyProviderParameterGroup",
- "implementation": "org.onap.policy.models.provider.impl.DatabasePolicyModelsProviderImpl",
- "databaseDriver": "org.mariadb.jdbc.Driver",
- "databaseUrl": "jdbc:mariadb://localhost:3306/controlloop",
- "databaseUser": "policy",
- "databasePassword": "P01icY",
- "persistenceUnit": "CommissioningMariaDb"
- },
- "topicParameterGroup": {
- "topicSources": [
- {
- "topic": "POLICY-CLRUNTIME-PARTICIPANT",
- "servers": [
- "localhost"
- ],
- "topicCommInfrastructure": "dmaap",
- "fetchTimeout": 15000
- }
- ],
- "topicSinks": [
- {
- "topic": "POLICY-CLRUNTIME-PARTICIPANT",
- "servers": [
- "localhost"
- ],
- "topicCommInfrastructure": "dmaap"
- },
- {
- "topic": "POLICY-NOTIFICATION",
- "servers": [
- "localhost"
- ],
- "topicCommInfrastructure": "dmaap"
- }
- ]
- }
-}
'pap', '6969'
]
apex-pdp:
- image: registry.nordix.org/onap/policy-apex-pdp:2.6.0-SNAPSHOT
+ image: nexus3.onap.org:10001/onap/policy-apex-pdp:2.5.4
container_name: policy-apex-pdp
depends_on:
- mariadb
properties:
provider:
type: string
- requred: false
+ required: false
+ metadata:
+ common: true
+ description: Specifies the organization that provides the control loop element
participant_id:
type: onap.datatypes.ToscaConceptIdentifier
requred: true
+ metadata:
+ common: true
+ participantType:
+ type: onap.datatypes.ToscaConceptIdentifier
+ required: true
+ metadata:
+ common: true
+ description: The identity of the participant type that hosts this type of Control Loop Element
+ startPhase:
+ type: integer
+ required: false
+ constraints:
+ - greater_or_equal: 0
+ metadata:
+ common: true
+ description: A value indicating the start phase in which this control loop element will be started, the
+ first start phase is zero. Control Loop Elements are started in their start_phase order and stopped
+ in reverse start phase order. Control Loop Elements with the same start phase are started and
+ stopped simultaneously
+ uninitializedToPassiveTimeout:
+ type: integer
+ required: false
+ constraints:
+ - greater_or_equal: 0
+ default: 60
+ metadata:
+ common: true
+ description: The maximum time in seconds to wait for a state chage from uninitialized to passive
+ passiveToRunningTimeout:
+ type: integer
+ required: false
+ constraints:
+ - greater_or_equal: 0
+ default: 60
+ metadata:
+ common: true
+ description: The maximum time in seconds to wait for a state chage from passive to running
+ runningToPassiveTimeout:
+ type: integer
+ required: false
+ constraints:
+ - greater_or_equal: 0
+ default: 60
+ metadata:
+ common: true
+ description: The maximum time in seconds to wait for a state chage from running to passive
+ passiveToUninitializedTimeout:
+ type: integer
+ required: false
+ constraints:
+ - greater_or_equal: 0
+ default: 60
+ metadata:
+ common: true
+ description: The maximum time in seconds to wait for a state chage from passive to uninitialized
org.onap.policy.clamp.controlloop.ControlLoop:
version: 1.0.1
derived_from: tosca.nodetypes.Root
properties:
provider:
type: string
- requred: false
+ required: false
+ metadata:
+ common: true
+ description: Specifies the organization that provides the control loop element
elements:
type: list
required: true
+ metadata:
+ common: true
entry_schema:
type: onap.datatypes.ToscaConceptIdentifier
+ description: Specifies a list of control loop element definitions that make up this control loop definition
org.onap.policy.clamp.controlloop.PolicyControlLoopElement:
version: 1.0.1
derived_from: org.onap.policy.clamp.controlloop.ControlLoopElement
description: Control loop element for the Link Monitor
properties:
provider: Ericsson
- participantType: org.onap.policy.controlloop.PolicyControlLoopParticipant:2.3.1
- startPhase: 0
- policyType: onap.policies.controlloop.operational.common.Apex:1.0.0
- policyId: operational.apex.linkmonitor:1.0.0
- org.onap.domain.linkmonitor.LinkMonitorControlLoopDefinition:
+ participant_id:
+ name: org.onap.PM_Policy
+ version: 1.0.0
+ participantType:
+ name: org.onap.policy.controlloop.PolicyControlLoopParticipant
+ version: 2.3.1
+ policy_type_id:
+ name: onap.policies.controlloop.operational.common.Apex
+ version: 1.0.0
+ policy_id:
+ name: operational.apex.linkmonitor
+ version: 1.0.0
+ pdpGroup: defaultGroup
+ org.onap.domain.linkmonitor.LinkMonitorControlLoopDefinition0:
version: 1.2.3
type: org.onap.policy.clamp.controlloop.ControlLoop
type_version: 1.0.0
{
- "orderedState": "RUNNING",
+ "orderedState": "PASSIVE",
"controlLoopIdentifierList": [
{
"name": "LinkMonitorInstance0",
"name": "LinkMonitorInstance0",
"version": "1.0.1",
"definition": {
- "name": "org.onap.domain.linkmonitor.LinkMonitorControlLoopDefinition",
+ "name": "org.onap.domain.linkmonitor.LinkMonitorControlLoopDefinition0",
"version": "1.2.3"
},
"state": "UNINITIALISED",
"name": "org.onap.policy.controlloop.PolicyControlLoopParticipant",
"version": "2.3.1"
},
+ "participantId": {
+ "name": "org.onap.PM_Policy",
+ "version": "1.0.0"
+ },
"state": "UNINITIALISED",
"orderedState": "UNINITIALISED",
"description": "Link Monitor Policy Control Loop Element"
--- /dev/null
+#
+# ===========LICENSE_START====================================================
+# 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.
+# 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=====================================================
+#
+version: '2'
+networks:
+ default:
+ driver: bridge
+ name: nonrtric-docker-net
+services:
+ controlloop-runtime:
+ image: nexus3.onap.org:10001/onap/policy-clamp-cl-runtime:6.1.3
+ container_name: controlloop-runtime
+ hostname: controlloop-runtime
+ ports:
+ - "6969:6969"
+ expose:
+ - 6969
+ volumes:
+ - ./config/ks.jks:/opt/app/policy/clamp/etc/ssl/policy-keystore:ro
+ - ./wait_for_port.sh:/opt/app/policy/clamp/bin/wait_for_port.sh:ro
+ environment:
+ - TOPICSERVER=onap-dmaap
+ - MARIADB_HOST=mariadb
+ - MARIADB_PORT=3306
+ - KEYSTORE=/opt/app/policy/clamp/etc/ssl/policy-keystore
+ - KEYSTORE_PASSWD=Pol1cy_0nap
+ - RUNTIME_TOPICPARAMETERGROUP_TOPICSOURCES_0_TOPIC=POLICY-CLRUNTIME-PARTICIPANT
+ - RUNTIME_TOPICPARAMETERGROUP_TOPICSOURCES_0_SERVERS_0=onap-dmaap
+ - RUNTIME_TOPICPARAMETERGROUP_TOPICSOURCES_0_TOPICCOMMINFRASTRUCTURE=dmaap
+ - RUNTIME_TOPICPARAMETERGROUP_TOPICSOURCES_0_FETCHTIMEOUT=15000
+ - RUNTIME_TOPICPARAMETERGROUP_TOPICSOURCES_0_USEHTTPS=false
+ - RUNTIME_TOPICPARAMETERGROUP_TOPICSINKS_0_TOPIC=POLICY-CLRUNTIME-PARTICIPANT
+ - RUNTIME_TOPICPARAMETERGROUP_TOPICSINKS_0_SERVERS_0=onap-dmaap
+ - RUNTIME_TOPICPARAMETERGROUP_TOPICSINKS_0_TOPICCOMMINFRASTRUCTURE=dmaap
+ - RUNTIME_TOPICPARAMETERGROUP_TOPICSINKS_0_FETCHTIMEOUT=15000
+ - RUNTIME_TOPICPARAMETERGROUP_TOPICSINKS_0_USEHTTPS=false
+ entrypoint: /opt/app/policy/clamp/bin/wait_for_port.sh
+ command: [
+ '-c', '/opt/app/policy/clamp/bin/controlloop-runtime.sh',
+ 'mariadb', '3306',
+ 'onap-dmaap', '3904'
+ ]
+ policy-participant:
+ image: nexus3.onap.org:10001/onap/policy-clamp-cl-pf-ppnt:6.1.3
+ container_name: policy-participant
+ depends_on:
+ - controlloop-runtime
+ hostname: policy-participant
+ volumes:
+ - ./config/ks.jks:/opt/app/policy/clamp/etc/ssl/policy-keystore:ro
+ - ./wait_for_port.sh:/opt/app/policy/clamp/bin/wait_for_port.sh:ro
+ environment:
+ - TOPICSERVER=onap-dmaap
+ - KEYSTORE=/opt/app/policy/clamp/etc/ssl/policy-keystore
+ - KEYSTORE_PASSWD=Pol1cy_0nap
+ - PARTICIPANT_INTERMEDIARYPARAMETERS_CLAMPCONTROLLOOPTOPICS_TOPICSOURCES_0_TOPIC=POLICY-CLRUNTIME-PARTICIPANT
+ - PARTICIPANT_INTERMEDIARYPARAMETERS_CLAMPCONTROLLOOPTOPICS_TOPICSOURCES_0_SERVERS_0=onap-dmaap
+ - PARTICIPANT_INTERMEDIARYPARAMETERS_CLAMPCONTROLLOOPTOPICS_TOPICSOURCES_0_TOPICCOMMINFRASTRUCTURE=dmaap
+ - PARTICIPANT_INTERMEDIARYPARAMETERS_CLAMPCONTROLLOOPTOPICS_TOPICSOURCES_0_FETCHTIMEOUT=15000
+ - PARTICIPANT_INTERMEDIARYPARAMETERS_CLAMPCONTROLLOOPTOPICS_TOPICSOURCES_0_USEHTTPS=false
+ - PARTICIPANT_INTERMEDIARYPARAMETERS_CLAMPCONTROLLOOPTOPICS_TOPICSINKS_0_TOPIC=POLICY-CLRUNTIME-PARTICIPANT
+ - PARTICIPANT_INTERMEDIARYPARAMETERS_CLAMPCONTROLLOOPTOPICS_TOPICSINKS_0_SERVERS_0=onap-dmaap
+ - PARTICIPANT_INTERMEDIARYPARAMETERS_CLAMPCONTROLLOOPTOPICS_TOPICSINKS_0_TOPICCOMMINFRASTRUCTURE=dmaap
+ - PARTICIPANT_INTERMEDIARYPARAMETERS_CLAMPCONTROLLOOPTOPICS_TOPICSINKS_0_FETCHTIMEOUT=15000
+ - PARTICIPANT_INTERMEDIARYPARAMETERS_CLAMPCONTROLLOOPTOPICS_TOPICSINKS_0_USEHTTPS=false
+ entrypoint: /opt/app/policy/clamp/bin/wait_for_port.sh
+ command: [
+ '-c', '/opt/app/policy/clamp/bin/policy-participant.sh',
+ 'controlloop-runtime', '6969'
+ ]
\ No newline at end of file
--- /dev/null
+#!/bin/sh
+# ============LICENSE_START====================================================
+# Copyright (C) 2021 AT&T Intellectual Property. 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.
+#
+# SPDX-License-Identifier: Apache-2.0
+# ============LICENSE_END======================================================
+
+tmout=120
+cmd=
+while getopts c:t: opt; do
+ case "$opt" in
+ c) cmd="$OPTARG" ;;
+ t) tmout="$OPTARG" ;;
+ esac
+done
+nargs=$(expr $OPTIND - 1)
+shift $nargs
+
+even_args=$(expr $# % 2)
+if [ $# -lt 2 -o $even_args -ne 0 ]; then
+ echo "args: [-t timeout] [-c command] hostname1 port1 hostname2 port2 ..." >&2
+ exit 1
+fi
+
+while [ $# -ge 2 ]; do
+ export host=$1
+ export port=$2
+ shift
+ shift
+
+ echo "Waiting for $host port $port..."
+ timeout $tmout sh -c 'until nc -vz "$host" "$port"; do echo -n ".";
+ sleep 1; done'
+ rc=$?
+
+ if [ $rc != 0 ]; then
+ echo "$host port $port cannot be reached"
+ exit $rc
+ fi
+done
+
+$cmd
+
+exit 0
.history
oruclosedloop
+simulator
)
type Configuration struct {
- InfoCoordAddress string
- SDNRAddress string
- SDNRUser string
- SDNRPassword string
+ SDNRAddress string
+ SDNRUser string
+ SDNRPassword string
}
const rawSdnrPath = "/rests/data/network-topology:network-topology/topology=topology-netconf/node=[O-DU-ID]/yang-ext:mount/o-ran-sc-du-hello-world:network-function/du-to-ru-connection=[O-RU-ID]"
Body []byte
}
+func (e RequestError) Error() string {
+ return fmt.Sprintf("Request failed due to error response with status: %v and body: %v", e.StatusCode, string(e.Body))
+}
+
// HTTPClient interface
type HTTPClient interface {
Get(url string) (*http.Response, error)
Do(*http.Request) (*http.Response, error)
}
-func (pe RequestError) Error() string {
- return fmt.Sprintf("Request failed due to error response with status: %v and body: %v", pe.StatusCode, string(pe.Body))
-}
-
func PutWithoutAuth(url string, body []byte, client HTTPClient) error {
return do(http.MethodPut, url, body, client)
}
url: "badRequest",
mockReturnStatus: http.StatusBadRequest,
mockReturnBody: []byte("bad request"),
- mockReturnError: nil,
},
wantErr: RequestError{
StatusCode: http.StatusBadRequest,
"encoding/json"
"fmt"
"net/http"
+ "os"
+ "os/signal"
+ "syscall"
"time"
"github.com/gorilla/mux"
"oransc.org/usecase/oruclosedloop/internal/restclient"
)
+type Server interface {
+ ListenAndServe() error
+}
+
const timeoutHTTPClient = time.Second * 5
const jobId = "14e7bb84-a44d-44c1-90b7-6995a92ad43c"
-var infoCoordAddress string
+var jobRegistrationInfo = struct {
+ InfoTypeId string `json:"info_type_id"`
+ JobResultUri string `json:"job_result_uri"`
+ JobOwner string `json:"job_owner"`
+ JobDefinition interface{} `json:"job_definition"`
+}{
+ InfoTypeId: "STD_Fault_Messages",
+ JobResultUri: "",
+ JobOwner: "O-RU Closed Loop Usecase",
+ JobDefinition: "{}",
+}
+
+var client restclient.HTTPClient
+var configuration *config.Config
var linkfailureConfig linkfailure.Configuration
var lookupService repository.LookupService
-var host string
-var port string
-var client restclient.HTTPClient
+var consumerPort string
func init() {
- configuration := config.New()
+ doInit()
+}
+
+func doInit() {
+ configuration = config.New()
+
+ log.SetLevel(configuration.LogLevel)
client = &http.Client{
Timeout: timeoutHTTPClient,
}
- log.SetLevel(configuration.LogLevel)
+ consumerPort = fmt.Sprint(configuration.ConsumerPort)
+ jobRegistrationInfo.JobResultUri = configuration.ConsumerHost + ":" + consumerPort
+
+ linkfailureConfig = linkfailure.Configuration{
+ SDNRAddress: configuration.SDNRHost + ":" + fmt.Sprint(configuration.SDNRPort),
+ SDNRUser: configuration.SDNRUser,
+ SDNRPassword: configuration.SDNPassword,
+ }
+}
+func main() {
if err := validateConfiguration(configuration); err != nil {
- log.Fatalf("Unable to start consumer due to: %v", err)
+ log.Fatalf("Unable to start consumer due to configuration error: %v", err)
}
- host = configuration.ConsumerHost
- port = fmt.Sprint(configuration.ConsumerPort)
csvFileHelper := repository.NewCsvFileHelperImpl()
- if initErr := initializeLookupService(csvFileHelper, configuration); initErr != nil {
+ if initErr := initializeLookupService(csvFileHelper, configuration.ORUToODUMapFile); initErr != nil {
log.Fatalf("Unable to create LookupService due to inability to get O-RU-ID to O-DU-ID map. Cause: %v", initErr)
}
- infoCoordAddress = configuration.InfoCoordinatorAddress
+ go func() {
+ startServer(&http.Server{
+ Addr: ":" + consumerPort,
+ Handler: getRouter(),
+ })
+ os.Exit(1) // If the startServer function exits, it is because there has been a failure in the server, so we exit.
+ }()
- linkfailureConfig = linkfailure.Configuration{
- SDNRAddress: configuration.SDNRHost + ":" + fmt.Sprint(configuration.SDNRPort),
- SDNRUser: configuration.SDNRUser,
- SDNRPassword: configuration.SDNPassword,
- }
+ go func() {
+ deleteOnShutdown(make(chan os.Signal, 1))
+ os.Exit(0)
+ }()
+
+ keepConsumerAlive()
}
func validateConfiguration(configuration *config.Config) error {
return nil
}
-func initializeLookupService(csvFileHelper repository.CsvFileHelper, configuration *config.Config) error {
- lookupService = repository.NewLookupServiceImpl(csvFileHelper, configuration.ORUToODUMapFile)
- if initErr := lookupService.Init(); initErr != nil {
- return initErr
- }
- return nil
+func initializeLookupService(csvFileHelper repository.CsvFileHelper, csvFile string) error {
+ lookupService = repository.NewLookupServiceImpl(csvFileHelper, csvFile)
+ return lookupService.Init()
}
-func main() {
- defer deleteJob()
+func getRouter() *mux.Router {
messageHandler := linkfailure.NewLinkFailureHandler(lookupService, linkfailureConfig, client)
+
r := mux.NewRouter()
- r.HandleFunc("/", messageHandler.MessagesHandler).Methods(http.MethodPost)
- r.HandleFunc("/admin/start", startHandler).Methods(http.MethodPost)
- r.HandleFunc("/admin/stop", stopHandler).Methods(http.MethodPost)
- log.Error(http.ListenAndServe(":"+port, r))
+ r.HandleFunc("/", messageHandler.MessagesHandler).Methods(http.MethodPost).Name("messageHandler")
+ r.HandleFunc("/admin/start", startHandler).Methods(http.MethodPost).Name("start")
+ r.HandleFunc("/admin/stop", stopHandler).Methods(http.MethodPost).Name("stop")
+
+ return r
}
-func startHandler(w http.ResponseWriter, r *http.Request) {
- jobRegistrationInfo := struct {
- InfoTypeId string `json:"info_type_id"`
- JobResultUri string `json:"job_result_uri"`
- JobOwner string `json:"job_owner"`
- JobDefinition interface{} `json:"job_definition"`
- }{
- InfoTypeId: "STD_Fault_Messages",
- JobResultUri: host + ":" + port,
- JobOwner: "O-RU Closed Loop Usecase",
- JobDefinition: "{}",
+func startServer(server Server) {
+ if err := server.ListenAndServe(); err != nil {
+ log.Errorf("Server stopped unintentionally due to: %v. Deleteing job.", err)
+ if deleteErr := deleteJob(); deleteErr != nil {
+ log.Error(fmt.Sprintf("Unable to delete consumer job due to: %v. Please remove job %v manually.", deleteErr, jobId))
+ }
}
+}
+
+func keepConsumerAlive() {
+ forever := make(chan int)
+ <-forever
+}
+
+func startHandler(w http.ResponseWriter, r *http.Request) {
body, _ := json.Marshal(jobRegistrationInfo)
- putErr := restclient.PutWithoutAuth(infoCoordAddress+"/data-consumer/v1/info-jobs/"+jobId, body, client)
+ putErr := restclient.PutWithoutAuth(configuration.InfoCoordinatorAddress+"/data-consumer/v1/info-jobs/"+jobId, body, client)
if putErr != nil {
- http.Error(w, fmt.Sprintf("Unable to register consumer job: %v", putErr), http.StatusBadRequest)
+ http.Error(w, fmt.Sprintf("Unable to register consumer job due to: %v.", putErr), http.StatusBadRequest)
return
}
log.Debug("Registered job.")
func stopHandler(w http.ResponseWriter, r *http.Request) {
deleteErr := deleteJob()
if deleteErr != nil {
- http.Error(w, fmt.Sprintf("Unable to delete consumer job: %v", deleteErr), http.StatusBadRequest)
+ http.Error(w, fmt.Sprintf("Unable to delete consumer job due to: %v. Please remove job %v manually.", deleteErr, jobId), http.StatusBadRequest)
return
}
log.Debug("Deleted job.")
}
+func deleteOnShutdown(s chan os.Signal) {
+ signal.Notify(s, os.Interrupt)
+ signal.Notify(s, syscall.SIGTERM)
+ <-s
+ log.Info("Shutting down gracefully.")
+ if err := deleteJob(); err != nil {
+ log.Error(fmt.Sprintf("Unable to delete job on shutdown due to: %v. Please remove job %v manually.", err, jobId))
+ }
+}
+
func deleteJob() error {
- return restclient.Delete(infoCoordAddress+"/data-consumer/v1/info-jobs/"+jobId, client)
+ return restclient.Delete(configuration.InfoCoordinatorAddress+"/data-consumer/v1/info-jobs/"+jobId, client)
}
--- /dev/null
+// -
+// ========================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 (
+ "bytes"
+ "encoding/json"
+ "errors"
+ "fmt"
+ "io/ioutil"
+ "net/http"
+ "net/http/httptest"
+ "os"
+ "sync"
+ "syscall"
+ "testing"
+ "time"
+
+ log "github.com/sirupsen/logrus"
+ "github.com/stretchr/testify/mock"
+ "github.com/stretchr/testify/require"
+ "oransc.org/usecase/oruclosedloop/internal/config"
+ "oransc.org/usecase/oruclosedloop/internal/linkfailure"
+ "oransc.org/usecase/oruclosedloop/mocks"
+)
+
+func Test_init(t *testing.T) {
+ assertions := require.New(t)
+
+ os.Setenv("CONSUMER_HOST", "consumerHost")
+ os.Setenv("CONSUMER_PORT", "8095")
+ t.Cleanup(func() {
+ os.Clearenv()
+ })
+
+ doInit()
+
+ wantedConfiguration := &config.Config{
+ LogLevel: log.InfoLevel,
+ ConsumerHost: "consumerHost",
+ ConsumerPort: 8095,
+ InfoCoordinatorAddress: "http://enrichmentservice:8083",
+ SDNRHost: "http://localhost",
+ SDNRPort: 3904,
+ SDNRUser: "admin",
+ SDNPassword: "Kp8bJ4SXszM0WXlhak3eHlcse2gAw84vaoGGmJvUy2U",
+ ORUToODUMapFile: "o-ru-to-o-du-map.csv",
+ }
+ assertions.Equal(wantedConfiguration, configuration)
+
+ assertions.Equal(fmt.Sprint(wantedConfiguration.ConsumerPort), consumerPort)
+ assertions.Equal(wantedConfiguration.ConsumerHost+":"+fmt.Sprint(wantedConfiguration.ConsumerPort), jobRegistrationInfo.JobResultUri)
+
+ wantedLinkFailureConfig := linkfailure.Configuration{
+ SDNRAddress: wantedConfiguration.SDNRHost + ":" + fmt.Sprint(wantedConfiguration.SDNRPort),
+ SDNRUser: wantedConfiguration.SDNRUser,
+ SDNRPassword: wantedConfiguration.SDNPassword,
+ }
+ assertions.Equal(wantedLinkFailureConfig, linkfailureConfig)
+}
+
+func Test_validateConfiguration(t *testing.T) {
+ assertions := require.New(t)
+
+ type args struct {
+ configuration *config.Config
+ }
+ tests := []struct {
+ name string
+ args args
+ wantErr error
+ }{
+ {
+ name: "Valid config, should return nil",
+ args: args{
+ configuration: &config.Config{
+ ConsumerHost: "host",
+ ConsumerPort: 80,
+ },
+ },
+ },
+ {
+ name: "Invalid config, should return error",
+ args: args{
+ configuration: &config.Config{},
+ },
+ wantErr: fmt.Errorf("consumer host and port must be provided"),
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ err := validateConfiguration(tt.args.configuration)
+ assertions.Equal(tt.wantErr, err)
+ })
+ }
+}
+
+func Test_initializeLookupService(t *testing.T) {
+ assertions := require.New(t)
+ type args struct {
+ csvFile string
+ oRuId string
+ mockReturn [][]string
+ mockReturnError error
+ }
+ tests := []struct {
+ name string
+ args args
+ wantODuId string
+ wantInitErr error
+ }{
+ {
+ name: "Successful initialization, should return nil and lookup service should be initiated with data",
+ args: args{
+ csvFile: "file",
+ oRuId: "1",
+ mockReturn: [][]string{{"1", "2"}},
+ },
+ wantODuId: "2",
+ },
+ {
+ name: "Unsuccessful initialization, should return error and lookup service should not be initiated with data",
+ args: args{
+ csvFile: "file",
+ mockReturnError: errors.New("Error"),
+ },
+ wantInitErr: errors.New("Error"),
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ mockCsvFileHelper := &mocks.CsvFileHelper{}
+ mockCsvFileHelper.On("GetCsvFromFile", mock.Anything).Return(tt.args.mockReturn, tt.args.mockReturnError)
+
+ err := initializeLookupService(mockCsvFileHelper, tt.args.csvFile)
+ oDuId, _ := lookupService.GetODuID(tt.args.oRuId)
+ assertions.Equal(tt.wantODuId, oDuId)
+ assertions.Equal(tt.wantInitErr, err)
+ mockCsvFileHelper.AssertCalled(t, "GetCsvFromFile", tt.args.csvFile)
+ })
+ }
+}
+
+func Test_getRouter_shouldContainAllPathsWithHandlers(t *testing.T) {
+ assertions := require.New(t)
+
+ r := getRouter()
+ messageHandlerRoute := r.Get("messageHandler")
+ assertions.NotNil(messageHandlerRoute)
+ supportedMethods, err := messageHandlerRoute.GetMethods()
+ assertions.Equal([]string{http.MethodPost}, supportedMethods)
+ assertions.Nil(err)
+ path, _ := messageHandlerRoute.GetPathTemplate()
+ assertions.Equal("/", path)
+
+ startHandlerRoute := r.Get("start")
+ assertions.NotNil(messageHandlerRoute)
+ supportedMethods, err = startHandlerRoute.GetMethods()
+ assertions.Equal([]string{http.MethodPost}, supportedMethods)
+ assertions.Nil(err)
+ path, _ = startHandlerRoute.GetPathTemplate()
+ assertions.Equal("/admin/start", path)
+
+ stopHandlerRoute := r.Get("stop")
+ assertions.NotNil(stopHandlerRoute)
+ supportedMethods, err = stopHandlerRoute.GetMethods()
+ assertions.Equal([]string{http.MethodPost}, supportedMethods)
+ assertions.Nil(err)
+ path, _ = stopHandlerRoute.GetPathTemplate()
+ assertions.Equal("/admin/stop", path)
+}
+
+func Test_startServer_shouldDeleteJobWhenServerStopsWithErrorAndLog(t *testing.T) {
+ assertions := require.New(t)
+
+ var buf bytes.Buffer
+ log.SetOutput(&buf)
+
+ os.Setenv("CONSUMER_PORT", "wrong")
+ t.Cleanup(func() {
+ log.SetOutput(os.Stderr)
+ })
+
+ mockServer := &mocks.Server{}
+ mockServer.On("ListenAndServe").Return(errors.New("Server failure"))
+
+ startServer(mockServer)
+
+ log := buf.String()
+ assertions.Contains(log, "level=error")
+ assertions.Contains(log, "Server stopped unintentionally due to: Server failure. Deleteing job.")
+ assertions.Contains(log, "Please remove job 14e7bb84-a44d-44c1-90b7-6995a92ad43c manually")
+}
+
+func Test_startHandler(t *testing.T) {
+ assertions := require.New(t)
+
+ jobRegistrationInfo.JobResultUri = "host:80"
+
+ type args struct {
+ mockReturnBody []byte
+ mockReturnStatus int
+ }
+ tests := []struct {
+ name string
+ args args
+ wantedStatus int
+ wantedBody string
+ }{
+ {
+ name: "Start with successful registration, should return ok",
+ args: args{
+ mockReturnBody: []byte(""),
+ mockReturnStatus: http.StatusOK,
+ },
+ wantedStatus: http.StatusOK,
+ },
+ {
+ name: "Start with error response at registration, should return error",
+ args: args{
+ mockReturnBody: []byte("error"),
+ mockReturnStatus: http.StatusBadRequest,
+ },
+ wantedStatus: http.StatusBadRequest,
+ wantedBody: "Unable to register consumer job due to:",
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ clientMock := setUpClientMock(tt.args.mockReturnBody, tt.args.mockReturnStatus)
+
+ handler := http.HandlerFunc(startHandler)
+ responseRecorder := httptest.NewRecorder()
+ r, _ := http.NewRequest(http.MethodPost, "/start", nil)
+
+ handler.ServeHTTP(responseRecorder, r)
+
+ assertions.Equal(tt.wantedStatus, responseRecorder.Code, tt.name)
+ assertions.Contains(responseRecorder.Body.String(), tt.wantedBody, tt.name)
+
+ var wantedJobRegistrationInfo = struct {
+ InfoTypeId string `json:"info_type_id"`
+ JobResultUri string `json:"job_result_uri"`
+ JobOwner string `json:"job_owner"`
+ JobDefinition interface{} `json:"job_definition"`
+ }{
+ InfoTypeId: "STD_Fault_Messages",
+ JobResultUri: "host:80",
+ JobOwner: "O-RU Closed Loop Usecase",
+ JobDefinition: "{}",
+ }
+ wantedBody, _ := json.Marshal(wantedJobRegistrationInfo)
+
+ var actualRequest *http.Request
+ clientMock.AssertCalled(t, "Do", mock.MatchedBy(func(req *http.Request) bool {
+ actualRequest = req
+ return true
+ }))
+ assertions.Equal(http.MethodPut, actualRequest.Method)
+ assertions.Equal("http", actualRequest.URL.Scheme)
+ assertions.Equal("enrichmentservice:8083", actualRequest.URL.Host)
+ assertions.Equal("/data-consumer/v1/info-jobs/14e7bb84-a44d-44c1-90b7-6995a92ad43c", actualRequest.URL.Path)
+ assertions.Equal("application/json; charset=utf-8", actualRequest.Header.Get("Content-Type"))
+ body, _ := ioutil.ReadAll(actualRequest.Body)
+ expectedBody := wantedBody
+ assertions.Equal(expectedBody, body)
+ clientMock.AssertNumberOfCalls(t, "Do", 1)
+ })
+ }
+}
+
+func Test_stopHandler(t *testing.T) {
+ assertions := require.New(t)
+
+ jobRegistrationInfo.JobResultUri = "host:80"
+
+ type args struct {
+ mockReturnBody []byte
+ mockReturnStatus int
+ }
+ tests := []struct {
+ name string
+ args args
+ wantedStatus int
+ wantedBody string
+ }{
+ {
+ name: "Stop with successful job deletion, should return ok",
+ args: args{
+ mockReturnBody: []byte(""),
+ mockReturnStatus: http.StatusOK,
+ },
+ wantedStatus: http.StatusOK,
+ },
+ {
+ name: "Stop with error response at job deletion, should return error",
+ args: args{
+ mockReturnBody: []byte("error"),
+ mockReturnStatus: http.StatusBadRequest,
+ },
+ wantedStatus: http.StatusBadRequest,
+ wantedBody: "Please remove job 14e7bb84-a44d-44c1-90b7-6995a92ad43c manually",
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ clientMock := setUpClientMock(tt.args.mockReturnBody, tt.args.mockReturnStatus)
+
+ handler := http.HandlerFunc(stopHandler)
+ responseRecorder := httptest.NewRecorder()
+ r, _ := http.NewRequest(http.MethodPost, "/stop", nil)
+
+ handler.ServeHTTP(responseRecorder, r)
+
+ assertions.Equal(tt.wantedStatus, responseRecorder.Code, tt.name)
+ assertions.Contains(responseRecorder.Body.String(), tt.wantedBody, tt.name)
+
+ var actualRequest *http.Request
+ clientMock.AssertCalled(t, "Do", mock.MatchedBy(func(req *http.Request) bool {
+ actualRequest = req
+ return true
+ }))
+ assertions.Equal(http.MethodDelete, actualRequest.Method)
+ assertions.Equal("http", actualRequest.URL.Scheme)
+ assertions.Equal("enrichmentservice:8083", actualRequest.URL.Host)
+ assertions.Equal("/data-consumer/v1/info-jobs/14e7bb84-a44d-44c1-90b7-6995a92ad43c", actualRequest.URL.Path)
+ clientMock.AssertNumberOfCalls(t, "Do", 1)
+ })
+ }
+}
+
+func Test_deleteOnShutdown(t *testing.T) {
+ assertions := require.New(t)
+
+ var buf bytes.Buffer
+ log.SetOutput(&buf)
+
+ t.Cleanup(func() {
+ log.SetOutput(os.Stderr)
+ })
+
+ type args struct {
+ mockReturnBody []byte
+ mockReturnStatus int
+ }
+ tests := []struct {
+ name string
+ args args
+ wantedLog string
+ }{
+ {
+ name: "Delete with successful job deletion, should return ok",
+ args: args{
+ mockReturnBody: []byte(""),
+ mockReturnStatus: http.StatusOK,
+ },
+ },
+ {
+ name: "Stop with error response at job deletion, should return error",
+ args: args{
+ mockReturnBody: []byte("error"),
+ mockReturnStatus: http.StatusBadRequest,
+ },
+ wantedLog: "Please remove job 14e7bb84-a44d-44c1-90b7-6995a92ad43c manually",
+ },
+ }
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ setUpClientMock(tt.args.mockReturnBody, tt.args.mockReturnStatus)
+
+ c := make(chan os.Signal, 1)
+ go deleteOnShutdown(c)
+ c <- syscall.SIGTERM
+
+ waitForLogToBeWritten(&buf)
+
+ log := buf.String()
+ if tt.wantedLog != "" {
+ assertions.Contains(log, "level=error")
+ assertions.Contains(log, "Unable to delete job on shutdown due to:")
+ assertions.Contains(log, tt.wantedLog)
+ }
+ })
+ }
+}
+
+func waitForLogToBeWritten(logBuf *bytes.Buffer) {
+ wg := sync.WaitGroup{}
+ wg.Add(1)
+ for {
+ if waitTimeout(&wg, 10*time.Millisecond) && logBuf.Len() != 0 {
+ wg.Done()
+ break
+ }
+ }
+}
+
+// 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 setUpClientMock(body []byte, status int) *mocks.HTTPClient {
+ clientMock := mocks.HTTPClient{}
+ clientMock.On("Do", mock.Anything).Return(&http.Response{
+ Body: ioutil.NopCloser(bytes.NewReader(body)),
+ StatusCode: status,
+ }, nil)
+ client = &clientMock
+ return &clientMock
+}
--- /dev/null
+// Code generated by mockery v1.0.0. DO NOT EDIT.
+
+package mocks
+
+import mock "github.com/stretchr/testify/mock"
+
+// Server is an autogenerated mock type for the Server type
+type Server struct {
+ mock.Mock
+}
+
+// ListenAndServe provides a mock function with given fields:
+func (_m *Server) ListenAndServe() error {
+ ret := _m.Called()
+
+ var r0 error
+ if rf, ok := ret.Get(0).(func() error); ok {
+ r0 = rf()
+ } else {
+ r0 = ret.Error(0)
+ }
+
+ return r0
+}
--- /dev/null
+// -
+// ========================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 (
+ "bytes"
+ "encoding/json"
+ "net/http"
+ "time"
+
+ "oransc.org/usecase/oruclosedloop/internal/ves"
+)
+
+func main() {
+ message := ves.FaultMessage{
+ Event: ves.Event{
+ CommonEventHeader: ves.CommonEventHeader{
+ Domain: "fault",
+ SourceName: "ERICSSON-O-RU-11220",
+ },
+ FaultFields: ves.FaultFields{
+ AlarmCondition: "28",
+ },
+ },
+ }
+ client := &http.Client{
+ Timeout: 5 * time.Second,
+ }
+
+ critical := true
+ for range time.Tick(2 * time.Second) {
+ if critical {
+ message.Event.FaultFields.EventSeverity = "CRITICAL"
+ critical = false
+ } else {
+ critical = true
+ message.Event.FaultFields.EventSeverity = "NORMAL"
+ }
+ m, _ := json.Marshal(message)
+ msgToSend, _ := json.Marshal([]string{string(m)})
+
+ req, _ := http.NewRequest(http.MethodPost, "http://localhost:40935", bytes.NewBuffer(msgToSend))
+ req.Header.Set("Content-Type", "application/json; charset=utf-8")
+
+ client.Do(req)
+ }
+
+}
requred: true
topology_template:
node_templates:
- org.onap.domain.linkmonitor.LinkMonitorControlLoopDefinition:
+ org.onap.domain.linkmonitor.LinkMonitorControlLoopDefinition1:
version: 1.2.3
type: org.onap.policy.clamp.controlloop.ControlLoop
type_version: 1.0.1
properties:
provider: ONAP
participant_id:
+ name: K8sParticipant0
+ version: 1.0.0
+ participantType:
name: org.onap.k8s.controlloop.K8SControlLoopParticipant
version: 2.3.4
- uninitializedToPassiveTimeout: 180
- podStatusCheckInterval: 30
chart:
chartId:
name: oru-app
version: 0.1.0
releaseName: oru-app
- # repository can point to a helm repo or a path in local file system where chart is stored
- repository: chartmuseum
+ repository:
+ repoName: chartmuseum
namespace: nonrtric
org.onap.domain.linkmonitor.MessageGeneratorK8SMicroserviceControlLoopElement:
version: 1.2.3
properties:
provider: ONAP
participant_id:
+ name: K8sParticipant0
+ version: 1.0.0
+ participantType:
name: org.onap.k8s.controlloop.K8SControlLoopParticipant
version: 2.3.4
- uninitializedToPassiveTimeout: 180
- podStatusCheckInterval: 30
chart:
chartId:
name: message-generator
version: 0.1.0
releaseName: message-generator
- # repository can point to a helm repo or a path in local file system where chart is stored
- repository: chartmuseum
+ repository:
+ repoName: chartmuseum
namespace: nonrtric
overrideParams:
image.tag: v2
properties:
provider: ONAP
participant_id:
+ name: K8sParticipant0
+ version: 1.0.0
+ participantType:
name: org.onap.k8s.controlloop.K8SControlLoopParticipant
version: 2.3.4
- uninitializedToPassiveTimeout: 180
- podStatusCheckInterval: 30
chart:
chartId:
name: sdnr-simulator
version: 0.1.0
releaseName: sdnr-simulator
- # repository can point to a helm repo or a path in local file system where chart is stored
- repository: chartmuseum
+ repository:
+ repoName: chartmuseum
namespace: nonrtric
org.onap.domain.linkmonitor.DmaapMrK8SMicroserviceControlLoopElement:
version: 1.2.3
properties:
provider: ONAP
participant_id:
+ name: K8sParticipant0
+ version: 1.0.0
+ participantType:
name: org.onap.k8s.controlloop.K8SControlLoopParticipant
version: 2.3.4
- uninitializedToPassiveTimeout: 180
- podStatusCheckInterval: 30
chart:
chartId:
name: dmaap-mr
version: 0.1.0
releaseName: dmaap-mr
- # repository can point to a helm repo or a path in local file system where chart is stored
- repository: chartmuseum
+ repository:
+ repoName: chartmuseum
namespace: nonrtric
\ No newline at end of file
{
- "orderedState": "RUNNING",
+ "orderedState": "PASSIVE",
"controlLoopIdentifierList": [
{
- "name": "LinkMonitorInstance0",
+ "name": "LinkMonitorInstance1",
"version": "1.0.1"
}
]
{
"controlLoopList": [
{
- "name": "LinkMonitorInstance0",
+ "name": "LinkMonitorInstance1",
"version": "1.0.1",
"definition": {
- "name": "org.onap.domain.linkmonitor.LinkMonitorControlLoopDefinition",
+ "name": "org.onap.domain.linkmonitor.LinkMonitorControlLoopDefinition1",
"version": "1.2.3"
},
"state": "UNINITIALISED",
"orderedState": "UNINITIALISED",
- "description": "Link Monitor control loop instance 0",
+ "description": "Link Monitor control loop instance 1",
"elements": {
- "709c62b3-8918-41b9-a747-d21eb79c6c22": {
- "id": "709c62b3-8918-41b9-a747-d21eb79c6c22",
+ "709c62b3-8918-41b9-a747-d21eb79c6c12": {
+ "id": "709c62b3-8918-41b9-a747-d21eb79c6c12",
"definition": {
"name": "org.onap.domain.linkmonitor.OruAppK8SMicroserviceControlLoopElement",
"version": "1.2.3"
"name": "org.onap.k8s.controlloop.K8SControlLoopParticipant",
"version": "2.3.4"
},
+ "participantId": {
+ "name": "K8sParticipant0",
+ "version": "1.0.0"
+ },
"state": "UNINITIALISED",
"orderedState": "UNINITIALISED",
"description": "Oru App k8s Control Loop Element"
},
- "709c62b3-8918-41b9-a747-d21eb79c6c23": {
- "id": "709c62b3-8918-41b9-a747-d21eb79c6c23",
+ "709c62b3-8918-41b9-a747-d21eb79c6c13": {
+ "id": "709c62b3-8918-41b9-a747-d21eb79c6c13",
"definition": {
"name": "org.onap.domain.linkmonitor.MessageGeneratorK8SMicroserviceControlLoopElement",
"version": "1.2.3"
"name": "org.onap.k8s.controlloop.K8SControlLoopParticipant",
"version": "2.3.4"
},
+ "participantId": {
+ "name": "K8sParticipant0",
+ "version": "1.0.0"
+ },
"state": "UNINITIALISED",
"orderedState": "UNINITIALISED",
"description": "Message Generator k8s Control Loop Element"
},
- "709c62b3-8918-41b9-a747-d21eb79c6c24": {
- "id": "709c62b3-8918-41b9-a747-d21eb79c6c24",
+ "709c62b3-8918-41b9-a747-d21eb79c6c14": {
+ "id": "709c62b3-8918-41b9-a747-d21eb79c6c14",
"definition": {
"name": "org.onap.domain.linkmonitor.SdnrSimulatorK8SMicroserviceControlLoopElement",
"version": "1.2.3"
"name": "org.onap.k8s.controlloop.K8SControlLoopParticipant",
"version": "2.3.4"
},
+ "participantId": {
+ "name": "K8sParticipant0",
+ "version": "1.0.0"
+ },
"state": "UNINITIALISED",
"orderedState": "UNINITIALISED",
"description": "Sdnr Simulator k8s Control Loop Element"
},
- "709c62b3-8918-41b9-a747-d21eb79c6c25": {
- "id": "709c62b3-8918-41b9-a747-d21eb79c6c25",
+ "709c62b3-8918-41b9-a747-d21eb79c6c15": {
+ "id": "709c62b3-8918-41b9-a747-d21eb79c6c15",
"definition": {
"name": "org.onap.domain.linkmonitor.DmaapMrK8SMicroserviceControlLoopElement",
"version": "1.2.3"
"name": "org.onap.k8s.controlloop.K8SControlLoopParticipant",
"version": "2.3.4"
},
+ "participantId": {
+ "name": "K8sParticipant0",
+ "version": "1.0.0"
+ },
"state": "UNINITIALISED",
"orderedState": "UNINITIALISED",
"description": "Dmaap Mr k8s Control Loop Element"
###
mysql -uroot -p$MYSQL_ROOT_PASSWORD -f < /docker-entrypoint-initdb.d/create-db.sql
-mysql -uroot -p$MYSQL_ROOT_PASSWORD --execute "CREATE USER 'policy'@'%' IDENTIFIED BY 'P01icY';"
-mysql -uroot -p$MYSQL_ROOT_PASSWORD --execute "GRANT ALL PRIVILEGES ON controlloop.* TO 'policy'@'%';"
\ No newline at end of file
+mysql -uroot -p$MYSQL_ROOT_PASSWORD --execute "CREATE USER 'policy_user'@'%' IDENTIFIED BY 'policy_user';"
+mysql -uroot -p$MYSQL_ROOT_PASSWORD --execute "GRANT ALL PRIVILEGES ON controlloop.* TO 'policy_user'@'%';"
\ No newline at end of file
expose:
- 3306
controlloop-runtime:
- image: nexus3.onap.org:10001/onap/policy-controlloop-runtime:6.1.2-SNAPSHOT
+ image: nexus3.onap.org:10001/onap/policy-clamp-cl-runtime:6.1.3
container_name: controlloop-runtime
depends_on:
- mariadb
expose:
- 6969
volumes:
- - ./config/ks.jks:/opt/app/policy/clamp/etc/ssl/policy-keystore.jks:ro
+ - ./config/ks.jks:/opt/app/policy/clamp/etc/ssl/policy-keystore:ro
+ - ./wait_for_port.sh:/opt/app/policy/clamp/bin/wait_for_port.sh:ro
environment:
- TOPICSERVER=onap-dmaap
- MARIADB_HOST=mariadb
- MARIADB_PORT=3306
+ - KEYSTORE=/opt/app/policy/clamp/etc/ssl/policy-keystore
+ - KEYSTORE_PASSWD=Pol1cy_0nap
+ - RUNTIME_TOPICPARAMETERGROUP_TOPICSOURCES_0_TOPIC=POLICY-CLRUNTIME-PARTICIPANT
+ - RUNTIME_TOPICPARAMETERGROUP_TOPICSOURCES_0_SERVERS_0=onap-dmaap
+ - RUNTIME_TOPICPARAMETERGROUP_TOPICSOURCES_0_TOPICCOMMINFRASTRUCTURE=dmaap
+ - RUNTIME_TOPICPARAMETERGROUP_TOPICSOURCES_0_FETCHTIMEOUT=15000
+ - RUNTIME_TOPICPARAMETERGROUP_TOPICSOURCES_0_USEHTTPS=false
+ - RUNTIME_TOPICPARAMETERGROUP_TOPICSINKS_0_TOPIC=POLICY-CLRUNTIME-PARTICIPANT
+ - RUNTIME_TOPICPARAMETERGROUP_TOPICSINKS_0_SERVERS_0=onap-dmaap
+ - RUNTIME_TOPICPARAMETERGROUP_TOPICSINKS_0_TOPICCOMMINFRASTRUCTURE=dmaap
+ - RUNTIME_TOPICPARAMETERGROUP_TOPICSINKS_0_FETCHTIMEOUT=15000
+ - RUNTIME_TOPICPARAMETERGROUP_TOPICSINKS_0_USEHTTPS=false
+ entrypoint: /opt/app/policy/clamp/bin/wait_for_port.sh
+ command: [
+ '-c', '/opt/app/policy/clamp/bin/controlloop-runtime.sh',
+ 'mariadb', '3306',
+ 'onap-dmaap', '3904'
+ ]
k8s-participant:
- image: nexus3.onap.org:10001/onap/kubernetes-participant:6.1.2-SNAPSHOT
+ image: nexus3.onap.org:10001/onap/policy-clamp-cl-k8s-ppnt:6.1.3
container_name: k8s-participant
depends_on:
- mariadb
- controlloop-runtime
- - chartmuseum
hostname: k8s-participant
volumes:
- - ./config/ks.jks:/opt/app/policy/clamp/etc/ssl/policy-keystore.jks:ro
+ - ./config/ks.jks:/opt/app/policy/clamp/etc/ssl/policy-keystore:ro
- ./../helm:/home/policy/helm
+ - ./wait_for_port.sh:/opt/app/policy/clamp/bin/wait_for_port.sh:ro
- <PATH TO kube-config>:/home/policy/.kube/config:ro
environment:
- TOPICSERVER=onap-dmaap
- - KEYSTORE=/opt/app/policy/clamp/etc/ssl/policy-keystore.jks
+ - KEYSTORE=/opt/app/policy/clamp/etc/ssl/policy-keystore
- KEYSTORE_PASSWD=Pol1cy_0nap
- entrypoint: sh -c "/home/policy/helm/chartmuseum_init.sh && /opt/app/policy/clamp/bin/kubernetes-participant.sh"
+ - PARTICIPANT_INTERMEDIARYPARAMETERS_CLAMPCONTROLLOOPTOPICS_TOPICSOURCES_0_TOPIC=POLICY-CLRUNTIME-PARTICIPANT
+ - PARTICIPANT_INTERMEDIARYPARAMETERS_CLAMPCONTROLLOOPTOPICS_TOPICSOURCES_0_SERVERS_0=onap-dmaap
+ - PARTICIPANT_INTERMEDIARYPARAMETERS_CLAMPCONTROLLOOPTOPICS_TOPICSOURCES_0_TOPICCOMMINFRASTRUCTURE=dmaap
+ - PARTICIPANT_INTERMEDIARYPARAMETERS_CLAMPCONTROLLOOPTOPICS_TOPICSOURCES_0_FETCHTIMEOUT=15000
+ - PARTICIPANT_INTERMEDIARYPARAMETERS_CLAMPCONTROLLOOPTOPICS_TOPICSOURCES_0_USEHTTPS=false
+ - PARTICIPANT_INTERMEDIARYPARAMETERS_CLAMPCONTROLLOOPTOPICS_TOPICSINKS_0_TOPIC=POLICY-CLRUNTIME-PARTICIPANT
+ - PARTICIPANT_INTERMEDIARYPARAMETERS_CLAMPCONTROLLOOPTOPICS_TOPICSINKS_0_SERVERS_0=onap-dmaap
+ - PARTICIPANT_INTERMEDIARYPARAMETERS_CLAMPCONTROLLOOPTOPICS_TOPICSINKS_0_TOPICCOMMINFRASTRUCTURE=dmaap
+ - PARTICIPANT_INTERMEDIARYPARAMETERS_CLAMPCONTROLLOOPTOPICS_TOPICSINKS_0_FETCHTIMEOUT=15000
+ - PARTICIPANT_INTERMEDIARYPARAMETERS_CLAMPCONTROLLOOPTOPICS_TOPICSINKS_0_USEHTTPS=false
+ entrypoint: sh -c "/opt/app/policy/clamp/bin/wait_for_port.sh controlloop-runtime 6969 && /home/policy/helm/chartmuseum_init.sh && /opt/app/policy/clamp/bin/kubernetes-participant.sh"
chartmuseum:
image: ghcr.io/helm/chartmuseum:v0.13.1
container_name: chartmuseum
--- /dev/null
+#!/bin/sh
+# ============LICENSE_START====================================================
+# Copyright (C) 2021 AT&T Intellectual Property. 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.
+#
+# SPDX-License-Identifier: Apache-2.0
+# ============LICENSE_END======================================================
+
+tmout=120
+cmd=
+while getopts c:t: opt; do
+ case "$opt" in
+ c) cmd="$OPTARG" ;;
+ t) tmout="$OPTARG" ;;
+ esac
+done
+nargs=$(expr $OPTIND - 1)
+shift $nargs
+
+even_args=$(expr $# % 2)
+if [ $# -lt 2 -o $even_args -ne 0 ]; then
+ echo "args: [-t timeout] [-c command] hostname1 port1 hostname2 port2 ..." >&2
+ exit 1
+fi
+
+while [ $# -ge 2 ]; do
+ export host=$1
+ export port=$2
+ shift
+ shift
+
+ echo "Waiting for $host port $port..."
+ timeout $tmout sh -c 'until nc -vz "$host" "$port"; do echo -n ".";
+ sleep 1; done'
+ rc=$?
+
+ if [ $rc != 0 ]; then
+ echo "$host port $port cannot be reached"
+ exit $rc
+ fi
+done
+
+$cmd
+
+exit 0