Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 5 additions & 4 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
language: python
python:
- "3.6"
- "3.7"
- "3.8"
install:
- pip install --upgrade setuptools tox tox-travis coveralls
- python -m pip install --upgrade pip
- pip install --upgrade setuptools coveralls pipenv
- pipenv lock --dev --requirements > requirements.txt
- pip install -r requirements.txt
script:
- coverage erase
- tox
- python setup.py test
after_success:
- coverage combine
- coveralls
Expand Down
23 changes: 14 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ microservices with Python which handles cross-cutting concerns:
- Metrics
- Distributed tracing

![Python package](https://github.com/python-microservices/microservices-scaffold/workflows/Python%20package/badge.svg?branch=master)
[![Build Status](https://travis-ci.org/python-microservices/microservices-scaffold.svg?branch=master)](https://travis-ci.org/python-microservices/microservices-scaffold)
[![Coverage Status](https://coveralls.io/repos/github/python-microservices/microservices-scaffold/badge.svg?branch=master)](https://coveralls.io/github/python-microservices/microservices-scaffold?branch=master)
[![Requirements Status](https://requires.io/github/python-microservices/microservices-scaffold/requirements.svg?branch=master)](https://requires.io/github/python-microservices/microservices-scaffold/requirements/?branch=master)
Expand All @@ -21,20 +22,27 @@ Table of Contents
* [microservices-scaffold](#microservices-scaffold)
* [How to run the scaffold](#how-to-run-the-scaffold)
* [Installation](#installation)
* [Clone the repository](#clone-the-repository)
* [Install with virtualenv](#install-with-virtualenv)
* [Install with pipenv](#install-with-pipenv)
* [Advantages over plain pip and requirements.txt](#advantages-over-plain-pip-and-requirementstxt)
* [Run your python script](#run-your-python-script)
* [Check the result](#check-the-result)
* [Docker](#docker)
* [Kubernetes](#kubernetes)
* [How to contrib](#how-to-contrib)
* [Update docs](#update-docs)
* [How To contribute](#how-to-contribute)

# How to run the scaffold

## Installation

### Clone the repository

```bash
git clone git@github.com:purwowd/microservices-scaffold.git
cd microservices-scaffold
```

### Install with virtualenv
```bash
virtualenv --python=python[3.6|3.7|3.8] venv
Expand All @@ -50,8 +58,6 @@ pipenv install

### Install on MacOS
```bash
git clone git@github.com:purwowd/microservices-scaffold.git
cd microservices-scaffold
virtualenv -p python3 venv
source venv/bin/activate
pip3 install -r requirements.txt
Expand Down Expand Up @@ -123,9 +129,8 @@ You can dockerize this microservice with these steps:
You can run this microservice in a Kubernetes cluster with:

kubectl apply -f service.yaml

See a simple tutorial in [the doc](https://microservices-scaffold.readthedocs.io/en/latest/runinkubernetes.html)

## How to contrib

https://github.com/python-microservices/microservices-scaffold/blob/master/CONTRIBUTING.md
# How To contribute

We appreciate opening issues and pull requests to make PyMS even more stable & useful! See [This doc](CONTRIBUTING.md)
for more details
4 changes: 2 additions & 2 deletions config-docker.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ pyms:
requests:
data: ""
swagger:
path: "swagger"
path: "project/swagger"
file: "swagger.yaml"
url: "/ui/"
project_dir: "project.views"
Expand All @@ -15,7 +15,7 @@ pyms:
DEBUG: false
TESTING: false
APP_NAME: Films&Actors
APPLICATION_ROOT : ""
APPLICATION_ROOT : "/"
SQLALCHEMY_TRACK_MODIFICATIONS: true
SECRET_KEY: "gjr39dkjn344_!67#"
DATABASE: db.sqlite3
Expand Down
8 changes: 4 additions & 4 deletions config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ pyms:
requests:
data: ""
swagger:
path: "swagger"
path: "project/swagger"
file: "swagger.yaml"
url: "/ui/"
project_dir: "project.views"
Expand All @@ -12,11 +12,11 @@ pyms:
host: "localhost"
component_name: "Python Microservice"
config:
DEBUG: false
DEBUG: true
TESTING: false
APP_NAME: Films&Actors
APPLICATION_ROOT : ""
APPLICATION_ROOT : "/"
SQLALCHEMY_TRACK_MODIFICATIONS: true
SECRET_KEY: "gjr39dkjn344_!67#"
DATABASE: db.sqlite3
SQLALCHEMY_DATABASE_URI: sqlite:///db.sqlite3
SQLALCHEMY_DATABASE_URI: sqlite:///project/db.sqlite3
12 changes: 11 additions & 1 deletion manage.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,17 @@
# encoding: utf-8
from flask_script import Manager

from project.app import create_app
from project.app import MyMicroservice


def create_app():
"""Initialize the Flask app, register blueprints and intialize all libraries like Swagger, database, the trace system...
return the app and the database objects.
:return:
"""
ms = MyMicroservice(path=__file__)
return ms.create_app()


app = create_app()

Expand Down
9 changes: 0 additions & 9 deletions project/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,12 +71,3 @@ def init_logger(self) -> None:
}

logging.config.dictConfig(LOGGING)


def create_app():
"""Initialize the Flask app, register blueprints and intialize all libraries like Swagger, database, the trace system...
return the app and the database objects.
:return:
"""
ms = MyMicroservice(path=__file__)
return ms.create_app()
8 changes: 4 additions & 4 deletions tests/config-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ pyms:
requests:
data: ""
swagger:
path: "swagger"
path: "project/swagger"
file: "swagger.yaml"
url: "/ui/"
project_dir: "project.views"
Expand All @@ -12,12 +12,12 @@ pyms:
host: "localhost"
component_name: "Python Microservice2"
config:
DEBUG: false
DEBUG: true
TESTING: true
TEST_VAR: "1234"
APP_NAME: Films&Actors
APPLICATION_ROOT : ""
APPLICATION_ROOT : "/"
SQLALCHEMY_TRACK_MODIFICATIONS: true
SECRET_KEY: "gjr39dkjn344_!67#"
DATABASE: db.sqlite3
SQLALCHEMY_DATABASE_URI: sqlite:///db.sqlite3
SQLALCHEMY_DATABASE_URI: sqlite:///project/db_tests.sqlite3
58 changes: 58 additions & 0 deletions tests/conftest.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import os

import pytest

from manage import create_app
from project.models.init_db import db as _db


def conf_environment():
if not os.environ.get("CONFIGMAP_FILE", False):
os.environ["CONFIGMAP_FILE"] = os.path.join(os.path.dirname(os.path.abspath(__file__)), "config-tests.yml")


@pytest.fixture(scope="session")
def app():
conf_environment()
app = create_app()
return app


@pytest.fixture(scope="module")
def client(app, db):
"""A test client for the app."""
return app.test_client()


@pytest.fixture(scope="module")
def base_url(app):
"""Base url of the service."""
return app.config["APPLICATION_ROOT"]


@pytest.fixture(scope="session")
def db(app, request):
def teardown():
_db.drop_all()

_db.app = app
_db.init_app(app)
_db.create_all()

request.addfinalizer(teardown)

return _db


@pytest.fixture(scope="session")
def db_handler(app_handler, request):
def teardown():
_db.drop_all()

_db.app = app_handler
_db.init_app(app_handler)
_db.create_all()

request.addfinalizer(teardown)

return _db
113 changes: 48 additions & 65 deletions tests/test_views.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,7 @@
import json
import os
import pytest
from typing import Dict, List, Union, Text
from pyms.constants import CONFIGMAP_FILE_ENVIRONMENT
from pyms.flask.app import config

from project.app import MyMicroservice
from pyms.flask.app import config

backup_config = config()

Expand All @@ -17,63 +13,50 @@ def _format_response(response: Text = "") -> Union[List, Dict]:
return json.loads(response)


class TestProject:
BASE_DIR = os.path.dirname(os.path.abspath(__file__))

@pytest.fixture(scope="session")
def microservice(self):
os.environ[CONFIGMAP_FILE_ENVIRONMENT] = os.path.join(self.BASE_DIR, "config-tests.yml")
ms = MyMicroservice(path=os.path.join(os.path.dirname(os.path.dirname(__file__)), "project", "test_views.py"))
ms.app = ms.create_app()
ms.base_url = ms.app.config["APPLICATION_ROOT"]
ms.client = ms.app.test_client()
return ms

def test_home(self, microservice):
response = microservice.client.get('/')
assert 404 == response.status_code

def test_healthcheck(self, microservice):
response = microservice.client.get('/healthcheck')
assert 200 == response.status_code

def test_list_actors(self, microservice):
response = microservice.client.get('/actors'.format(base_url=microservice.base_url))
assert 200 == response.status_code

def test_list_films(self, microservice):
response = microservice.client.get('/films'.format(base_url=microservice.base_url))
assert 200 == response.status_code

def test_pyms(self, microservice):
assert "1234" == microservice.app.config["TEST_VAR"]

def test_create_film(self, microservice):
name = "Avengers"
pubDate = "2020-01-20"
cast = [{"id": 1, "name": "Robert", "surname": "Downey Jr."}, {"id": 2, "name": "Chris", "surname": "Hemsworth"}]
response = microservice.client.post('/films'.format(
base_url=microservice.base_url),
data=json.dumps(dict(name=name, pubDate=pubDate, cast=cast)),
content_type='application/json'
)
assert 200 == response.status_code
assert name == _format_response(response.data)["name"]

def test_create_actor(self, microservice):
response = microservice.client.get('/actors'.format(base_url=microservice.base_url))
assert 200 == response.status_code

def test_pyms(self, microservice):
assert "1234" == microservice.app.config["TEST_VAR"]

def test_create_view(self, microservice):
name = "Robert"
surname = "Downey Jr."
response = microservice.client.post('/actors'.format(
base_url=microservice.base_url),
data=json.dumps(dict(name=name, surname=surname)),
content_type='application/json'
)
assert 200 == response.status_code
assert name == _format_response(response.data)["name"]
def test_home(client):
response = client.get('/')
assert 404 == response.status_code


def test_healthcheck(client):
response = client.get('/healthcheck')
assert 200 == response.status_code


def test_list_actors(client, base_url):
response = client.get('{base_url}actors'.format(base_url=base_url))
assert 200 == response.status_code


def test_list_films(client, base_url):
response = client.get('{base_url}films'.format(base_url=base_url))
assert 200 == response.status_code


def test_pyms(app):
assert "1234" == app.config["TEST_VAR"]


def test_create_film(client, base_url):
name = "Avengers"
pubDate = "2020-01-20"
cast = [{"id": 1, "name": "Robert", "surname": "Downey Jr."}, {"id": 2, "name": "Chris", "surname": "Hemsworth"}]
response = client.post('{base_url}films'.format(
base_url=base_url),
data=json.dumps(dict(name=name, pubDate=pubDate, cast=cast)),
content_type='application/json'
)
assert 200 == response.status_code
assert name == _format_response(response.data)["name"]


def test_create_view(client, base_url):
name = "Robert"
surname = "Downey Jr."
response = client.post('{base_url}actors'.format(
base_url=base_url),
data=json.dumps(dict(name=name, surname=surname)),
content_type='application/json'
)
assert 200 == response.status_code
assert name == _format_response(response.data)["name"]