Commit a9b02518 authored by Daniele Venzano's avatar Daniele Venzano

Update the integration tests to use pytest

parent 1f878fe3
FROM python:3.4
MAINTAINER Daniele Venzano <venza@brownhat.org>
RUN mkdir -p /opt/zoe
WORKDIR /opt/zoe
COPY ./requirements* /opt/zoe/
RUN pip install -U pip setuptools
RUN pip install --no-cache-dir -r requirements.txt
RUN pip install --no-cache-dir -r requirements_tests.txt
COPY . /opt/zoe
RUN echo 'admin,admin,admin' > /opt/zoe/zoepass.csv
......@@ -7,7 +7,6 @@ humanfriendly
psycopg2>=2.6.1
pyzmq>=15.2.0
typing
python-oauth2
python-consul
pykube>=0.14.0
sphinx
......
#!/usr/bin/env bash
docker build -f Dockerfile.test -t zoe_test_image .
docker network create zoe_test
docker run -d --network zoe_test --name postgres -p 5432:5432 -e POSTGRES_DB=zoe -e POSTGRES_USER=zoeuser -e POSTGRES_PASSWORD=zoepass postgres:9.3
docker pull nginx:alpine
sleep 4 # give postgres the time to start
docker run -it --network zoe_test --name zoe zoe_test_image pytest --tb=short --cov-report=term --cov zoe_api --cov zoe_lib --cov zoe_master tests/basic_auth_success_test.py
docker rm -f zoe postgres
docker network rm zoe_test
"""Test script for successful basic authentication."""
import json
import os
import subprocess
import time
import json
import sys
import unittest
import os
import pytest
import requests
ZOE_API_URI = 'http://192.168.12.2:5100/api/0.7/'
ZOE_API_URI = 'http://127.0.0.1:5100/api/0.7/'
ZOE_AUTH = ('admin', 'admin')
class ZoeRestTestSuccess(unittest.TestCase):
TIMEOUT = 5
ARGS = [
'--debug',
'--deployment-name', 'integration_test',
'--dbuser', 'zoeuser',
'--dbhost', 'postgres',
'--dbport', '5432',
'--dbname', 'zoe',
'--dbpass', 'zoepass',
'--master-url', 'tcp://localhost:4850',
'--auth-type', 'text',
'--listen-port', '5100',
'--workspace-base-path', '/tmp',
'--workspace-deployment-path', 'integration_test',
'--auth-file', 'zoepass.csv',
'--backend', 'DockerEngine',
'--backend-docker-config-file', 'tests/sample_docker.conf',
'--zapp-shop-path', 'contrib/zapp-shop-sample'
]
@pytest.fixture(scope="session")
def zoe_api_process(request):
"""Fixture that starts the Zoe API process."""
proc = subprocess.Popen(["python", "zoe-api.py"] + ARGS, stderr=sys.stderr, stdout=sys.stdout)
request.addfinalizer(proc.terminate)
time.sleep(2)
@pytest.fixture(scope="session")
def zoe_master_process(request):
"""Fixture that starts the Zoe Master process."""
os.mkdir('/tmp/integration_test')
proc = subprocess.Popen(["python", "zoe-master.py"] + ARGS, stderr=sys.stderr, stdout=sys.stdout)
request.addfinalizer(proc.terminate)
time.sleep(4)
class TestZoeRest:
"""Test case class."""
uri = ZOE_API_URI
auth = ZOE_AUTH
id = ''
def tearDown(self):
"""Test end."""
time.sleep(3)
id = None
def test_0_info(self):
def test_info(self, zoe_api_process):
"""Test info api endpoint."""
print('Test info api endpoint')
req = requests.get(self.__class__.uri + 'info')
self.assertEqual(req.status_code, 200)
req = requests.get(ZOE_API_URI + 'info', timeout=TIMEOUT)
assert req.status_code == 200
def test_1_userinfo(self):
def test_userinfo(self, zoe_api_process):
"""Test userinfo api endpoint."""
print('Test userinfo api endpoint')
req = requests.get(self.__class__.uri + 'userinfo', auth=self.__class__.auth)
self.assertEqual(req.status_code, 200)
def test_3_execution_details(self):
"""Test execution details api endpoint."""
print('Test execution details api endpoint')
req = requests.get(self.__class__.uri + 'execution/' + self.__class__.id, auth=self.__class__.auth)
self.assertEqual(req.status_code, 200)
def test_4_service_details(self):
"""Test service details api endpoint."""
print('Test service details api endpoint')
req = requests.get(self.__class__.uri + 'execution/' + self.__class__.id, auth=self.__class__.auth)
sid = req.json()["services"][0]
req = requests.get(self.__class__.uri + 'service/' + str(sid), auth=self.__class__.auth)
self.assertEqual(req.status_code, 200)
def test_5_terminate_execution(self):
"""Test terminate execution api endpoint."""
print('Test terminate execution api endpoint')
req = requests.delete(self.__class__.uri + 'execution/' + self.__class__.id, auth=self.__class__.auth)
self.assertEqual(req.status_code, 204)
req = requests.get(ZOE_API_URI + 'userinfo', auth=ZOE_AUTH, timeout=TIMEOUT)
assert req.status_code == 200
def test_6_list_all_executions(self):
def test_list_all_executions(self, zoe_api_process):
"""Test list all executions api endpoint."""
print('Test list all executions api endpoint')
req = requests.get(self.__class__.uri + 'execution', auth=self.__class__.auth)
self.assertEqual(req.status_code, 200)
req = requests.get(ZOE_API_URI + 'execution', auth=ZOE_AUTH, timeout=TIMEOUT)
assert req.status_code == 200
# def test_7_delete_execution(self):
# """Test delete execution api endpoint."""
......@@ -69,30 +81,55 @@ class ZoeRestTestSuccess(unittest.TestCase):
# print('error message: {}'.format(req.json()['message']))
# self.assertEqual(req.status_code, 204)
def test_2_start_execution(self):
def test_start_stop_execution(self, zoe_api_process, zoe_master_process):
"""Test start execution api endpoint."""
print('Test start execution api endpoint')
with open('zapp.json', encoding='utf-8') as data_file:
with open('tests/zapp.json', encoding='utf-8') as data_file:
data = json.loads(data_file.read())
req = requests.post(self.__class__.uri + 'execution', auth=self.__class__.auth, json={"application": data, "name": "requests"})
self.assertEqual(req.status_code, 201)
self.__class__.id = str(req.json()['execution_id'])
req = requests.post(ZOE_API_URI + 'execution', auth=ZOE_AUTH, json={"application": data, "name": "requests"}, timeout=TIMEOUT)
assert req.status_code == 201
exec_id = str(req.json()['execution_id'])
print('execution ID is {}'.format(exec_id))
print('Test execution details api endpoint')
while True:
req = requests.get(ZOE_API_URI + 'execution/' + exec_id, auth=ZOE_AUTH, timeout=TIMEOUT)
assert req.status_code == 200
if req.json()['status'] == 'running':
break
elif req.json()['status'] == 'error':
print(req.json()['error_message'])
assert False
print('Waiting for ZApp to start (status is {})...'.format(req.json()['status']))
time.sleep(1)
def test_zapp_validate(self):
print('Test service details api endpoint')
req = requests.get(ZOE_API_URI + 'execution/' + exec_id, auth=ZOE_AUTH, timeout=TIMEOUT)
sid = req.json()["services"][0]
req = requests.get(ZOE_API_URI + 'service/' + str(sid), auth=ZOE_AUTH, timeout=TIMEOUT)
assert req.status_code == 200
print('Test terminate execution api endpoint')
req = requests.delete(ZOE_API_URI + 'execution/' + exec_id, auth=ZOE_AUTH, timeout=TIMEOUT)
assert req.status_code == 204
def test_zapp_validate(self, zoe_api_process):
"""Test ZApp validation endpoint"""
print("Test ZApp validation endpoint")
with open('zapp.json', encoding='utf-8') as data_file:
with open('tests/zapp.json', encoding='utf-8') as data_file:
data = json.loads(data_file.read())
req = requests.post(self.__class__.uri + 'zapp_validate', json={"application": data})
self.assertEqual(req.status_code, 200)
req = requests.post(ZOE_API_URI + 'zapp_validate', json={"application": data}, timeout=TIMEOUT)
assert req.status_code == 200
def test_zapp_validate_fail(self, zoe_api_process):
"""Test ZApp validation endpoint"""
print("Test ZApp validation endpoint")
with open('tests/zapp.json', encoding='utf-8') as data_file:
data = json.loads(data_file.read())
if __name__ == '__main__':
if len(sys.argv) > 1:
API_SERVER = sys.argv.pop()
ZoeRestTestSuccess.uri = 'http://' + API_SERVER + '/api/0.7/'
ZoeRestTestSuccess.auth = (os.getenv('ZOE_USER', ZOE_AUTH[0]), os.getenv('ZOE_PASS', ZOE_AUTH[1]))
unittest.main()
del data['version']
req = requests.post(ZOE_API_URI + 'zapp_validate', json={"application": data}, timeout=TIMEOUT)
assert req.status_code == 400
[DEFAULT]
use_tls: no
tls_cert: /mnt/test/cert.pem
tls_key: /mnt/test/key.pem
tls_ca: /mnt/test/ca.pem
[bf5]
docker_address: 192.168.47.5:2375
external_address: 192.168.47.5
use_tls: yes
[bf7]
docker_address: 192.168.47.7:2375
external_address: 192.168.47.7
use_tls: yes
[bf8]
docker_address: 192.168.47.8:2375
external_address: 192.168.47.8
use_tls: yes
[bf9]
docker_address: 192.168.47.9:2375
external_address: 192.168.47.9
use_tls: yes
[bf10]
docker_address: 192.168.47.10:2375
external_address: 192.168.47.10
use_tls: yes
[bf12]
docker_address: 192.168.47.12:2375
external_address: 192.168.47.12
use_tls: yes
[bf13]
docker_address: 192.168.47.13:2375
external_address: 192.168.47.13
use_tls: yes
[bf14]
docker_address: 192.168.47.14:2375
external_address: 192.168.47.14
use_tls: yes
[bf15]
docker_address: 192.168.47.15:2375
external_address: 192.168.47.15
use_tls: yes
[bf16]
docker_address: 192.168.47.16:2375
external_address: 192.168.47.16
use_tls: yes
[bf17]
docker_address: 192.168.47.17:2375
external_address: 192.168.47.17
use_tls: yes
[bf18]
docker_address: 192.168.47.18:2375
external_address: 192.168.47.18
use_tls: yes
[bf19]
docker_address: 192.168.47.19:2375
external_address: 192.168.47.19
use_tls: yes
[bf20]
docker_address: 192.168.47.20:2375
external_address: 192.168.47.20
use_tls: yes
[bf21]
docker_address: 192.168.47.21:2375
external_address: 192.168.47.21
use_tls: yes
[bf22]
docker_address: 192.168.47.22:2375
external_address: 192.168.47.22
use_tls: yes
[container-router]
docker_address: 192.168.45.25:2375
external_address: 192.168.45.25
......@@ -35,13 +35,14 @@ log = logging.getLogger("zoe_api")
LOG_FORMAT = '%(asctime)-15s %(levelname)s %(threadName)s->%(name)s: %(message)s'
def zoe_web_main() -> int:
def zoe_web_main(test_conf=None) -> int:
"""
This is the entry point for the Zoe Web script.
:return: int
"""
config.load_configuration()
config.load_configuration(test_conf)
args = config.get_conf()
log_args = {
'level': logging.DEBUG if args.debug else logging.INFO,
'format': LOG_FORMAT
......
......@@ -95,7 +95,7 @@ def load_configuration(test_conf=None):
argparser.add_argument('--proxy-path', help='Proxy base path', default='127.0.0.1')
# Scheduler
argparser.add_argument('--scheduler-class', help='Scheduler class to use for scheduling ZApps', choices=['ZoeSimpleScheduler', 'ZoeElasticScheduler'], default='ZoeSimpleScheduler')
argparser.add_argument('--scheduler-class', help='Scheduler class to use for scheduling ZApps', choices=['ZoeSimpleScheduler', 'ZoeElasticScheduler'], default='ZoeElasticScheduler')
argparser.add_argument('--scheduler-policy', help='Scheduler policy to use for scheduling ZApps', choices=['FIFO', 'SIZE'], default='FIFO')
argparser.add_argument('--backend', choices=['Swarm', 'Kubernetes', 'DockerEngine'], default='Swarm', help='Which backend to enable')
......
......@@ -16,27 +16,23 @@
"""Unit tests for zoe_lib/applications.py"""
import json
from collections import namedtuple
import pytest
from zoe_lib import applications
ConfigMockup = namedtuple('ConfigMockup', ['max_core_limit', 'max_memory_limit'])
def fake_get_conf():
"""Mock-up for the config.get_conf() method."""
return ConfigMockup(16, 64)
from zoe_lib.tests.config_mock import zoe_configuration
from zoe_lib.config import load_configuration
class TestApplicationsMethods:
"""Application validation tests."""
@pytest.fixture(autouse=True)
def mock_config(self, monkeypatch):
def mock_config(self, zoe_configuration):
"""Fixture for mock config method."""
monkeypatch.setattr('zoe_lib.config.get_conf', fake_get_conf)
zoe_configuration.max_core_limit = 32
zoe_configuration.max_memory_limit = 64
load_configuration(zoe_configuration)
def test_pass_for_zapp(self):
"""Test zapp validation code."""
......
# Copyright (c) 2017, Jordan Kuhn
#
# 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.
"""Fixture for mock configuration used in tests."""
from argparse import Namespace
import pytest
@pytest.fixture(scope="session")
def zoe_configuration():
"""Mock Zoe configuration."""
zoe_api_args = Namespace()
zoe_api_args.debug = True
zoe_api_args.deployment_name = 'integration_test'
zoe_api_args.dbhost = 'postgres'
zoe_api_args.dbport = 5432
zoe_api_args.dbuser = 'zoeuser'
zoe_api_args.dbpass = 'zoepass'
zoe_api_args.dbname = 'zoe'
zoe_api_args.api_listen_uri = 'tcp://*:4850'
zoe_api_args.kairosdb_enable = False
zoe_api_args.workspace_base_path = '/tmp'
zoe_api_args.workspace_deployment_path = zoe_api_args.workspace_base_path
zoe_api_args.overlay_network_name = 'zoe'
zoe_api_args.gelf_listener = 0
zoe_api_args.listen_address = '0.0.0.0'
zoe_api_args.listen_port = 5100
zoe_api_args.master_url = 'tcp://127.0.0.1:4850'
zoe_api_args.cookie_secret = 'changeme'
zoe_api_args.auth_type = 'text'
zoe_api_args.auth_file = 'zoepass.csv'
zoe_api_args.scheduler_class = 'ZoeElasticScheduler'
zoe_api_args.scheduler_policy = 'FIFO'
zoe_api_args.backend = 'DockerEngine'
zoe_api_args.backend_docker_config_file = 'tests/sample_docker.conf'
zoe_api_args.zapp_shop_path = 'contrib/zapp-shop-sample'
zoe_api_args.log_file = 'stderr'
zoe_api_args.max_core_limit = 1
zoe_api_args.max_memory_limit = 2
zoe_api_args.no_user_edit_limits_web = False
zoe_api_args.additional_volumes = ''
return zoe_api_args
......@@ -41,13 +41,14 @@ def _check_configuration_sanity():
return 0
def main():
def main(test_conf=None):
"""
The entrypoint for the zoe-master script.
:return: int
"""
config.load_configuration()
config.load_configuration(test_conf)
args = config.get_conf()
log_args = {
'level': logging.DEBUG if args.debug else logging.INFO,
'format': LOG_FORMAT
......
......@@ -34,6 +34,7 @@ def _digest_application_description(state: SQLManager, execution: Execution):
for node in nodes:
images += list_available_images(node)
images = [name for image in images for name in image['names']]
for service_descr in execution.description['services']:
if service_descr['image'] not in images:
execution.set_error()
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment