From: Gary Wu Date: Tue, 23 Oct 2018 21:49:18 +0000 (+0000) Subject: Merge "OOF SMS CSIT" X-Git-Tag: 3.0.0-ONAP~19 X-Git-Url: https://gerrit.onap.org/r/gitweb?a=commitdiff_plain;h=97f80c77d52858b2b20484703bb1f235e5fcf393;hp=425ba9232b52ee2d40999526ae792bbf2bf76f55;p=integration%2Fcsit.git Merge "OOF SMS CSIT" --- diff --git a/plans/dcaegen2/prh-testsuites/setup.sh b/plans/dcaegen2/prh-testsuites/setup.sh index 096c695b..9040ae60 100644 --- a/plans/dcaegen2/prh-testsuites/setup.sh +++ b/plans/dcaegen2/prh-testsuites/setup.sh @@ -2,17 +2,6 @@ source ${SCRIPTS}/common_functions.sh -function check_heartbeat () -{ - local port=$1 - - for i in {1..10}; do - curl -sS -m 1 localhost:$port/heartbeat && break - echo sleep ${i} - sleep ${i} - done -} - export PRH_SERVICE="prh" export SSL_PRH_SERVICE="ssl_prh" export DMAAP_SIMULATOR="dmaap_simulator" @@ -41,9 +30,9 @@ echo DMAAP_SIMULATOR_IP=${DMAAP_SIMULATOR_IP} echo AAI_SIMULATOR_IP=${AAI_SIMULATOR_IP} # Wait for initialization of PRH services -check_heartbeat 8100 -check_heartbeat 8200 +wait_for_service_init localhost:8100/heartbeat +wait_for_service_init localhost:8200/heartbeat # #Pass any variables required by Robot test suites in ROBOT_VARIABLES -ROBOT_VARIABLES="-v DMAAP_SIMULATOR:${DMAAP_SIMULATOR_IP}:2222 -v AAI_SIMULATOR:${AAI_SIMULATOR_IP}:3333 -v SSL_AAI_SIMULATOR:${AAI_SIMULATOR_IP}:3334 -v AAI_SIMULATOR_SETUP:${AAI_SIMULATOR_IP}:3335" +ROBOT_VARIABLES="-v DMAAP_SIMULATOR_SETUP:${DMAAP_SIMULATOR_IP}:2224 -v AAI_SIMULATOR_SETUP:${AAI_SIMULATOR_IP}:3335" diff --git a/plans/dmaap-buscontroller/with_dr/teardown.sh b/plans/dmaap-buscontroller/with_dr/teardown.sh index 23ae60a1..c7a2d6d8 100755 --- a/plans/dmaap-buscontroller/with_dr/teardown.sh +++ b/plans/dmaap-buscontroller/with_dr/teardown.sh @@ -21,6 +21,6 @@ if [ "$KEEP_DMAAP" != "Y" ] then kill-instance.sh dmaapbc -cd $WORKSPACE/archives/dmaapdr/datarouter/docker-compose/ +cd $WORKSPACE/archives/dmaapdr/datarouter/datarouter-docker-compose/src/main/resources docker-compose down -v fi diff --git a/plans/multicloud-azure/functionality1/setup.sh b/plans/multicloud-azure/functionality1/setup.sh new file mode 100755 index 00000000..54941ad1 --- /dev/null +++ b/plans/multicloud-azure/functionality1/setup.sh @@ -0,0 +1,34 @@ +#!/bin/bash +# +# Copyright (c) 2018 Amdocs +# +# 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. + +pushd ${SCRIPTS} + +# start multicloud-azure +./run-instance.sh nexus3.onap.org:10001/onap/multicloud/azure:latest multicloud-azure +SERVICE_IP=$(./get-instance-ip.sh multicloud-azure) +SERVICE_PORT=9008 +popd + +if [[ $no_proxy && $no_proxy != *$SERVICE_IP* ]]; then + export no_proxy+=$no_proxy,$SERVICE_IP +fi + +for i in {1..50}; do + curl -sS ${SERVICE_IP}:${SERVICE_PORT} && break + echo sleep $i + sleep $i +done + +# Pass any variables required by Robot test suites in ROBOT_VARIABLES +ROBOT_VARIABLES+="-v SERVICE_IP:${SERVICE_IP} " +ROBOT_VARIABLES+="-v SERVICE_PORT:${SERVICE_PORT} " diff --git a/plans/multicloud-azure/functionality1/teardown.sh b/plans/multicloud-azure/functionality1/teardown.sh new file mode 100755 index 00000000..5cb017a1 --- /dev/null +++ b/plans/multicloud-azure/functionality1/teardown.sh @@ -0,0 +1,15 @@ +#!/bin/bash +# +# Copyright (c) 2018 Amdocs +# +# 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. + +# This script is sourced by run-csit.sh after Robot test completion. +kill-instance.sh multicloud-azure diff --git a/plans/multicloud-azure/functionality1/testplan.txt b/plans/multicloud-azure/functionality1/testplan.txt new file mode 100644 index 00000000..0bc3efa8 --- /dev/null +++ b/plans/multicloud-azure/functionality1/testplan.txt @@ -0,0 +1,3 @@ +# Test suites are relative paths under [integration/csit.git]/tests/. +# Place the suites in run order. +multicloud-azure/provision/sanity_test_multicloud.robot diff --git a/plans/vid/healthCheck/setup.sh b/plans/vid/healthCheck/setup.sh index 38dddf54..584a640a 100644 --- a/plans/vid/healthCheck/setup.sh +++ b/plans/vid/healthCheck/setup.sh @@ -14,24 +14,30 @@ # See the License for the specific language governing permissions and # limitations under the License. # -# Modifications copyright (c) 2017 AT&T Intellectual Property +# Modifications copyright (c) 2018 Nokia Intellectual Property # # Place the scripts in run order: /usr/bin/Xvfb :0 -screen 0 1024x768x24& export DISPLAY=:0 +source ${SCRIPTS}/common_functions.sh source ${WORKSPACE}/scripts/vid/clone_and_setup_vid_data.sh - source ${WORKSPACE}/scripts/vid/start_vid_containers.sh +echo `Obtaining ip of VID server...` +VID_IP=`get-instance-ip.sh vid-server` +SO_SIMULATOR_IP=`get-instance-ip.sh so-simulator` + +bypass_ip_address ${VID_IP} +bypass_ip_address ${SO_SIMULATOR_IP} -BE_IP=`get-instance-ip.sh vid-server` -echo BE_IP=${BE_IP} +echo VID_IP=${VID_IP} +echo SO_SIMULATOR_IP=${SO_SIMULATOR_IP} # Pass any variables required by Robot test suites in ROBOT_VARIABLES -ROBOT_VARIABLES="-v BE_IP:${BE_IP}" +ROBOT_VARIABLES="-v VID_IP:${VID_IP} -v SO_SIMULATOR_IP:${SO_SIMULATOR_IP}" pip install assertpy pip install requests \ No newline at end of file diff --git a/plans/vid/healthCheck/teardown.sh b/plans/vid/healthCheck/teardown.sh index 14fd0522..8f168679 100644 --- a/plans/vid/healthCheck/teardown.sh +++ b/plans/vid/healthCheck/teardown.sh @@ -14,7 +14,7 @@ # See the License for the specific language governing permissions and # limitations under the License. # -# Modifications copyright (c) 2017 AT&T Intellectual Property +# Modifications copyright (c) 2018 Nokia Intellectual Property # source ${WORKSPACE}/scripts/vid/kill_containers_and_remove_dataFolders.sh diff --git a/plans/vid/healthCheck/testplan.txt b/plans/vid/healthCheck/testplan.txt index 20add7af..61c39083 100644 --- a/plans/vid/healthCheck/testplan.txt +++ b/plans/vid/healthCheck/testplan.txt @@ -3,3 +3,4 @@ vid/healthCheck vid/login vid/https-connection +vid/scaleOut \ No newline at end of file diff --git a/scripts/dmaap-buscontroller/dr-launch.sh b/scripts/dmaap-buscontroller/dr-launch.sh index abc0aae8..bba1b73d 100644 --- a/scripts/dmaap-buscontroller/dr-launch.sh +++ b/scripts/dmaap-buscontroller/dr-launch.sh @@ -20,9 +20,8 @@ function dmaap_dr_launch() { git clone --depth 1 https://gerrit.onap.org/r/dmaap/datarouter -b master cd datarouter git pull - cd $WORKSPACE/archives/dmaapdr/datarouter/docker-compose/ + cd $WORKSPACE/archives/dmaapdr/datarouter/datarouter-docker-compose/src/main/resources - sed -i 's/10003/10001/g' docker-compose.yml # start DMaaP DR containers with docker compose and configuration from docker-compose.yml docker login -u docker -p docker nexus3.onap.org:10001 docker-compose up -d diff --git a/scripts/get-instance-ip.sh b/scripts/get-instance-ip.sh index c4ca82cf..a236c025 100755 --- a/scripts/get-instance-ip.sh +++ b/scripts/get-instance-ip.sh @@ -14,4 +14,4 @@ # See the License for the specific language governing permissions and # limitations under the License. # -docker inspect --format '{{ .NetworkSettings.IPAddress }}' $1 +docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' $1 diff --git a/scripts/vid/start_vid_containers.sh b/scripts/vid/start_vid_containers.sh index a058e1fb..c8804349 100644 --- a/scripts/vid/start_vid_containers.sh +++ b/scripts/vid/start_vid_containers.sh @@ -17,6 +17,8 @@ # 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. +# +# Modifications copyright (c) 2018 Nokia Intellectual Property # ============LICENSE_END============================================ # =================================================================== # ECOMP is a trademark and service mark of AT&T Intellectual Property. @@ -33,8 +35,21 @@ docker-compose up -d --build TIME_OUT=1200 INTERVAL=5 TIME=0 + + for i in {1..10}; do + if [ $(docker inspect -f '{{ .State.Running }}' vid-server) ] + then + echo "VID service is running" + VID_DOCKER_IP=$(docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' vid-server) + break + else + echo "Waiting for vid-server docker initialization... $i" + sleep $i + fi + done + while [ "$TIME" -lt "$TIME_OUT" ]; do - response=$(curl --write-out '%{http_code}' --silent --output /dev/null http://localhost:8080/vid/healthCheck); echo $response + response=$(curl --write-out '%{http_code}' --silent --output /dev/null http://"$VID_DOCKER_IP":8080/vid/healthCheck); echo $response if [ "$response" == "200" ]; then echo VID and its database well started in $TIME seconds diff --git a/tests/dcaegen2/prh-testcases/prh_tests.robot b/tests/dcaegen2/prh-testcases/prh_tests.robot index d81efe6e..634f37f8 100644 --- a/tests/dcaegen2/prh-testcases/prh_tests.robot +++ b/tests/dcaegen2/prh-testcases/prh_tests.robot @@ -1,14 +1,15 @@ *** Settings *** Documentation Integration tests for PRH. ... PRH receive events from DMaaP and produce or not PNF_READY notification depends on required fields in received event. -Suite Setup Run keywords Create header Create sessions -Test Setup Run keywords Reset Simulators +Suite Setup Run keywords Create header AND Create sessions AND Ensure Container Is Running prh AND Ensure Container Is Exited ssl_prh +Suite Teardown Ensure Container Is Running ssl_prh +Test Teardown Reset Simulators Library resources/PrhLibrary.py Resource resources/prh_library.robot Resource ../../common.robot *** Variables *** -${DMAAP_SIMULATOR_URL} http://${DMAAP_SIMULATOR} +${DMAAP_SIMULATOR_SETUP_URL} http://${DMAAP_SIMULATOR_SETUP} ${AAI_SIMULATOR_SETUP_URL} http://${AAI_SIMULATOR_SETUP} ${EVENT_WITH_ALL_VALID_REQUIRED_FIELDS} %{WORKSPACE}/tests/dcaegen2/prh-testcases/assets/json_events/event_with_all_fields.json ${EVENT_WITH_IPV4} %{WORKSPACE}/tests/dcaegen2/prh-testcases/assets/json_events/event_with_IPV4.json @@ -62,6 +63,7 @@ Get valid event from DMaaP and AAI is not responding [Tags] PRH AAI [Timeout] 180s ${data}= Get Data From File ${EVENT_WITH_ALL_VALID_REQUIRED_FIELDS} - Stop AAI + Ensure Container Is Exited aai_simulator Set event in DMaaP ${data} Wait Until Keyword Succeeds 100x 300ms Check PRH log java.net.UnknownHostException: aai + Ensure Container Is Running aai_simulator diff --git a/tests/dcaegen2/prh-testcases/resources/PrhLibrary.py b/tests/dcaegen2/prh-testcases/resources/PrhLibrary.py index 656f6fc3..dc589369 100644 --- a/tests/dcaegen2/prh-testcases/resources/PrhLibrary.py +++ b/tests/dcaegen2/prh-testcases/resources/PrhLibrary.py @@ -1,6 +1,7 @@ import json import docker +import time class PrhLibrary(object): @@ -35,10 +36,45 @@ class PrhLibrary(object): return correlation_id @staticmethod - def stop_aai(): + def ensure_container_is_running(name): client = docker.from_env() - container = client.containers.get('aai_simulator') - container.stop() + + if not PrhLibrary.is_in_status(client, name, "running"): + print ("starting container", name) + container = client.containers.get(name) + container.start() + PrhLibrary.wait_for_status(client, name, "running") + + PrhLibrary.print_status(client) + + @staticmethod + def ensure_container_is_exited(name): + client = docker.from_env() + + if not PrhLibrary.is_in_status(client, name, "exited"): + print ("stopping container", name) + container = client.containers.get(name) + container.stop() + PrhLibrary.wait_for_status(client, name, "exited") + + PrhLibrary.print_status(client) + + @staticmethod + def print_status(client): + print("containers status") + for c in client.containers.list(all=True): + print(c.name, " ", c.status) + + @staticmethod + def wait_for_status(client, name, status): + while not PrhLibrary.is_in_status(client, name, status): + print ("waiting for container: ", name, "to be in status: ", status) + time.sleep(3) + + @staticmethod + def is_in_status(client, name, status): + return len(client.containers.list(all=True, filters={"name": "^/"+name+"$", "status": status})) == 1 + def create_invalid_notification(self, json_file): return self.create_pnf_ready_notification(json_file).replace("\":", "\": ")\ diff --git a/tests/dcaegen2/prh-testcases/resources/docker-compose.yml b/tests/dcaegen2/prh-testcases/resources/docker-compose.yml index 04d5763f..6d646801 100644 --- a/tests/dcaegen2/prh-testcases/resources/docker-compose.yml +++ b/tests/dcaegen2/prh-testcases/resources/docker-compose.yml @@ -31,9 +31,9 @@ services: --dmaap.dmaapConsumerConfiguration.dmaapPortNumber=2222 --dmaap.dmaapProducerConfiguration.dmaapHostName=dmaap --dmaap.dmaapProducerConfiguration.dmaapPortNumber=2222 - --aai.aaiClientConfiguration.aaiHostPortNumber=3334 + --aai.aaiClientConfiguration.aaiHostPortNumber=3333 --aai.aaiClientConfiguration.aaiHost=aai - --aai.aaiClientConfiguration.aaiProtocol=https + --aai.aaiClientConfiguration.aaiProtocol=http entrypoint: - java - -Dspring.profiles.active=dev @@ -54,6 +54,8 @@ services: dockerfile: DMaaP_simulator ports: - "2222:2222" + - "2223:2223" + - "2224:2224" container_name: dmaap_simulator aai: diff --git a/tests/dcaegen2/prh-testcases/resources/prh_library.robot b/tests/dcaegen2/prh-testcases/resources/prh_library.robot index b7653671..71753875 100644 --- a/tests/dcaegen2/prh-testcases/resources/prh_library.robot +++ b/tests/dcaegen2/prh-testcases/resources/prh_library.robot @@ -10,13 +10,14 @@ Create header Set Suite Variable ${suite_headers} ${headers} Create sessions - Create Session dmaap_session ${DMAAP_SIMULATOR_URL} - Set Suite Variable ${suite_dmaap_session} dmaap_session + Create Session dmaap_setup_session ${DMAAP_SIMULATOR_SETUP_URL} + Set Suite Variable ${dmaap_setup_session} dmaap_setup_session Create Session aai_setup_session ${AAI_SIMULATOR_SETUP_URL} Set Suite Variable ${aai_setup_session} aai_setup_session Reset Simulators Reset AAI simulator + Reset DMaaP simulator Invalid event processing [Arguments] ${input_invalid_event_in_dmaap} @@ -44,7 +45,7 @@ Check PRH log Check PNF_READY notification [Arguments] ${posted_event_to_dmaap} - ${resp}= Get Request ${suite_dmaap_session} /events/pnfReady headers=${suite_headers} + ${resp}= Get Request ${dmaap_setup_session} /events/pnfReady headers=${suite_headers} Should Be Equal ${resp.text} ${posted_event_to_dmaap} Set PNF name in AAI @@ -55,9 +56,13 @@ Set PNF name in AAI Set event in DMaaP [Arguments] ${event_in_dmaap} - ${resp}= Put Request ${suite_dmaap_session} /set_get_event headers=${suite_headers} data=${event_in_dmaap} + ${resp}= Put Request ${dmaap_setup_session} /set_get_event headers=${suite_headers} data=${event_in_dmaap} Should Be Equal As Strings ${resp.status_code} 200 Reset AAI simulator ${resp}= Post Request ${aai_setup_session} /reset Should Be Equal As Strings ${resp.status_code} 200 + +Reset DMaaP simulator + ${resp}= Post Request ${dmaap_setup_session} /reset + Should Be Equal As Strings ${resp.status_code} 200 \ No newline at end of file diff --git a/tests/dcaegen2/prh-testcases/resources/simulator/AAI.py b/tests/dcaegen2/prh-testcases/resources/simulator/AAI.py index b6c9c0f9..416e7f45 100644 --- a/tests/dcaegen2/prh-testcases/resources/simulator/AAI.py +++ b/tests/dcaegen2/prh-testcases/resources/simulator/AAI.py @@ -1,6 +1,7 @@ +import re +import time from http.server import BaseHTTPRequestHandler -from http.server import HTTPServer -import _thread, ssl, time, re +import httpServerLib pnfs = 'Empty' @@ -12,7 +13,7 @@ class AAISetup(BaseHTTPRequestHandler): global pnfs content_length = int(self.headers['Content-Length']) pnfs = self.rfile.read(content_length) - _header_200_and_json(self) + httpServerLib.header_200_and_json(self) return @@ -20,10 +21,11 @@ class AAISetup(BaseHTTPRequestHandler): if re.search('/reset', self.path): global pnfs pnfs = 'Empty' - _header_200_and_json(self) + httpServerLib.header_200_and_json(self) return + class AAIHandler(BaseHTTPRequestHandler): def do_PATCH(self): @@ -38,37 +40,14 @@ class AAIHandler(BaseHTTPRequestHandler): return -def _header_200_and_json(self): - self.send_response(200) - self.send_header('Content-Type', 'application/json') - self.end_headers() - - def _main_(handler_class=AAIHandler, protocol="HTTP/1.0"): handler_class.protocol_version = protocol - _thread.start_new_thread(_init_http_endpoints, (3333, AAIHandler)) - _thread.start_new_thread(_init_https_endpoints, (3334, AAIHandler)) - _thread.start_new_thread(_init_http_endpoints, (3335, AAISetup)) + httpServerLib.start_http_endpoint(3333, AAIHandler) + httpServerLib.start_https_endpoint(3334, AAIHandler) + httpServerLib.start_http_endpoint(3335, AAISetup) while 1: time.sleep(10) -def _init_http_endpoints(port, handler_class, server_class=HTTPServer): - server = server_class(('', port), handler_class) - sa = server.socket.getsockname() - print("Serving HTTP on", sa[0], "port", sa[1], "for", handler_class, "...") - server.serve_forever() - - -def _init_https_endpoints(port, handler_class, server_class=HTTPServer): - server = server_class(('', port), handler_class) - server.socket = ssl.wrap_socket(server.socket, - keyfile="certs/server.key", certfile="certs/server.crt", - ca_certs="certs/client.crt", server_side=True) - sa = server.socket.getsockname() - print("Serving HTTPS on", sa[0], "port", sa[1], "for", handler_class, "...") - server.serve_forever() - - if __name__ == '__main__': _main_() diff --git a/tests/dcaegen2/prh-testcases/resources/simulator/AAI_simulator b/tests/dcaegen2/prh-testcases/resources/simulator/AAI_simulator index b44add60..a906bc58 100644 --- a/tests/dcaegen2/prh-testcases/resources/simulator/AAI_simulator +++ b/tests/dcaegen2/prh-testcases/resources/simulator/AAI_simulator @@ -1,14 +1,6 @@ -FROM alpine:3.8 +FROM python:3-alpine -RUN apk add --no-cache python3 && \ - python3 -m ensurepip && \ - rm -r /usr/lib/python*/ensurepip && \ - pip3 install --upgrade pip setuptools && \ - if [ ! -e /usr/bin/pip ]; then ln -s pip3 /usr/bin/pip ; fi && \ - if [[ ! -e /usr/bin/python ]]; then ln -sf /usr/bin/python3 /usr/bin/python; fi && \ - rm -r /root/.cache - -ADD AAI.py / +ADD AAI.py httpServerLib.py / COPY certs/* /certs/ CMD [ "python", "./AAI.py" ] diff --git a/tests/dcaegen2/prh-testcases/resources/simulator/DMaaP.py b/tests/dcaegen2/prh-testcases/resources/simulator/DMaaP.py index 85c36109..bb37ddd0 100644 --- a/tests/dcaegen2/prh-testcases/resources/simulator/DMaaP.py +++ b/tests/dcaegen2/prh-testcases/resources/simulator/DMaaP.py @@ -1,64 +1,67 @@ -from http.server import BaseHTTPRequestHandler -from http.server import HTTPServer import re -import sys +import time +from http.server import BaseHTTPRequestHandler +import httpServerLib posted_event_from_prh = b'Empty' received_event_to_get_method = b'Empty' -class DMaaPHandler(BaseHTTPRequestHandler): +class DmaapSetup(BaseHTTPRequestHandler): def do_PUT(self): if re.search('/set_get_event', self.path): global received_event_to_get_method content_length = int(self.headers['Content-Length']) received_event_to_get_method = self.rfile.read(content_length) - _header_200_and_json(self) - + httpServerLib.header_200_and_json(self) + + return + + def do_GET(self): + if re.search('/events/pnfReady', self.path): + httpServerLib.header_200_and_json(self) + self.wfile.write(posted_event_from_prh) + + return + + def do_POST(self): + if re.search('/reset', self.path): + global posted_event_from_prh + global received_event_to_get_method + posted_event_from_prh = b'Empty' + received_event_to_get_method = b'Empty' + httpServerLib.header_200_and_json(self) + return + +class DMaaPHandler(BaseHTTPRequestHandler): + def do_POST(self): if re.search('/events/unauthenticated.PNF_READY', self.path): global posted_event_from_prh content_length = int(self.headers['Content-Length']) posted_event_from_prh = self.rfile.read(content_length) - _header_200_and_json(self) - + httpServerLib.header_200_and_json(self) + return def do_GET(self): if re.search('/events/unauthenticated.VES_PNFREG_OUTPUT/OpenDcae-c12/c12', self.path): - _header_200_and_json(self) + httpServerLib.header_200_and_json(self) self.wfile.write(received_event_to_get_method) - elif re.search('/events/pnfReady', self.path): - _header_200_and_json(self) - self.wfile.write(posted_event_from_prh) return -def _header_200_and_json(self): - self.send_response(200) - self.send_header('Content-Type', 'application/json') - self.end_headers() - - -def _main_(handler_class=DMaaPHandler, server_class=HTTPServer, protocol="HTTP/1.0"): - - if sys.argv[1:]: - port = int(sys.argv[1]) - else: - port = 2222 - - server_address = ('', port) - +def _main_(handler_class=DMaaPHandler, protocol="HTTP/1.0"): handler_class.protocol_version = protocol - httpd = server_class(server_address, handler_class) - - sa = httpd.socket.getsockname() - print("Serving HTTP on", sa[0], "port", sa[1], "...") - httpd.serve_forever() + httpServerLib.start_http_endpoint(2222, DMaaPHandler) + httpServerLib.start_https_endpoint(2223, DMaaPHandler) + httpServerLib.start_http_endpoint(2224, DmaapSetup) + while 1: + time.sleep(10) if __name__ == '__main__': diff --git a/tests/dcaegen2/prh-testcases/resources/simulator/DMaaP_simulator b/tests/dcaegen2/prh-testcases/resources/simulator/DMaaP_simulator index 9cf21dc9..8139fc33 100644 --- a/tests/dcaegen2/prh-testcases/resources/simulator/DMaaP_simulator +++ b/tests/dcaegen2/prh-testcases/resources/simulator/DMaaP_simulator @@ -1,15 +1,6 @@ -FROM alpine:3.8 +FROM python:3-alpine -RUN apk add --no-cache python3 && \ - python3 -m ensurepip && \ - rm -r /usr/lib/python*/ensurepip && \ - pip3 install --upgrade pip setuptools && \ - if [ ! -e /usr/bin/pip ]; then ln -s pip3 /usr/bin/pip ; fi && \ - if [[ ! -e /usr/bin/python ]]; then ln -sf /usr/bin/python3 /usr/bin/python; fi && \ - rm -r /root/.cache - -ADD DMaaP.py / - -EXPOSE 2222 +ADD DMaaP.py httpServerLib.py / +COPY certs/* /certs/ CMD [ "python", "./DMaaP.py" ] diff --git a/tests/dcaegen2/prh-testcases/resources/simulator/httpServerLib.py b/tests/dcaegen2/prh-testcases/resources/simulator/httpServerLib.py new file mode 100644 index 00000000..dcfdb7ca --- /dev/null +++ b/tests/dcaegen2/prh-testcases/resources/simulator/httpServerLib.py @@ -0,0 +1,34 @@ +import _thread +import ssl +from http.server import HTTPServer + + +def header_200_and_json(self): + self.send_response(200) + self.send_header('Content-Type', 'application/json') + self.end_headers() + + +def start_http_endpoint(port, handler_class): + _thread.start_new_thread(init_http_endpoints, (port, handler_class)) + + +def start_https_endpoint(port, handler_class, keyfile="certs/server.key", + certfile="certs/server.crt", ca_certs="certs/client.crt"): + _thread.start_new_thread(init_https_endpoints, (port, handler_class, keyfile, certfile, ca_certs)) + + +def init_http_endpoints(port, handler_class, server_class=HTTPServer): + server = server_class(('', port), handler_class) + sa = server.socket.getsockname() + print("Serving HTTP on", sa[0], "port", sa[1], "for", handler_class, "...") + server.serve_forever() + + +def init_https_endpoints(port, handler_class, keyfile, certfile, ca_certs, server_class=HTTPServer): + server = server_class(('', port), handler_class) + server.socket = ssl.wrap_socket(server.socket, keyfile=keyfile, certfile=certfile, + ca_certs=ca_certs, server_side=True) + sa = server.socket.getsockname() + print("Serving HTTPS on", sa[0], "port", sa[1], "for", handler_class, "...") + server.serve_forever() diff --git a/tests/dcaegen2/prh-testcases/ssl_prh_tests.robot b/tests/dcaegen2/prh-testcases/ssl_prh_tests.robot index 3fd0faf1..49d2c45a 100644 --- a/tests/dcaegen2/prh-testcases/ssl_prh_tests.robot +++ b/tests/dcaegen2/prh-testcases/ssl_prh_tests.robot @@ -1,31 +1,27 @@ *** Settings *** Documentation Integration tests for PRH. -... PRH receive events from DMaaP and produce or not PNF_READY notification depends on required fields in received event. -Suite Setup Run keywords Create header Create sessions +... PRH receive events from DMaaP and produce or not PNF_READY notification depends on required fields in received event. PRH comunicates with AAI and DMaaP through SSL +Suite Setup Run keywords Create header AND Create sessions AND Ensure Container Is Running ssl_prh AND Ensure Container Is Exited prh +Suite Teardown Ensure Container Is Running prh +Test Teardown Reset Simulators Library resources/PrhLibrary.py Resource resources/prh_library.robot Resource ../../common.robot *** Variables *** -${DMAAP_SIMULATOR_URL} http://${DMAAP_SIMULATOR} +${DMAAP_SIMULATOR_SETUP_URL} http://${DMAAP_SIMULATOR_SETUP} ${AAI_SIMULATOR_SETUP_URL} http://${AAI_SIMULATOR_SETUP} ${EVENT_WITH_ALL_VALID_REQUIRED_FIELDS} %{WORKSPACE}/tests/dcaegen2/prh-testcases/assets/json_events/event_with_all_fields.json ${EVENT_WITH_IPV4} %{WORKSPACE}/tests/dcaegen2/prh-testcases/assets/json_events/event_with_IPV4.json ${EVENT_WITH_IPV6} %{WORKSPACE}/tests/dcaegen2/prh-testcases/assets/json_events/event_with_IPV6.json -${EVENT_WITH_MISSING_IPV4_AND_IPV6} %{WORKSPACE}/tests/dcaegen2/prh-testcases/assets/json_events/event_with_missing_IPV4_and_IPV6.json -${EVENT_WITH_MISSING_SOURCENAME} %{WORKSPACE}/tests/dcaegen2/prh-testcases/assets/json_events/event_with_missing_sourceName.json -${EVENT_WITH_MISSING_SOURCENAME_AND_IPV4} %{WORKSPACE}/tests/dcaegen2/prh-testcases/assets/json_events/event_with_missing_sourceName_and_IPV4.json -${EVENT_WITH_MISSING_SOURCENAME_AND_IPV6} %{WORKSPACE}/tests/dcaegen2/prh-testcases/assets/json_events/event_with_missing_sourceName_and_IPV6.json -${EVENT_WITH_MISSING_SOURCENAME_IPV4_AND_IPV6} %{WORKSPACE}/tests/dcaegen2/prh-testcases/assets/json_events/event_with_missing_sourceName_IPV4_and_IPV6.json ${EVENT_WITHOUT_IPV6_FILED} %{WORKSPACE}/tests/dcaegen2/prh-testcases/assets/json_events/event_without_IPV6_field.json -${Not_json_format} %{WORKSPACE}/tests/dcaegen2/prh-testcases/assets/json_events/not_json_format.json *** Test Cases *** -#Valid DMaaP event can be converted to PNF_READY notification with ssl connection to AAI -# [Documentation] PRH get valid event from DMaaP with required fields - PRH produce PNF_READY notification -# [Tags] PRH Valid event -# [Template] Valid event processing -# ${EVENT_WITH_ALL_VALID_REQUIRED_FIELDS} -# ${EVENT_WITH_IPV4} -# ${EVENT_WITH_IPV6} -# ${EVENT_WITHOUT_IPV6_FILED} +Valid DMaaP event can be converted to PNF_READY notification with ssl connection to AAI + [Documentation] PRH get valid event from DMaaP with required fields - PRH produce PNF_READY notification + [Tags] PRH Valid event + [Template] Valid event processing + ${EVENT_WITH_ALL_VALID_REQUIRED_FIELDS} + ${EVENT_WITH_IPV4} + ${EVENT_WITH_IPV6} + ${EVENT_WITHOUT_IPV6_FILED} diff --git a/tests/multicloud-azure/provision/sanity_test_multicloud.robot b/tests/multicloud-azure/provision/sanity_test_multicloud.robot new file mode 100644 index 00000000..7cdd70f0 --- /dev/null +++ b/tests/multicloud-azure/provision/sanity_test_multicloud.robot @@ -0,0 +1,22 @@ +*** settings *** +Library Collections +Library RequestsLibrary +Library OperatingSystem +Library json + +*** Variables *** +@{return_ok_list}= 200 201 202 +${queryswagger_ocata_url} /api/multicloud-azure/v0/swagger.json + + +*** Test Cases *** +OcataSwaggerTest + [Documentation] query swagger info rest test + ${headers} Create Dictionary Content-Type=application/json Accept=application/json + Create Session web_session http://${SERVICE_IP}:${SERVICE_PORT} headers=${headers} + ${resp}= Get Request web_session ${queryswagger_ocata_url} + ${response_code}= Convert To String ${resp.status_code} + List Should Contain Value ${return_ok_list} ${response_code} + ${response_json} json.loads ${resp.content} + ${swagger_version}= Convert To String ${response_json['swagger']} + Should Be Equal ${swagger_version} 2.0 diff --git a/tests/vid/healthCheck/test1.robot b/tests/vid/healthCheck/test1.robot index 8f9448d8..4f1aabd3 100644 --- a/tests/vid/healthCheck/test1.robot +++ b/tests/vid/healthCheck/test1.robot @@ -7,9 +7,9 @@ Library json *** Test Cases *** Get Requests health check ok [Tags] get - CreateSession vid http://localhost:8080 + CreateSession vid http://${VID_IP}:8080 ${headers}= Create Dictionary Accept=application/json Content-Type=application/json - ${resp}= Get Request vid /vid/healthCheck headers=&{headers} + ${resp}= Get Request vid /vid/healthCheck headers=${headers} Should Be Equal As Strings ${resp.status_code} 200 Log to console statusCode: ${resp.json()['statusCode']} Should Be Equal As Strings ${resp.json()['statusCode']} 200 diff --git a/tests/vid/https-connection/__init__.robot b/tests/vid/https-connection/__init__.robot index e69de29b..dcb082f1 100644 --- a/tests/vid/https-connection/__init__.robot +++ b/tests/vid/https-connection/__init__.robot @@ -0,0 +1,2 @@ +*** Settings *** +Documentation VID - Checking connection to other component using HTTPS diff --git a/tests/vid/https-connection/keywords.py b/tests/vid/https-connection/keywords.py deleted file mode 100755 index 85bca101..00000000 --- a/tests/vid/https-connection/keywords.py +++ /dev/null @@ -1,125 +0,0 @@ -import ast - -import requests -from assertpy import assert_that -from robot.api import logger -from robot.api.deco import keyword - -JSESSIONID_COOKIE = "JSESSIONID" - -_vid_to_so_request_details = { - "requestDetails": { - "cloudConfiguration": { - "lcpCloudRegionId": "RegionOne", - "tenantId": "982c540f6e69488eb6be5664255e00c0" - }, - "modelInfo": { - "modelInvariantId": "41b3c314-dfab-4501-9c5e-1c9fe5d8e151", - "modelName": "SoWs1..base_ws..module-0", - "modelType": "vfModule", - "modelVersion": "1", - "modelVersionId": "7ea96ae9-9eac-4eaa-882e-077478a6c44a" - }, - "relatedInstanceList": [{ - "relatedInstance": { - "instanceId": "0d8a98d8-d7ca-4c26-b7ab-81d3729e3b6c", - "modelInfo": { - "modelInvariantId": "a4413616-cf96-4615-a94e-0dc5a6a65430", - "modelName": "SC_WS_SW_2", - "modelType": "service", - "modelVersion": "3.0", - "modelVersionId": "0fdaaf44-3c6c-4d81-9c57-b2ce7224dbb9" - } - } - }, - { - "relatedInstance": { - "instanceId": "61c19619-2714-46f8-90c9-39734e4f545f", - "modelInfo": { - "modelCustomizationName": "SO_WS_1 0", - "modelInvariantId": "3b2c9dcb-6ef8-4c3c-8d5b-43d5776f7110", - "modelName": "SO_WS_1", - "modelType": "vnf", - "modelVersion": "1.0", - "modelVersionId": "0fdaaf44-3c6c-4d81-9c57-b2ce7224dbb9" - } - } - } - ], - "requestInfo": { - "source": "VID", - "suppressRollback": False, - "requestorId": "az2016", - "instanceName": "SC_WS_VNF_1_2" - }, - "requestParameters": { - "controllerType": "SDNC", - "userParams": [] - } - - } -} - -_expected_so_response = { - "status": 202, - "entity": { - "requestReferences": { - "instanceId": "fffcbb6c-1983-42df-9ca8-89ae8b3a46c1", - "requestId": "b2197d7e-3a7d-410e-82ba-7b7e8191bc46" - } - } -} - - -def _extract_cookie_from_headers(headers): - for i in headers["Set-Cookie"].split(";"): - if JSESSIONID_COOKIE in i: - return i - raise RuntimeError("No cookie when logging in to VID") - - -def _log_request(response): - logger.console( - "\n=========\n" - "Performing request to : {} \nBODY: {}\nHEADERS: {}" - .format(str(response.request.url), str(response.request.body), str(response.request.headers))) - logger.console( - "---------\n" - "Got response\n BODY: {} \n HEADERS: {}" - "\n=========\n".format(str(response.headers), str(response.content))) - - -@keyword('Login To VID') -def login_to_vid(): - headers = {'User-Agent': 'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:61.0) Gecko/20100101 Firefox/61.0', - 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8', - 'Accept-Language': 'pl,en-US;q=0.7,en;q=0.3', - 'Accept-Encoding': 'gzip, deflate', 'Referer': 'http://localhost:8080/vid/login.htm', - 'Content-Type': 'application/x-www-form-urlencoded', - 'Content-Length': '36', - 'Cookie': 'JSESSIONID=1B4AF817AA4BCB87C07BB5B49EFE8526', - 'Connection': 'keep-alive', - 'Upgrade-Insecure-Requests': '1'} - response = requests.post("https://localhost:8443/vid/login_external", data="loginId=demo&password=Kp8bJ4SXszM0WX", - headers=headers, allow_redirects=False, verify=False) - logger.console("Performing login") - _log_request(response) - return _extract_cookie_from_headers(response.headers) - - -@keyword('Send create VF module instance request to VID') -def send_create_vfmodule_instance_request_to_vid(jsession_cookie): - response = requests.post( - "https://localhost:8443/vid/mso/mso_create_vfmodule_instance/0d8a98d8-d7ca-4c26-b7ab-81d3729e3b6c/vnfs/61c19619-2714-46f8-90c9-39734e4f545f ", - headers={"Cookie": jsession_cookie}, json=_vid_to_so_request_details, verify=False) - content = ast.literal_eval(response.content) - logger.console("Triggering VF module instance creation") - _log_request(response) - return content - - -@keyword('Response should contain valid entity') -def expect_response_from_so_was_correctly_propageted(content): - logger.console("\nActual entity" + str(content['entity'])) - logger.console("Expected entity" + str(_expected_so_response)) - assert_that(content['entity']).is_equal_to(_expected_so_response) diff --git a/tests/vid/https-connection/test1.robot b/tests/vid/https-connection/test1.robot index 2173757a..a7f6c4b9 100644 --- a/tests/vid/https-connection/test1.robot +++ b/tests/vid/https-connection/test1.robot @@ -1,16 +1,29 @@ *** Settings *** -Library keywords.py -Library Collections +Library SeleniumLibrary +Library RequestsLibrary +Library OperatingSystem +Library json +Resource ../../common.robot +Resource ../resources/keywords/scaleout_vid_keywords.robot + *** Variables *** +${VID_TEST_ASSET_DIR} %{WORKSPACE}/tests/vid/resources/simulators/test_data_assets +${EXPECTED_SO_RESPONSES_FILEPATH} ${VID_TEST_ASSET_DIR}/expected_so_responses.json +${EXPECTED_SO_REQUESTS_FILEPATH} ${VID_TEST_ASSET_DIR}/expected_so_requests.json +${SO_SIMULATOR_BASE_URL} http://${SO_SIMULATOR_IP}:8443 +${VID_HTTP_BASE_URL} http://${VID_IP}:8080 +${VID_SCALEOUT_ENDPOINT} vid/mso/mso_create_vfmodule_instance/0d8a98d8-d7ca-4c26-b7ab-81d3729e3b6c/vnfs/61c19619-2714-46f8-90c9-39734e4f545f +${VALID_SCALEOUT_REQ_FILEPATH} ${VID_TEST_ASSET_DIR}/vid_create_vfmodule_request.json +${VALID_SCALEOUT_RESP_FILEPATH} ${VID_TEST_ASSET_DIR}/so_action_response.json *** Test Cases *** -Connection to SO is performed using HTTPS - ${cookies}= Login To VID - ${response}= Send create VF module instance request to VID ${cookies} - Dictionary Should Contain Item ${response} status 200 - Response should contain valid entity ${response} - - -*** Keywords *** +Triggering create vfmodule operation in SO is performed using HTTPS + Setup Expected Data In SO Simulator ${EXPECTED_SO_RESPONSES_FILEPATH} ${SO_SIMULATOR_BASE_URL} setResponse + ${jsessionIdCookie}= Login to VID Internally ${VID_HTTP_BASE_URL}/vid/login.htm demo Kp8bJ4SXszM0WX + Log to console loginResponse: ${jsessionIdCookie} + ${soExpectedJsonResp}= json_from_file ${VALID_SCALEOUT_RESP_FILEPATH} + ${soResponse}= Send Post request from VID FE ${VID_HTTP_BASE_URL} ${VID_SCALEOUT_ENDPOINT} ${VALID_SCALEOUT_REQ_FILEPATH} ${VALID_SCALEOUT_RESP_FILEPATH} ${jsessionIdCookie} + Dictionaries Should Be Equal ${soExpectedJsonResp} ${soResponse.json()['entity']} + [Teardown] Close Browser \ No newline at end of file diff --git a/tests/vid/login/test1.robot b/tests/vid/login/test1.robot index acb6aae8..2c39b503 100644 --- a/tests/vid/login/test1.robot +++ b/tests/vid/login/test1.robot @@ -40,7 +40,7 @@ Login To VID GUI Click Button xpath=//input[@id='loginBtn'] Wait Until Page Contains Welcome to VID ${GLOBAL_SELENIUM_BROWSER_WAIT_TIMEOUT} Log Logged in to ${VID_ENDPOINT}${VID_ENV} - + [Teardown] Close Browser *** Keywords *** Setup Browser diff --git a/tests/vid/resources/docker-compose.yml b/tests/vid/resources/docker-compose.yml index 4aecb6ab..5f2c0fec 100644 --- a/tests/vid/resources/docker-compose.yml +++ b/tests/vid/resources/docker-compose.yml @@ -14,7 +14,7 @@ services: - vid-mariadb:vid-mariadb-docker-instance vid-mariadb: - image: mariadb:10 + image: nexus3.onap.org:10001/library/mariadb:10 environment: - MYSQL_DATABASE=vid_openecomp_epsdk - MYSQL_USER=vidadmin @@ -28,7 +28,7 @@ services: so-simulator: build: context: simulators - dockerfile: SO-simulator + dockerfile: Dockerfile ports: - "8444:8443" container_name: so-simulator \ No newline at end of file diff --git a/tests/vid/resources/keywords/scaleout_vid_keywords.robot b/tests/vid/resources/keywords/scaleout_vid_keywords.robot new file mode 100644 index 00000000..0b96d45d --- /dev/null +++ b/tests/vid/resources/keywords/scaleout_vid_keywords.robot @@ -0,0 +1,45 @@ +*** Settings *** +Documentation Collection of util keywords for managing SO simulator +Library SeleniumLibrary +Library RequestsLibrary +Library OperatingSystem +Library Collections +Library json +Resource ../../../common.robot + + +*** Keywords *** +Setup Expected Data In SO Simulator + [Documentation] Setup data to be returned by simulator + [Arguments] ${expectedResponseFilePath} ${simulatorBaseUrl} ${simulatorPutEndpoint} + ${expectedDataToReturn}= json_from_file ${expectedResponseFilePath} + ${headers}= Create Dictionary Content-Type=application/json + ${session}= Create Session so_simulator ${simulatorBaseUrl} + ${resp}= Put Request so_simulator uri=/${simulatorPutEndpoint} data=${expectedDataToReturn} headers=${headers} + Should Be Equal As Strings ${resp.status_code} 200 + Log to console Successfully initialized so-simulator: status code ${resp.status_code} + + +Send Post request from VID FE + [Documentation] Imitates VID UI. This keyword is designed for imitating calls from VID UI to VID BE + [Arguments] ${vidBaseUrl} ${endpoint} ${requestFilePath} ${expectedResponseFilePath} ${cookie} + ${vidRequest}= json_from_file ${requestFilePath} + ${headers}= Create Dictionary Content-Type=application/json Cookie=${cookie} + ${session}= Create Session vid ${vidBaseUrl} + ${resp}= Post Request vid uri=/${endpoint} data=${vidRequest} headers=${headers} + Should Be Equal As Strings ${resp.status_code} 200 + Log to console ${resp.content} + [Return] ${resp} + + +Login to VID Internally + [Arguments] ${url} ${username} ${password} + [Documentation] Login using Autn + Open browser ${url} chrome + Input Text id=loginId ${username} + Input Password id=password ${password} + Click Element id=loginBtn + ${cookie_value} Get Cookie Value JSESSIONID + [Return] JSESSIONID=${cookie_value} + + diff --git a/tests/vid/resources/simulators/Dockerfile b/tests/vid/resources/simulators/Dockerfile new file mode 100644 index 00000000..5aa13925 --- /dev/null +++ b/tests/vid/resources/simulators/Dockerfile @@ -0,0 +1,8 @@ +FROM frolvlad/alpine-python3 + +COPY SO.py / +ADD ./test_data_assets/ / + +EXPOSE 8443 + +CMD [ "python", "./SO.py", "expected_so_requests.json", "expected_so_responses.json" ] diff --git a/tests/vid/resources/simulators/SO-simulator b/tests/vid/resources/simulators/SO-simulator deleted file mode 100644 index 54587665..00000000 --- a/tests/vid/resources/simulators/SO-simulator +++ /dev/null @@ -1,8 +0,0 @@ -FROM frolvlad/alpine-python3 - -ADD SO.py / -ADD so_post_response.json / - -EXPOSE 8443 - -CMD [ "python", "./SO.py" ] \ No newline at end of file diff --git a/tests/vid/resources/simulators/SO.py b/tests/vid/resources/simulators/SO.py index edc15f62..c1199390 100644 --- a/tests/vid/resources/simulators/SO.py +++ b/tests/vid/resources/simulators/SO.py @@ -1,45 +1,115 @@ +# ============LICENSE_START======================================================= +# INTEGRATION CSIT +# ================================================================================ +# Copyright (C) 2018 Nokia 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. +# ============LICENSE_END========================================================= + +import json import logging +from functools import partial +from sys import argv from http.server import BaseHTTPRequestHandler, HTTPServer DEFAULT_PORT = 8443 class SOHandler(BaseHTTPRequestHandler): + def __init__(self, expected_requests, expected_responses, *args, **kwargs): - def __init__(self, request, client_address, server): - self.response_on_get = self._read_on_get_response() - super().__init__(request, client_address, server) + self._expected_requests = expected_requests + self._expected_responses = expected_responses + super().__init__(*args, **kwargs) def do_POST(self): - logging.info('POST called') + logging.info( + 'POST called. Expected POST REQUEST: ' + json.dumps( + self._expected_requests["post"]) + '\nExpected POST response: ' + + json.dumps(self._expected_responses["post"])) self.send_response(200) self._set_headers() - self.wfile.write(self.response_on_get.encode("utf-8")) + self.wfile.write(json.dumps(self._expected_responses["post"]).encode("utf-8")) return def do_GET(self): - logging.info('GET called') + logging.info( + 'GET called. Expected GET REQUEST: ' + json.dumps( + self._expected_requests["get"]) + '\nExpected GET response: ' + + json.dumps(self._expected_responses["get"])) self.send_response(200) self._set_headers() - self.wfile.write(self.response_on_get.encode("utf-8")) - return + self.wfile.write(json.dumps(self._expected_responses["get"]).encode("utf-8")) + return self._expected_responses["get"] + + def do_PUT(self): + request_body_json = self._get_request_body() + if request_body_json is not None: + self._apply_expected_data(request_body_json) + logging.info("EXPECTED RESPONSES: " + str(self._expected_responses)) + logging.info("EXPECTED REQUESTS: " + str(self._expected_requests)) + response_status = 200 + else: + response_status = 400 + self.send_response(response_status) + self._set_headers() + + def _get_request_body(self): + content_len = int(self.headers['Content-Length'], 0) + parsed_req_body = None + if content_len > 0: + body = self.rfile.read(content_len) + body_decoded = body.decode('utf8') + logging.info("BODY: %s type: %s body decoded: %s type: %s", str(body), type(body), str(body_decoded), + type(body_decoded)) + parsed_req_body = json.loads(body_decoded) + return parsed_req_body + + def _apply_expected_data(self, request_body_json): + if self.path == '/setResponse': + logging.info("IN PUT /setResponse: " + str(request_body_json)) + print("TYPE: %s and text: %s", type(request_body_json), str(request_body_json)) + self._expected_responses.update(request_body_json) + print("TYPE: %s", type(request_body_json)) + elif self.path == '/setRequest': + logging.info("IN PUT /setRequest: " + str(request_body_json)) + self._expected_requests.update(request_body_json) def _set_headers(self): self.send_header('Content-Type', 'application/json') self.end_headers() + +class JsonFileToDictReader(object): + @staticmethod - def _read_on_get_response(): - with open('so_post_response.json', 'r') as file: - return file.read() + def read_expected_test_data(expected_responses_filename): + with open(expected_responses_filename, 'r') as file: + return json.load(file) -if __name__ == '__main__': +def init_so_simulator(): + expected_so_requests = JsonFileToDictReader.read_expected_test_data(argv[1]) + expected_so_responses = JsonFileToDictReader.read_expected_test_data(argv[2]) logging.basicConfig(filename='output.log', level=logging.INFO) - SOHandler.protocol_version = "HTTP/1.0" - - httpd = HTTPServer(('', DEFAULT_PORT), SOHandler) + handler = partial(SOHandler, expected_so_requests, expected_so_responses) + handler.protocol_version = "HTTP/1.0" + httpd = HTTPServer(('', DEFAULT_PORT), handler) logging.info("serving on: " + str(httpd.socket.getsockname())) httpd.serve_forever() + + +if __name__ == '__main__': + init_so_simulator() diff --git a/tests/vid/resources/simulators/test_data_assets/expected_so_requests.json b/tests/vid/resources/simulators/test_data_assets/expected_so_requests.json new file mode 100644 index 00000000..214fa6f0 --- /dev/null +++ b/tests/vid/resources/simulators/test_data_assets/expected_so_requests.json @@ -0,0 +1,57 @@ +{ + "get": { + "get_request": "accepted" + }, + "post": { + "requestDetails": { + "cloudConfiguration": { + "lcpCloudRegionId": "RegionOne", + "tenantId": "982c540f6e69488eb6be5664255e00c0" + }, + "modelInfo": { + "modelInvariantId": "41b3c314-dfab-4501-9c5e-1c9fe5d8e151", + "modelName": "SoWs1..base_ws..module-0", + "modelType": "vfModule", + "modelVersion": "1", + "modelVersionId": "7ea96ae9-9eac-4eaa-882e-077478a6c44a" + }, + "relatedInstanceList": [{ + "relatedInstance": { + "instanceId": "0d8a98d8-d7ca-4c26-b7ab-81d3729e3b6c", + "modelInfo": { + "modelInvariantId": "a4413616-cf96-4615-a94e-0dc5a6a65430", + "modelName": "SC_WS_SW_2", + "modelType": "service", + "modelVersion": "3.0", + "modelVersionId": "0fdaaf44-3c6c-4d81-9c57-b2ce7224dbb9" + } + } + }, + { + "relatedInstance": { + "instanceId": "61c19619-2714-46f8-90c9-39734e4f545f", + "modelInfo": { + "modelCustomizationName": "SO_WS_1 0", + "modelInvariantId": "3b2c9dcb-6ef8-4c3c-8d5b-43d5776f7110", + "modelName": "SO_WS_1", + "modelType": "vnf", + "modelVersion": "1.0", + "modelVersionId": "0fdaaf44-3c6c-4d81-9c57-b2ce7224dbb9" + } + } + } + ], + "requestInfo": { + "source": "VID", + "suppressRollback": "false", + "requestorId": "az2016", + "instanceName": "SC_WS_VNF_1_2" + }, + "requestParameters": { + "controllerType": "SDNC", + "userParams": [] + } + + } + } +} \ No newline at end of file diff --git a/tests/vid/resources/simulators/test_data_assets/expected_so_responses.json b/tests/vid/resources/simulators/test_data_assets/expected_so_responses.json new file mode 100644 index 00000000..1b735225 --- /dev/null +++ b/tests/vid/resources/simulators/test_data_assets/expected_so_responses.json @@ -0,0 +1,14 @@ +{ + "get": { + "get_response": "accepted" + }, + "post": { + "status": 202, + "entity": { + "requestReferences": { + "instanceId": "fffcbb6c-1983-42df-9ca8-89ae8b3a46c1", + "requestId": "b2197d7e-3a7d-410e-82ba-7b7e8191bc46" + } + } + } +} \ No newline at end of file diff --git a/tests/vid/resources/simulators/test_data_assets/so_action_response.json b/tests/vid/resources/simulators/test_data_assets/so_action_response.json new file mode 100644 index 00000000..391231dc --- /dev/null +++ b/tests/vid/resources/simulators/test_data_assets/so_action_response.json @@ -0,0 +1,9 @@ +{ + "status": 202, + "entity": { + "requestReferences": { + "instanceId": "fffcbb6c-1983-42df-9ca8-89ae8b3a46c1", + "requestId": "b2197d7e-3a7d-410e-82ba-7b7e8191bc46" + } + } +} \ No newline at end of file diff --git a/tests/vid/resources/simulators/test_data_assets/so_response_for_invalid_request.json b/tests/vid/resources/simulators/test_data_assets/so_response_for_invalid_request.json new file mode 100644 index 00000000..477de145 --- /dev/null +++ b/tests/vid/resources/simulators/test_data_assets/so_response_for_invalid_request.json @@ -0,0 +1,11 @@ +{ + "status": 400, + "entity": { + "requestError": { + "serviceException": { + "messageId": "SVC0002", + "text": "Error mapping request: Unrecognized field \"configurationParameters\" (class org.onap.so.serviceinstancebeans.ServiceInstancesRequest), not marked as ignorable (8 known properties: \"configurationId\", \"requestDetails\", \"serviceInstanceId\", \"vfModuleInstanceId\", \"correlationId\", \"vnfInstanceId\", \"volumeGroupInstanceId\", \"networkInstanceId\"])\n at [Source: {\"configurationParameters\":[],\"requestDetails\":{\"cloudConfiguration\":{\"lcpCloudRegionId\":\"RegionOne\",\"tenantId\":\"982c540f6e69488eb6be5664255e00c0\"},\"modelInfo\":{\"modelInvariantId\":\"41b3c314-dfab-4501-9c5e-1c9fe5d8e151\",\"modelName\":\"SoWs1..base_ws..module-0\",\"modelType\":\"vfModule\",\"modelVersion\":\"1\",\"modelVersionId\":\"7ea96ae9-9eac-4eaa-882e-077478a6c44a\"},\"relatedInstanceList\":[{\"relatedInstance\":{\"instanceId\":\"0d8a98d8-d7ca-4c26-b7ab-81d3729e3b6c\",\"modelInfo\":{\"modelInvariantId\":\"a4413616-cf96-4615-a94e-0dc5a6a65430\",\"modelName\":\"SC_WS_SW_2\",\"modelType\":\"service\",\"modelVersion\":\"3.0\",\"modelVersionId\":\"00e0bb964-e687-4439-9a9e-de9cd1ff5367\"}}},{\"relatedInstance\":{\"instanceId\":\"61c19619-2714-46f8-90c9-39734e4f545f\",\"modelInfo\":{\"modelCustomizationName\":\"SO_WS_1 0\",\"modelInvariantId\":\"3b2c9dcb-6ef8-4c3c-8d5b-43d5776f7110\",\"modelName\":\"SO_WS_1\",\"modelType\":\"vnf\",\"modelVersion\":\"1.0\",\"modelVersionId\":\"0fdaaf44-3c6c-4d81-9c57-b2ce7224dbb9\"}}}],\"requestInfo\":{\"source\":\"VID\",\"suppressRollback\":false,\"requestorId\":\"az2016\",\"instanceName\":\"SC_WS_VNF_1_2\"},\"requestParameters\":{\"controllerType\":\"SDNC\",\"userParams\":[]}}}; line: 1, column: 29] (through reference chain: org.onap.so.serviceinstancebeans.ServiceInstancesRequest[\"configurationParameters\"])" + } + } + } +} \ No newline at end of file diff --git a/tests/vid/resources/simulators/test_data_assets/vid_create_vfmodule_request.json b/tests/vid/resources/simulators/test_data_assets/vid_create_vfmodule_request.json new file mode 100644 index 00000000..7f0b6eb0 --- /dev/null +++ b/tests/vid/resources/simulators/test_data_assets/vid_create_vfmodule_request.json @@ -0,0 +1,52 @@ +{ + "requestDetails": { + "cloudConfiguration": { + "lcpCloudRegionId": "RegionOne", + "tenantId": "982c540f6e69488eb6be5664255e00c0" + }, + "modelInfo": { + "modelInvariantId": "41b3c314-dfab-4501-9c5e-1c9fe5d8e151", + "modelName": "SoWs1..base_ws..module-0", + "modelType": "vfModule", + "modelVersion": "1", + "modelVersionId": "7ea96ae9-9eac-4eaa-882e-077478a6c44a" + }, + "relatedInstanceList": [ + { + "relatedInstance": { + "instanceId": "0d8a98d8-d7ca-4c26-b7ab-81d3729e3b6c", + "modelInfo": { + "modelInvariantId": "a4413616-cf96-4615-a94e-0dc5a6a65430", + "modelName": "SC_WS_SW_2", + "modelType": "service", + "modelVersion": "3.0", + "modelVersionId": "0fdaaf44-3c6c-4d81-9c57-b2ce7224dbb9" + } + } + }, + { + "relatedInstance": { + "instanceId": "61c19619-2714-46f8-90c9-39734e4f545f", + "modelInfo": { + "modelCustomizationName": "SO_WS_1 0", + "modelInvariantId": "3b2c9dcb-6ef8-4c3c-8d5b-43d5776f7110", + "modelName": "SO_WS_1", + "modelType": "vnf", + "modelVersion": "1.0", + "modelVersionId": "0fdaaf44-3c6c-4d81-9c57-b2ce7224dbb9" + } + } + } + ], + "requestInfo": { + "source": "VID", + "suppressRollback": "false", + "requestorId": "az2016", + "instanceName": "SC_WS_VNF_1_2" + }, + "requestParameters": { + "controllerType": "SDNC", + "userParams": [] + } + } +} \ No newline at end of file diff --git a/tests/vid/resources/simulators/test_data_assets/vid_scaleout_request.json b/tests/vid/resources/simulators/test_data_assets/vid_scaleout_request.json new file mode 100644 index 00000000..70761ec1 --- /dev/null +++ b/tests/vid/resources/simulators/test_data_assets/vid_scaleout_request.json @@ -0,0 +1,23 @@ +{ + "requestDetails":[ + { + "vnfName":"ws-test-0310-8", + "vnfInstanceId":"980fe98e-47f8-4164-862d-4ebb026cec75", + "relatedInstanceList":[ + { + "relatedInstance":{ + "instanceId":"fd84f066-ea75-4b23-acd0-3cf3fce7a99b", + "modelInfo":{ + "modelVersionId":"0e0bb964-e687-4439-9a9e-de9cd1ff5367", + "modelName":"ws-service", + "modelInvariantId":"734f0952-6678-44e7-8918-f9aa4694b687", + "modelType":"service", + "modelVersion":"1.0" + } + } + } + ] + } + ], + "requestType":"VNF Scale Out" +} \ No newline at end of file diff --git a/tests/vid/scaleOut/__init__.robot b/tests/vid/scaleOut/__init__.robot new file mode 100644 index 00000000..540b7cab --- /dev/null +++ b/tests/vid/scaleOut/__init__.robot @@ -0,0 +1,2 @@ +*** Settings *** +Documentation VID - ScaleOut use case diff --git a/tests/vid/scaleOut/scaleout_workflow_test.robot b/tests/vid/scaleOut/scaleout_workflow_test.robot new file mode 100644 index 00000000..3b28c586 --- /dev/null +++ b/tests/vid/scaleOut/scaleout_workflow_test.robot @@ -0,0 +1,32 @@ +*** Settings *** +Library RequestsLibrary +Library OperatingSystem +Library json +Resource ../../common.robot +Resource ../resources/keywords/scaleout_vid_keywords.robot + + +*** Variables *** +${VID_TEST_ASSET_DIR} %{WORKSPACE}/tests/vid/resources/simulators/test_data_assets +${EXPECTED_SO_RESPONSES_FILEPATH} ${VID_TEST_ASSET_DIR}/expected_so_responses.json +${EXPECTED_SO_REQUESTS_FILEPATH} ${VID_TEST_ASSET_DIR}/expected_so_requests.json +${SO_SIMULATOR_BASE_URL} http://${SO_SIMULATOR_IP}:8443 +${VID_HTTP_BASE_URL} http://${VID_IP}:8080 +${VID_SCALEOUT_ENDPOINT} vid/change-management/workflow/ws-test-0310-8 +${VALID_SCALEOUT_REQ_FILEPATH} ${VID_TEST_ASSET_DIR}/vid_scaleout_request.json +${VALID_SCALEOUT_RESP_FILEPATH} ${VID_TEST_ASSET_DIR}/so_action_response.json + + +*** Test Cases *** +Triggering scaleout workflow operation succeeds + Setup Expected Data In SO Simulator ${EXPECTED_SO_RESPONSES_FILEPATH} ${SO_SIMULATOR_BASE_URL} setResponse + ${soExpectedJsonResp}= json_from_file ${VALID_SCALEOUT_RESP_FILEPATH} + ${vidRequest}= json_from_file ${VALID_SCALEOUT_REQ_FILEPATH} + ${headers}= Create Dictionary Content-Type=application/json + ${session}= Create Session alias=vid url=${VID_HTTP_BASE_URL} headers=${headers} + ${resp}= Post Request vid uri=/${VID_SCALEOUT_ENDPOINT} data=${vidRequest} headers=${headers} + Should Be Equal As Strings ${resp.status_code} 200 + Dictionaries Should Be Equal ${soExpectedJsonResp} ${resp.json()['entity']} + + +