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:
parent
e02b003fcb
commit
a6a8405510
@ -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
|
||||
|
@ -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
105
README.md
@ -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
|
||||
--------
|
||||
|
@ -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
|
||||
)
|
||||
|
@ -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):
|
||||
|
@ -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):
|
||||
|
@ -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
|
||||
|
@ -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):
|
||||
|
@ -16,7 +16,7 @@
|
||||
import aiomysql
|
||||
import asyncio
|
||||
|
||||
from laos.common import utils
|
||||
from . import utils
|
||||
|
||||
from functionsclient.v1 import client
|
||||
|
||||
|
@ -16,7 +16,7 @@ import datetime
|
||||
import logging
|
||||
import sys
|
||||
|
||||
from laos.common import utils
|
||||
from . import utils
|
||||
|
||||
|
||||
def common_logger_setup(
|
||||
|
@ -15,7 +15,7 @@
|
||||
import datetime
|
||||
import uuid
|
||||
|
||||
from laos.common import config
|
||||
from . import config
|
||||
|
||||
|
||||
class BaseDatabaseModel(object):
|
||||
|
@ -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):
|
||||
|
@ -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):
|
||||
|
@ -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(
|
||||
|
@ -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):
|
||||
|
@ -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):
|
||||
|
@ -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,
|
||||
|
@ -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):
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
|
@ -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
18
scripts/docker_full.sh
Executable 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}')
|
2
setup.py
2
setup.py
@ -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
107
testing.md
Normal 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
11
tox.ini
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user