summaryrefslogtreecommitdiffstats
path: root/ice-server/heat_test
diff options
context:
space:
mode:
Diffstat (limited to 'ice-server/heat_test')
-rw-r--r--ice-server/heat_test/__init__.py0
-rw-r--r--ice-server/heat_test/app.py65
-rw-r--r--ice-server/heat_test/default_settings.py9
-rw-r--r--ice-server/heat_test/heat_validator.py79
-rw-r--r--ice-server/heat_test/swagger/ice_api.yaml85
-rw-r--r--ice-server/heat_test/test/fixture/test.zipbin0 -> 166 bytes
-rw-r--r--ice-server/heat_test/test/test_api.py62
7 files changed, 300 insertions, 0 deletions
diff --git a/ice-server/heat_test/__init__.py b/ice-server/heat_test/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/ice-server/heat_test/__init__.py
diff --git a/ice-server/heat_test/app.py b/ice-server/heat_test/app.py
new file mode 100644
index 0000000..e982c68
--- /dev/null
+++ b/ice-server/heat_test/app.py
@@ -0,0 +1,65 @@
+#!flask/bin/python
+import argparse
+import logging
+import requests
+
+import connexion
+from connexion.resolver import RestyResolver
+
+
+def parse_args():
+ """
+ parse argument parameters
+ """
+ parser = argparse.ArgumentParser(description='start the heat validation rest server')
+ parser.add_argument("--debug", help="increase output verbosity")
+ parser.add_argument("-p", "--port", type=int, help="listen port (default 5000)", default=5000)
+ args = parser.parse_args()
+ if args.debug:
+ logging.info("debug mode")
+ debug = True
+ else:
+ debug = False
+ if args.port:
+ port = args.port
+ else:
+ port = 5000
+
+
+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_envvar('ICE_SETTINGS', silent=True)
+ app.add_api('ice_api.yaml', swagger_ui=app.app.config['DEBUG'], resolver=RestyResolver('ice_validator'))
+
+ return app
+
+def create_test_app():
+ print("create_test_app")
+ logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
+ app = connexion.App(__name__, specification_dir='swagger/')
+ app.add_api('ice_api.yaml', swagger_ui=app.app.config['DEBUG'], resolver=RestyResolver('ice_validator'))
+ app.app.testing = True
+ return app
+
+
+def start_app(app):
+ logging.info("######################################")
+ logging.info("starting server")
+ logging.info("######################################")
+ app.run(port=app.app.config['ICE_PORT'], debug=app.app.config['DEBUG'])
+
+ # register service in MSB
+ try:
+ msb_url = app.app.config['MSB_URL']
+ requests.get(msb_url)
+ logging.info("registration to %s done", msb_url)
+ except:
+ logging.info("registration to %s failed", msb_url)
+
+
+if __name__ == '__main__':
+ start_app(create_app())
diff --git a/ice-server/heat_test/default_settings.py b/ice-server/heat_test/default_settings.py
new file mode 100644
index 0000000..d32d039
--- /dev/null
+++ b/ice-server/heat_test/default_settings.py
@@ -0,0 +1,9 @@
+# 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
new file mode 100644
index 0000000..0cc32a1
--- /dev/null
+++ b/ice-server/heat_test/heat_validator.py
@@ -0,0 +1,79 @@
+import logging
+import os
+import shutil
+import sys
+import tempfile
+import zipfile
+from io import StringIO
+
+import pytest
+from flask import (request, jsonify, abort)
+
+
+class HeatValidator(object):
+ """REST service for HEAT templates validation"""
+
+ # Customize messages for pytest exit codes...
+ msg = {0: 'OK',
+ 1: 'Tests failed',
+ 2: 'Interrupted',
+ 3: 'Internal error',
+ 4: 'Usage error',
+ 5: 'No tests collected'}
+
+ def ping(self):
+ return "pong"
+
+ def validate(self):
+ """validate the heat template contained in the uploaded zipfile
+ by running the ice_validator scripts"""
+ logging.info("validate")
+
+ # check if the post request is valid
+ if 'file' not in request.files:
+ logging.error("invalid request: no file found")
+ abort(422, {'status': 1, 'message': 'no file found'})
+
+ try:
+ # extract the uploaded archive
+ zip_file = request.files['file']
+ tmp_dir = tempfile.mkdtemp()
+ zip_ref = zipfile.ZipFile(zip_file, 'r')
+ zip_ref.extractall(tmp_dir)
+ zip_ref.close()
+ debug = request.args.get('debug')
+
+ # execute the validation scripts with pytest
+ if debug == 'true':
+ # Save the original stream output, the console basically
+ 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',
+ '--resultlog=' + tmp_dir + '/result.txt',
+ '--template-dir', tmp_dir])
+ with open(tmp_dir + '/result.txt', 'r') as result_file:
+ result = result_file.read()
+ if debug == 'true':
+ output = sys.stdout.getvalue()
+ # close the stream and reset stdout to the original value (console)
+ sys.stdout.close()
+ sys.stdout = original_output
+ except zipfile.BadZipFile:
+ logging.exception("invalid file")
+ abort(422, {'status': 4, 'message': 'invalid file'})
+ except:
+ logging.exception("server error on file")
+ abort(500, {'status': 3, 'message': 'server error'})
+ finally:
+ if os.path.exists(tmp_dir):
+ shutil.rmtree(tmp_dir)
+
+ result = {'status': exit_code, 'message': self.msg[exit_code], 'result': result}
+ if debug == 'true':
+ result['debug'] = output
+
+ return jsonify(result), 200 if (exit_code == 0) else 422
+
+
+class_instance = HeatValidator()
diff --git a/ice-server/heat_test/swagger/ice_api.yaml b/ice-server/heat_test/swagger/ice_api.yaml
new file mode 100644
index 0000000..c12269f
--- /dev/null
+++ b/ice-server/heat_test/swagger/ice_api.yaml
@@ -0,0 +1,85 @@
+swagger: "2.0"
+
+info:
+ title: "ICE validation"
+ description: "Heat template validation rest API"
+ contact:
+ name: ONAP
+ url: https://www.onap.org
+ email: onap-discuss@lists.onap.org
+ license:
+ name: Apache 2.0
+ url: http://www.apache.org/licenses/LICENSE-2.0.html
+ version: "1.0.0"
+
+basePath: /onapapi/ice/v1
+
+paths:
+ /:
+ get:
+ summary: "list HEAT templates"
+ operationId: heat_validator.class_instance.ping
+ responses:
+ '200':
+ description: 'server is up and running'
+ schema:
+ type: string
+ post:
+ summary: "validate HEAT template"
+ operationId: heat_validator.class_instance.validate
+ consumes: [
+ "multipart/form-data"
+ ]
+ produces: [
+ "application/json"
+ ]
+ parameters: [
+ {
+ "name": "file",
+ "in": "formData",
+ "description": "file to upload",
+ "required": true,
+ "type": "file"
+ },
+ {
+ "name": "debug",
+ "in": "query",
+ "description": "debug mode",
+ "required": false,
+ "type": "boolean"
+ }
+ ]
+ responses:
+ "200":
+ description: 'validation success'
+ schema: {
+ "$ref": "#/definitions/Result"
+ }
+ "400":
+ description: 'validation error'
+ schema: {
+ "$ref": "#/definitions/Result"
+ }
+ "500":
+ description: 'validation error'
+ schema: {
+ "$ref": "#/definitions/Result"
+ }
+definitions:
+ Result:
+ required: [
+ "status",
+ "message"
+ ]
+ properties: {
+ "status": {
+ "type": "integer",
+ "format": "int64"
+ },
+ "message": {
+ "type": "string"
+ },
+ "debug": {
+ "type": "string"
+ }
+ } \ No newline at end of file
diff --git a/ice-server/heat_test/test/fixture/test.zip b/ice-server/heat_test/test/fixture/test.zip
new file mode 100644
index 0000000..d1e6d99
--- /dev/null
+++ b/ice-server/heat_test/test/fixture/test.zip
Binary files differ
diff --git a/ice-server/heat_test/test/test_api.py b/ice-server/heat_test/test/test_api.py
new file mode 100644
index 0000000..259a43b
--- /dev/null
+++ b/ice-server/heat_test/test/test_api.py
@@ -0,0 +1,62 @@
+import io
+import json
+import os
+import sys
+
+import pytest
+
+#sys.path.append(os.path.join(os.path.dirname(os.path.realpath(__file__)), os.pardir))
+
+# Make sure that the application source directory (this directory's parent) is
+# on sys.path.
+here = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
+sys.path.insert(0, here)
+print(sys.path)
+
+import app as myapp
+
+ICE_URL = '/ice/'
+
+flask_app = myapp.create_test_app()
+
+
+@pytest.fixture(scope='module')
+def client():
+ with flask_app.app.test_client() as c:
+ yield c
+
+
+def test_404(client):
+ response = client.get('/dummy')
+ assert response.status_code == 404
+
+
+def test_ping(client):
+ response = client.get(ICE_URL, content_type='application/json')
+ assert response.status_code == 200
+
+
+def test_validate_nofile(client):
+ response = client.post(ICE_URL)
+ assert response.status_code == 400
+ assert json_of_response(response) is not None
+
+
+def test_validate_not_zip(client):
+ data = {'file': (io.BytesIO(b'my file contents'), 'hello world.txt')}
+ response = client.post(ICE_URL, data=data)
+ assert response.status_code == 422
+
+
+@pytest.mark.skip(reason="no way of currently testing this")
+def test_validate_bad_zip(client):
+ zf = os.path.join(os.path.dirname(__file__), 'fixture/test.zip')
+ data = {'file': (zf, 'test.zip')}
+ response = client.post(ICE_URL, data=data)
+ print("##"+zf)
+ assert response.status_code == 200
+
+
+def json_of_response(response):
+ """Decode json from response"""
+ return json.loads(response.data.decode('utf8'))