Prepare for project renaming

- refactoring with relative imports to support simple renaming
 - new tox job to build and simply test code inside docker container
This commit is contained in:
Denis Makogon 2016-12-02 18:47:58 +02:00
parent e02b003fcb
commit a6a8405510
27 changed files with 178 additions and 154 deletions

View File

@ -11,5 +11,5 @@ RUN pip3 install -r /code/requirements.txt
RUN python3 /code/setup.py install
ENTRYPOINT ["python3", "/code/laos/service/laos_api.py"]
ENTRYPOINT ["python3", "/code/service/laos_api.py"]
EXPOSE 10001

View File

@ -1,6 +1,6 @@
LAOS_HOST=0.0.0.0
LAOS_PORT=10001
LAOS_DB=mysql://root:ubuntu@192.168.0.120/functions
LAOS_DB=mysql+pymysql://root:ubuntu@192.168.0.120/functions
KEYSTONE_ENDPOINT=http://192.168.0.120:5000/v3
FUNCTIONS_URL=http://192.168.0.120:8080/v1
LAOS_LOG_LEVEL=INFO

105
README.md
View File

@ -168,111 +168,6 @@ Once server is launched you can navigate to:
to see recent API docs
Testing (general information)
-----------------------------
In order to run tests you need to install `Tox`:
$ pip install tox
Also, you will need a running MySQL instance with the database migrations applied from the previous step.
Tests are dependent on pre-created MySQL database for persistence.
Please set env var
$ export TEST_DB_URI=mysql://<your-user>:<your-user-password>@<mysql-host>:<mysql-port>/<functions-db>
Testing: PEP8
-------------
In order to run `PEP8` style checks run following command:
$ tox -e pep8
Testing: Functional
-------------------
In order to run `functional` tests run following command:
$ tox -e py35-functional
Pros:
* lightweight (controllers and DB models testing)
* no OpenStack required
* no IronFunctions required
Cons:
* MySQL server required
* OpenStack authentication is not tested
* IronFunctions API stubbed with fake implementation
Testing: Integration
--------------------
Integration tests are dependent on following env variables:
* TEST_DB_URI - similar to functional tests, database endpoint
* FUNCTIONS_API_URL - IronFunctions API URL (default value - `http://localhost:8080/v1`)
* OS_AUTH_URL - OpenStack Identity endpoint
* OS_PROJECT_NAME - OpenStack user-specific project name
* OS_USERNAME - OpenStack user name
* OS_PASSWORD - OpenStack user user password
To run tests use following command:
export TEST_DB_URI=mysql://<your-user>:<your-user-password>@<mysql-host>:<mysql-port>/<functions-db>
export FUNCTIONS_API_URL=<functions-api-protocol>://<functions-host>:<functions-port>/<functions-api-version>
export OS_AUTH_URL=<identity-api-protocol>://<identity-host>:<identity-port>/<identity-api-version>
export OS_PROJECT_NAME=<project-name>
export OS_USERNAME=<project-name>
export OS_PASSWORD=<project-name>
tox -epy35-integration
Testing: Coverage regression
----------------------------
In order to build quality software it is necessary to keep test coverage at its highest point.
So, as part of `Tox` testing new check was added - functional test coverage regression.
In order to run it use following command:
$ tox -e py35-functional-regression
3rd party bugs to resolve
-------------------------
IronFunctions:
* https://github.com/iron-io/functions/issues/298
* https://github.com/iron-io/functions/issues/296
* https://github.com/iron-io/functions/issues/275
* https://github.com/iron-io/functions/issues/274
TODOs
-----
Swagger doc:
* Make swagger doc more explicit on HTTP POST/UPDATE body content
* HTTP headers requests
IronFunctions:
* Support app deletion in IronFunctions
* Support tasks listing/showing
Laos:
* Tests: integration, functional, units
* Better logging coverage
Python Functions client:
* Support logging instance passing in [function-python](https://github.com/iron-io/functions_python)
* python-laosclient (ReST API client and CLI tool)
* App writing examples
Contacts
--------

View File

@ -17,9 +17,9 @@ from aiohttp import web
from aioservice.http import controller
from aioservice.http import requests
from laos.api.views import app as app_view
from laos.common import config
from laos.models import app as app_model
from ...common import config
from ...models import app as app_model
from ..views import app as app_view
class AppV1Controller(controller.ServiceController):
@ -202,12 +202,12 @@ class AppV1Controller(controller.ServiceController):
stored_app = (await app_model.Apps.find_by(
project_id=project_id, name=app_name)).pop()
c.logger.info("Updating an app {} for project: {} with data {}"
c.logger.info("Updating app {} for project: {} with data {}"
.format(app_name, project_id, str(data)))
return web.json_response(
data={
"app": app_view.AppView(stored_app, fn_app).view(),
"message": "App successfully update"
"message": "App successfully updated"
},
status=200
)

View File

@ -19,9 +19,9 @@ from aiohttp import web
from aioservice.http import controller
from aioservice.http import requests
from laos.api.views import app as app_view
from laos.common import config
from laos.models import app as app_model
from ...common import config
from ...models import app as app_model
from ..views import app as app_view
class AppRouteV1Controller(controller.ServiceController):

View File

@ -17,7 +17,7 @@ from aiohttp import web
from aioservice.http import controller
from aioservice.http import requests
from laos.common import config
from ...common import config
class RunnableMixin(object):

View File

@ -14,12 +14,12 @@
from aiohttp import web
# from laos.models import app as app_model
# from ...models import app as app_model
from aioservice.http import controller
from aioservice.http import requests
# from laos.common import config
# from ...common import config
# TODO(denismakogon): disabled until

View File

@ -18,7 +18,7 @@ from keystoneclient import client
from aiohttp import web
from laos.common import config
from ...common import config
async def auth_through_token(app: web.Application, handler):

View File

@ -16,7 +16,7 @@
import aiomysql
import asyncio
from laos.common import utils
from . import utils
from functionsclient.v1 import client

View File

@ -16,7 +16,7 @@ import datetime
import logging
import sys
from laos.common import utils
from . import utils
def common_logger_setup(

View File

@ -15,7 +15,7 @@
import datetime
import uuid
from laos.common import config
from . import config
class BaseDatabaseModel(object):

View File

@ -12,7 +12,7 @@
# License for the specific language governing permissions and limitations
# under the License.
from laos.common import persistence
from ..common import persistence
class Apps(persistence.BaseDatabaseModel):

View File

@ -16,7 +16,7 @@ import asyncio
import datetime
import uvloop
from laos.common import logger as log
from ...common import logger as log
class LaosTestsBase(object):

View File

@ -120,7 +120,7 @@ class FakeApps(object):
async def delete(self, app_name, loop=None):
if app_name not in APPS:
raise client.FunctionsAPIException(
"App {} not exist.".format(app_name), 404)
"App {} not found.".format(app_name), 404)
else:
if APP_ROUTES[app_name]:
raise client.FunctionsAPIException(

View File

@ -18,17 +18,17 @@ import uuid
from aioservice.http import service
from laos.api.controllers import apps
from laos.api.controllers import routes
from laos.api.controllers import runnable
from laos.api.controllers import tasks
from laos.api.middleware import content_type
from ...api.controllers import apps
from ...api.controllers import routes
from ...api.controllers import runnable
from ...api.controllers import tasks
from ...api.middleware import content_type
from laos.common import config
from ...common import config
from laos.tests.common import base
from laos.tests.common import client
from laos.tests.fakes import functions_api
from ..common import base
from ..common import client
from ..fakes import functions_api
class LaosFunctionalTestsBase(base.LaosTestsBase, testtools.TestCase):

View File

@ -12,8 +12,8 @@
# License for the specific language governing permissions and limitations
# under the License.
from laos.tests.common import apps as apps_suite
from laos.tests.functional import base
from ..common import apps as apps_suite
from ..functional import base
class TestApps(base.LaosFunctionalTestsBase, apps_suite.AppsTestSuite):

View File

@ -12,8 +12,8 @@
# License for the specific language governing permissions and limitations
# under the License.
from laos.tests.common import routes as routes_suite
from laos.tests.functional import base
from ..common import routes as routes_suite
from ..functional import base
class TestAppRoutes(base.LaosFunctionalTestsBase,

View File

@ -12,18 +12,19 @@
# License for the specific language governing permissions and limitations
# under the License.
import aiohttp
import json
import os
from urllib import parse
import aiohttp
import testtools
from laos.common import config
from laos.service import laos_api
from ...common import config
from ..common import base
from ..common import client
from laos.tests.common import base
from laos.tests.common import client
from urllib import parse
from service import laos_api
class LaosIntegrationTestsBase(base.LaosTestsBase, testtools.TestCase):

View File

@ -12,8 +12,8 @@
# License for the specific language governing permissions and limitations
# under the License.
from laos.tests.common import apps as apps_suite
from laos.tests.integration import base
from ..common import apps as apps_suite
from ..integration import base
class TestIntegrationApps(base.LaosIntegrationTestsBase,

View File

@ -12,8 +12,8 @@
# License for the specific language governing permissions and limitations
# under the License.
from laos.tests.common import routes as routes_suite
from laos.tests.functional import base
from ..common import routes as routes_suite
from ..functional import base
class TestIntegrationAppRoutes(base.LaosFunctionalTestsBase,

View File

@ -3,7 +3,7 @@
# process, which may cause wedges in the gate later.
uvloop==0.6.0 # Apache-2.0
aioservice==0.0.1 # Apache-2.0
aioservice==0.0.2 # Apache-2.0
aiomysql==0.0.9 # Apache-2.0
alembic==0.8.8 # MIT
click==6.6 # Apache-2.0

18
scripts/docker_full.sh Executable file
View File

@ -0,0 +1,18 @@
#!/usr/bin/env bash
set +x
set +e
set +i
docker build -t laos-api -f Dockerfile . 2>&1
docker_h=$(echo ${DOCKER_HOST} | tr "://" " " |awk '{print $2}')
echo -e "Docker IP address ${docker_h}"
echo -e "OpenStack Identity service URL ${OS_AUTH_URL}"
echo -e "IronFunctions URL ${FUNCTIONS_API_URL}"
echo -e "Persistent storage URI ${TEST_DB_URI}"
docker run -d -p ${docker_h}:10002:10001 --env LAOS_HOST=0.0.0.0 --env LAOS_PORT=10001 --env LAOS_DB=${TEST_DB_URI} --env KEYSTONE_ENDPOINT=${OS_AUTH_URL} --env FUNCTIONS_URL=${FUNCTIONS_API_URL} --env LAOS_LOG_LEVEL=INFO laos-api
sleep 2
docker ps
echo -e "Service running on ${docker_h}:10002"
curl -X GET http://${docker_h}:10002/api/swagger.json | python -mjson.tool
docker stop -t 1 $(docker ps | grep "${docker_h}:10002" | awk '{print $1}')

View File

@ -30,7 +30,7 @@ setuptools.setup(
packages=setuptools.find_packages(),
install_requires=[
"uvloop==0.6.0",
"aioservice==0.0.1",
"aioservice==0.0.2",
"aiomysql==0.0.9",
"alembic==0.8.8",
"click==6.6",

107
testing.md Normal file
View File

@ -0,0 +1,107 @@
Testing
-------
In order to run tests you need to install `Tox`:
$ pip install tox
Also, you will need a running MySQL instance with the database migrations applied from the previous step.
Tests are dependent on pre-created MySQL database for persistence.
Please set env var
$ export TEST_DB_URI=mysql://<your-user>:<your-user-password>@<mysql-host>:<mysql-port>/<functions-db>
PEP8 style checks
-----------------
In order to run `PEP8` style checks run following command:
$ tox -e pep8
Functional testing
------------------
In order to run `functional` tests run following command:
$ tox -e py35-functional
Pros:
* lightweight (controllers and DB models testing)
* no OpenStack required
* no IronFunctions required
Cons:
* MySQL server required
* OpenStack authentication is not tested
* IronFunctions API stubbed with fake implementation
Integration integrations
------------------------
Integration tests are dependent on following env variables:
* TEST_DB_URI - similar to functional tests, database endpoint
* FUNCTIONS_API_URL - IronFunctions API URL (default value - `http://localhost:8080/v1`)
* OS_AUTH_URL - OpenStack Identity endpoint
* OS_PROJECT_NAME - OpenStack user-specific project name
* OS_USERNAME - OpenStack user name
* OS_PASSWORD - OpenStack user user password
To run tests use following command:
export TEST_DB_URI=mysql://<your-user>:<your-user-password>@<mysql-host>:<mysql-port>/<functions-db>
export FUNCTIONS_API_URL=<functions-api-protocol>://<functions-host>:<functions-port>/<functions-api-version>
export OS_AUTH_URL=<identity-api-protocol>://<identity-host>:<identity-port>/<identity-api-version>
export OS_PROJECT_NAME=<project-name>
export OS_USERNAME=<project-name>
export OS_PASSWORD=<project-name>
tox -epy35-integration
Testing: Docker-build
---------------------
This type of testing allows to ensure if code can be build inside docker container with no problems.
In order to run this check use following commands::
export DOCKER_HOST=tcp://<docker-host>:<docker-port>>
export TEST_DB_URI=mysql://<your-user>:<your-user-password>@<mysql-host>:<mysql-port>/<functions-db>
export FUNCTIONS_API_URL=<functions-api-protocol>://<functions-host>:<functions-port>/<functions-api-version>
export OS_AUTH_URL=<identity-api-protocol>://<identity-host>:<identity-port>/<identity-api-version>
tox -e docker-build
During this check Tox:
* builds an image
* deletes all artifacts (Python3.5 image and recently built image)
Testing Docker-full
-------------------
This type of testing allows to ensure if code code can be build and run successfully inside docker container with no problems.
In order to run this check use following commands::
export DOCKER_HOST=tcp://<docker-host>:<docker-port>>
export TEST_DB_URI=mysql://<your-user>:<your-user-password>@<mysql-host>:<mysql-port>/<functions-db>
export FUNCTIONS_API_URL=<functions-api-protocol>://<functions-host>:<functions-port>/<functions-api-version>
export OS_AUTH_URL=<identity-api-protocol>://<identity-host>:<identity-port>/<identity-api-version>
tox -e docker-full
During this check following operations are performed::
* build container from source code
* run container with exposed ports
* request Swagger API doc to see if API is responsive
* tear-down running container
Coverage regression testing
---------------------------
In order to build quality software it is necessary to keep test coverage at its highest point.
So, as part of `Tox` testing new check was added - functional test coverage regression.
In order to run it use following command:
$ tox -e py35-functional-regression

11
tox.ini
View File

@ -1,7 +1,7 @@
# Project LaOS
[tox]
envlist = py35-functional,py35-functional-regression,py35-integration,py35-integration-regression,pep8
envlist = py35-functional,py35-functional-regression,py35-integration,py35-integration-regression,pep8,docker-build
minversion = 1.6
skipsdist = True
@ -14,16 +14,16 @@ passenv =
OS_PASSWORD
OS_USERNAME
OS_PROJECT_NAME
DOCKER_HOST
setenv = VIRTUAL_ENV={envdir}
usedevelop = True
install_command = pip install -U {opts} {packages}
deps = -r{toxinidir}/requirements.txt
-r{toxinidir}/test-requirements.txt
commands = find . -type f -name "*.pyc" -delete
rm -f .testrepository/times.dbm
python setup.py testr --testr-args='{posargs}'
whitelist_externals = find
rm
docker
[testenv:pep8]
commands = flake8
@ -48,7 +48,10 @@ commands =
rm -rf doc/html doc/build
python setup.py build_sphinx
[testenv:docker-full]
commands = {toxinidir}/scripts/docker_full.sh
[flake8]
ignore = H202,H404,H405,H501
ignore = H202,H304,H404,H405,H501
show-source = True
exclude=.venv,.git,.tox,dist,doc,*lib/python*,*egg,build,migrations