From 2ac270a8ee0ecf5357c541deb6e162b4cc26dd98 Mon Sep 17 00:00:00 2001 From: koblosz Date: Tue, 23 Oct 2018 07:32:30 +0200 Subject: Enhance vid CSIT tests, added for scaleout Issue-ID: VID-323 Change-Id: I31ad377ee766eaf66c848ad802c33e21ea1dfe76 Signed-off-by: Sandra Koblosz --- plans/vid/healthCheck/setup.sh | 16 ++- plans/vid/healthCheck/teardown.sh | 2 +- plans/vid/healthCheck/testplan.txt | 1 + scripts/get-instance-ip.sh | 2 +- scripts/vid/start_vid_containers.sh | 17 ++- tests/vid/healthCheck/test1.robot | 4 +- tests/vid/https-connection/__init__.robot | 2 + tests/vid/https-connection/keywords.py | 125 --------------------- tests/vid/https-connection/test1.robot | 33 ++++-- tests/vid/login/test1.robot | 2 +- tests/vid/resources/docker-compose.yml | 4 +- .../resources/keywords/scaleout_vid_keywords.robot | 45 ++++++++ tests/vid/resources/simulators/Dockerfile | 8 ++ tests/vid/resources/simulators/SO-simulator | 8 -- tests/vid/resources/simulators/SO.py | 100 ++++++++++++++--- .../test_data_assets/expected_so_requests.json | 57 ++++++++++ .../test_data_assets/expected_so_responses.json | 14 +++ .../test_data_assets/so_action_response.json | 9 ++ .../so_response_for_invalid_request.json | 11 ++ .../vid_create_vfmodule_request.json | 52 +++++++++ .../test_data_assets/vid_scaleout_request.json | 23 ++++ tests/vid/scaleOut/__init__.robot | 2 + tests/vid/scaleOut/scaleout_workflow_test.robot | 32 ++++++ 23 files changed, 398 insertions(+), 171 deletions(-) delete mode 100755 tests/vid/https-connection/keywords.py create mode 100644 tests/vid/resources/keywords/scaleout_vid_keywords.robot create mode 100644 tests/vid/resources/simulators/Dockerfile delete mode 100644 tests/vid/resources/simulators/SO-simulator create mode 100644 tests/vid/resources/simulators/test_data_assets/expected_so_requests.json create mode 100644 tests/vid/resources/simulators/test_data_assets/expected_so_responses.json create mode 100644 tests/vid/resources/simulators/test_data_assets/so_action_response.json create mode 100644 tests/vid/resources/simulators/test_data_assets/so_response_for_invalid_request.json create mode 100644 tests/vid/resources/simulators/test_data_assets/vid_create_vfmodule_request.json create mode 100644 tests/vid/resources/simulators/test_data_assets/vid_scaleout_request.json create mode 100644 tests/vid/scaleOut/__init__.robot create mode 100644 tests/vid/scaleOut/scaleout_workflow_test.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/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/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']} + + + -- cgit 1.2.3-korg