From b071b23b024a07b5e0d9f1c915468384369e26af Mon Sep 17 00:00:00 2001 From: Mickael JEZEQUEL Date: Fri, 9 Mar 2018 17:44:34 +0100 Subject: Dockerize rest API for ICE tests Change-Id: I8928203bb76a20fb7d10fd05d06151e2c6b7a934 Issue-ID: VNFSDK-214 Signed-off-by: Mickael JEZEQUEL --- docker/README.MD | 24 ++++ docker/pom.xml | 154 +++++++++++++++++++++ docker/src/main/docker/Dockerfile | 29 ++++ docker/src/main/docker/prod_settings.cfg | 8 ++ docker/src/main/docker/run.sh | 7 + ice-server/heat_test/app.py | 53 +++++-- ice-server/heat_test/default_settings.cfg | 13 ++ ice-server/heat_test/default_settings.py | 9 -- ice-server/heat_test/heat_validator.py | 7 +- .../heat_test/test/fixture/heat_template_empty.zip | Bin 0 -> 166 bytes .../heat_test/test/fixture/heat_template_ok.zip | Bin 0 -> 1120 bytes ice-server/heat_test/test/fixture/test.zip | Bin 166 -> 0 bytes pom.xml | 3 +- 13 files changed, 286 insertions(+), 21 deletions(-) create mode 100644 docker/README.MD create mode 100644 docker/pom.xml create mode 100644 docker/src/main/docker/Dockerfile create mode 100644 docker/src/main/docker/prod_settings.cfg create mode 100644 docker/src/main/docker/run.sh create mode 100644 ice-server/heat_test/default_settings.cfg delete mode 100644 ice-server/heat_test/default_settings.py create mode 100644 ice-server/heat_test/test/fixture/heat_template_empty.zip create mode 100644 ice-server/heat_test/test/fixture/heat_template_ok.zip delete mode 100644 ice-server/heat_test/test/fixture/test.zip diff --git a/docker/README.MD b/docker/README.MD new file mode 100644 index 0000000..26a793b --- /dev/null +++ b/docker/README.MD @@ -0,0 +1,24 @@ +Introduction: +============= +This document provides the required steps for : +- generating the docker image of the heat validation rest service +- running the rest server. + +Installation steps: +==================== +Install following software: +- maven +- docker + +Configuration steps: +==================== +you can override the defaults settings (declared in default_settings.cfg and prod_settings.cfg) +by setting the env variable with the appropriate values (see Dockerfile for available ENV vars) + +How to run? +=========== +- make sure that the MSB is running +- build the image : +- ``$ mvn -P docker clean package`` +- run the server in DEBUG mode: +- ``$ docker run --rm --name vnfsdk-ice -d -p 5000:5000 -e DEBUG=True -e MSB_ADDR= -e MSB_PORT=80 onap/vnfsdk/ice`` diff --git a/docker/pom.xml b/docker/pom.xml new file mode 100644 index 0000000..ad876b4 --- /dev/null +++ b/docker/pom.xml @@ -0,0 +1,154 @@ + + + 4.0.0 + + + org.onap.oparent + oparent + 0.1.1 + ../../oparent + + + org.onap.vnfsdk.ice + vnf-sdk-ice-docker + 1.0.0-SNAPSHOT + + ice docker image builder + heat validation docker image builder + pom + + + yyyyMMdd-HHmm + + true + true + true + false + false + + + + docker + + false + + + + + io.fabric8 + docker-maven-plugin + 0.16.7 + + true + 1.23 + ${docker.skip} + + + onap/vnfsdk/ice + ice + + try + ${project.basedir}/src/main/docker + + dir + + middleware-rest + + ${project.basedir}/../ice-server + + requirements.txt + README.MD + + ice-server + + + ${project.basedir}/../ice-server/heat_test + + **/*.pyc + **/__pycache__ + + ice-server/heat_test + + + ${project.basedir}/../validation-scripts + + requirements.txt + README.MD + + validation-scripts + + + ${project.basedir}/../validation-scripts/ice_validator + + **/*.pyc + **/__pycache__ + + validation-scripts/ice_validator + + + + + + + + + + clean-images + pre-clean + + remove + + + true + onap/vnfsdk/ice + + + + + generate-images + generate-sources + + build + + + ${docker.skip.build} + + + + push-images + deploy + + build + push + + + onap/vnfsdk/ice + + + + + + + + + + diff --git a/docker/src/main/docker/Dockerfile b/docker/src/main/docker/Dockerfile new file mode 100644 index 0000000..7b3f033 --- /dev/null +++ b/docker/src/main/docker/Dockerfile @@ -0,0 +1,29 @@ +FROM python:3.6.1 + +ENV ICE_SETTINGS /opt/ice/ice-server/heat_test/prod_settings.cfg +ENV DEBUG False +ENV MSB_ADDR "127.0.0.1" +ENV MSB_PORT 80 + +# add application +COPY maven/ /opt/ice +COPY prod_settings.cfg /opt/ice/ice-server/heat_test/ +COPY run.sh /opt/ice/ice-server/heat_test/ + +EXPOSE 5000 + +# install requirements +# Create the group and user to be used in this container +RUN pip install -r /opt/ice/ice-server/requirements.txt &&\ + pip install -r /opt/ice/validation-scripts/requirements.txt &&\ + pip install dumb-init &&\ + groupadd flaskgroup && useradd -m -g flaskgroup -s /bin/bash flask &&\ + chown -R flask:flaskgroup /opt/ice &&\ + chmod +x /opt/ice/ice-server/heat_test/*.sh + +USER flask +WORKDIR /opt/ice/ice-server/heat_test +# use dumb-init to translate SIGTERM to SIGINT +# this is needed to gracefully stop flask (and unregister service properly) +ENTRYPOINT ["dumb-init", "--rewrite", "15:2", "--"] +CMD ["./run.sh"] diff --git a/docker/src/main/docker/prod_settings.cfg b/docker/src/main/docker/prod_settings.cfg new file mode 100644 index 0000000..f623d76 --- /dev/null +++ b/docker/src/main/docker/prod_settings.cfg @@ -0,0 +1,8 @@ +# ICE production settings +DEBUG = False + +# MSB production settings +MSB_ADDR = "127.0.0.1" +MSB_PORT = "80" +MSB_URL = "http://%s:%s/api/microservices/v1/services" % (MSB_ADDR, MSB_PORT) + diff --git a/docker/src/main/docker/run.sh b/docker/src/main/docker/run.sh new file mode 100644 index 0000000..662c8cf --- /dev/null +++ b/docker/src/main/docker/run.sh @@ -0,0 +1,7 @@ +#!/bin/sh + +sed -i "s/DEBUG =.*/DEBUG = ${DEBUG}/g" ${ICE_SETTINGS} +sed -i "s/MSB_ADDR =.*/MSB_ADDR = \"${MSB_ADDR}\"/g" ${ICE_SETTINGS} +sed -i "s/MSB_PORT =.*/MSB_PORT = \"${MSB_PORT}\"/g" ${ICE_SETTINGS} + +/usr/local/bin/python app.py \ No newline at end of file diff --git a/ice-server/heat_test/app.py b/ice-server/heat_test/app.py index c61150a..97c32a9 100644 --- a/ice-server/heat_test/app.py +++ b/ice-server/heat_test/app.py @@ -1,18 +1,19 @@ #!flask/bin/python -import argparse +import atexit import logging -import requests import connexion +import requests from connexion.resolver import RestyResolver +config = '' def create_app(): logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s') app = connexion.App(__name__, specification_dir='swagger/') # load default config - app.app.config.from_object("default_settings") + app.app.config.from_pyfile("default_settings.cfg") app.app.config.from_envvar('ICE_SETTINGS', silent=True) app.add_api('ice_api.yaml', swagger_ui=app.app.config['DEBUG'], resolver=RestyResolver('ice_validator')) @@ -32,15 +33,51 @@ def start_app(app): logging.info("######################################") logging.info("starting server") logging.info("######################################") + global config + config = app.app.config + msb_register() + atexit.register(msb_unregister) app.run(port=app.app.config['ICE_PORT'], debug=app.app.config['DEBUG']) - # register service in MSB + +def msb_register(): + try: + msb_url = config['MSB_URL'] + ice_json = { + "serviceName": config['ICE_SERVICE_NAME'], + "version": config['ICE_VERSION'], + "url": "/onapapi/ice/v1", + "protocol": "REST", + "visualRange": "1", + "nodes": [ + { + "ip": config['ICE_ADDR'], + "port": config['ICE_PORT'], + "ttl": 0 + } + ] + } + resp = requests.post(msb_url, json=ice_json) + if resp.status_code == 201: + global registered + registered = True + logging.info("registration to '%s' done", msb_url) + else: + logging.info("registration to '%s' failed; status_code = '%s'", msb_url, resp.status_code) + except: + logging.info("registration to '%s' failed", msb_url) + + +def msb_unregister(): try: - msb_url = app.app.config['MSB_URL'] - requests.get(msb_url) - logging.info("registration to %s done", msb_url) + msb_url = "%s/%s/version/%s" % (config['MSB_URL'], config['ICE_SERVICE_NAME'], config['ICE_VERSION']) + resp = requests.delete(msb_url) + if resp.status_code == 200: + logging.info("unregistration from '%s' done", msb_url) + else: + logging.info("unregistration from '%s' failed; status_code = '%s'", msb_url, resp.status_code) except: - logging.info("registration to %s failed", msb_url) + logging.info("unregistration from '%s' failed", msb_url) if __name__ == '__main__': diff --git a/ice-server/heat_test/default_settings.cfg b/ice-server/heat_test/default_settings.cfg new file mode 100644 index 0000000..3721bbf --- /dev/null +++ b/ice-server/heat_test/default_settings.cfg @@ -0,0 +1,13 @@ +# ICE settings +DEBUG = True +ICE_ADDR = "127.0.0.1" +ICE_PORT = 5000 +ICE_SCRIPT_PATH = '../../validation-scripts/ice_validator' +ICE_VERSION = "v1" +ICE_SERVICE_NAME = "vnfsdk-ice" + +# MSB settings +MSB_ADDR = "127.0.0.1" +MSB_PORT = "80" +MSB_URL = "http://%s:%s/api/microservices/v1/services" % (MSB_ADDR, MSB_PORT) + diff --git a/ice-server/heat_test/default_settings.py b/ice-server/heat_test/default_settings.py deleted file mode 100644 index d32d039..0000000 --- a/ice-server/heat_test/default_settings.py +++ /dev/null @@ -1,9 +0,0 @@ -# ICE settings -DEBUG = True -ICE_PORT = 5000 - -# MSB settings -MSB_IP = "127.0.0.1" -MSB_PORT = "80" -MSB_URL = "http://"+MSB_IP+':'+MSB_PORT+"/api/microservices/v1/services" - diff --git a/ice-server/heat_test/heat_validator.py b/ice-server/heat_test/heat_validator.py index 0cc32a1..d76d275 100644 --- a/ice-server/heat_test/heat_validator.py +++ b/ice-server/heat_test/heat_validator.py @@ -7,7 +7,7 @@ import zipfile from io import StringIO import pytest -from flask import (request, jsonify, abort) +from flask import (request, jsonify, abort, current_app) class HeatValidator(object): @@ -49,7 +49,8 @@ class HeatValidator(object): original_output = sys.stdout # Assign StringIO so the output is not sent anymore to the console sys.stdout = StringIO() - exit_code = pytest.main(['../../validation-scripts/ice_validator', + script_path = current_app.config['ICE_SCRIPT_PATH'] + exit_code = pytest.main([script_path, '--resultlog=' + tmp_dir + '/result.txt', '--template-dir', tmp_dir]) with open(tmp_dir + '/result.txt', 'r') as result_file: @@ -62,7 +63,7 @@ class HeatValidator(object): except zipfile.BadZipFile: logging.exception("invalid file") abort(422, {'status': 4, 'message': 'invalid file'}) - except: + except Exception as e: logging.exception("server error on file") abort(500, {'status': 3, 'message': 'server error'}) finally: diff --git a/ice-server/heat_test/test/fixture/heat_template_empty.zip b/ice-server/heat_test/test/fixture/heat_template_empty.zip new file mode 100644 index 0000000..d1e6d99 Binary files /dev/null and b/ice-server/heat_test/test/fixture/heat_template_empty.zip differ diff --git a/ice-server/heat_test/test/fixture/heat_template_ok.zip b/ice-server/heat_test/test/fixture/heat_template_ok.zip new file mode 100644 index 0000000..4e89aba Binary files /dev/null and b/ice-server/heat_test/test/fixture/heat_template_ok.zip differ diff --git a/ice-server/heat_test/test/fixture/test.zip b/ice-server/heat_test/test/fixture/test.zip deleted file mode 100644 index d1e6d99..0000000 Binary files a/ice-server/heat_test/test/fixture/test.zip and /dev/null differ diff --git a/pom.xml b/pom.xml index 0a941ea..f15eca9 100644 --- a/pom.xml +++ b/pom.xml @@ -19,7 +19,7 @@ under the License. org.onap.oparent oparent - 1.0.0-SNAPSHOT + 1.1.0 ../oparent @@ -33,5 +33,6 @@ under the License. validation-scripts ice-server + docker -- cgit 1.2.3-korg