Skip to content

Commit

Permalink
Merge branch 'develop'
Browse files Browse the repository at this point in the history
  • Loading branch information
avara1986 committed May 6, 2018
2 parents 6a89da3 + ed7b5d7 commit b245cfc
Show file tree
Hide file tree
Showing 10 changed files with 165 additions and 201 deletions.
4 changes: 2 additions & 2 deletions docs/configuration.rst
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ Documentation
The Microservice create a URL to inspect the Swagger documentation of the api in:

.. code-block:: bash
localhost:5000/[APPLICATION_ROOT]/apidocs/
localhost:5000/[APPLICATION_ROOT]/ui/
Our API Rest work with `Flasgger <https://github.com/rochacbruno/flasgger>`_. You can see Flasgger docs or the official
Our API Rest work with `connexion <http://connexion.readthedocs.io>`_. You can see connexion docs or the official
`Swagger documentation <https://swagger.io/specification/>`_ to add the syntax to your APIS and create your Swagger docs
4 changes: 3 additions & 1 deletion docs/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,13 @@ Python Microservices

Stack
-----
* `connexion <http://connexion.readthedocs.io>`_
* `Flask <https://github.com/pallets/flask>`_
* `SQLAlchemy <https://www.sqlalchemy.org/>`_
* `Flask-SQLAlchemy <http://flask-sqlalchemy.pocoo.org/2.3/>`_
* `Flasgger <https://github.com/rochacbruno/flasgger>`_
* `Flask-Injector <https://github.com/alecthomas/flask_injector>`_
* `Flask-Script <https://flask-script.readthedocs.io/en/latest/>`_
* `Opentracing <https://github.com/opentracing-contrib/python-flask>`_


Content
Expand Down
20 changes: 14 additions & 6 deletions docs/structure.rst
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,18 @@ You have a project with this structure:
project
├ __init__.py
├ config.py
├ views
│ ├ __init__.py
│ └ views.py
├ models
│ ├ __init__.py
│ └ models.py
└ tests
└ test_views.py
├ swagger
│ └ swagger.yaml
├ tests
│ └ test_views.py
└views
├ __init__.py
└ views.py
manager.py
----------
Expand Down Expand Up @@ -80,6 +84,10 @@ See :doc:`configuration </configuration>` section

project/views
~~~~~~~~~~~~~
use views.py or create your file. You must add after register the view blueprint in `project/views/__init__.py`.
use views.py or create your file.

swagger/swagger.yaml
~~~~~~~~~~~~~
Use to define your rest behaviour, endpoints and routes. See `connexion <http://connexion.readthedocs.io>`_ docs to how add new views


108 changes: 20 additions & 88 deletions project/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,7 @@
import logging
import os

from flasgger import Swagger
from flask import Flask
import connexion
from flask_injector import FlaskInjector
from injector import Injector

Expand All @@ -16,116 +15,49 @@

__author__ = "Alberto Vara"
__email__ = "a.vara.1986@gmail.com"
__version__ = "0.1"
__version__ = "0.2"

logger = logging.getLogger('jaeger_tracing')
logger.setLevel(logging.DEBUG)

ENVIRONMENT = os.environ.get("ENVIRONMENT", "default")

SWAGGER_CONFIG = {
"headers": [
],
"specs": [
{
"endpoint": 'apispec_1',
"route": '{application_root}/apispec_1.json',
"rule_filter": lambda rule: True, # all in
"model_filter": lambda tag: True, # all in
}
],
"info": {
"title": "API ",
"description": "API para...",
"contact": {
"responsibleOrganization": "ME",
"responsibleDeveloper": "Me",
"email": "me@me.com",
},
"version": "0.0.1"
},
"securityDefinitions": {
"APIKeyHeader": {"type": "apiKey", "name": "Authorization", "in": "header"},
},
"static_url_path": "{application_root}/flasgger_static",
"swagger_ui": True,
"uiversion": 2,
"specs_route": "/apidocs/",
"basePath": "{application_root}"
}


class PrefixMiddleware(object):
"""Set a prefix path to all routes. This action is needed if you have a stack of microservices and each of them
exist in the same domain but different path. Por example:
* mydomain.com/ms1/
* mydomain.com/ms2/
"""

def __init__(self, app, prefix=''):
self.app = app
self.prefix = prefix

def __call__(self, environ, start_response):
if environ['PATH_INFO'].startswith(self.prefix):
environ['PATH_INFO'] = environ['PATH_INFO'][len(self.prefix):]
environ['SCRIPT_NAME'] = self.prefix
return self.app(environ, start_response)
elif environ['PATH_INFO'].startswith("/healthcheck"):
return self.app(environ, start_response)
else:
start_response('404', [('Content-Type', 'text/plain')])
return ["This url does not belong to the app.".encode()]


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:
"""

from project.views import views_bp as views_blueprint
environment = os.environ.get("ENVIRONMENT", "default")

app = Flask(__name__)
app.config.from_object(CONFIG[environment])
app.wsgi_app = PrefixMiddleware(app.wsgi_app, prefix=app.config["APPLICATION_ROOT"])
app = connexion.App(__name__, specification_dir='./swagger/')
# app.app.json_encoder = encoder.JSONEncoder

db.init_app(app)
app.add_api('swagger.yaml',
arguments={'title': 'Swagger Example Project'},
base_path=CONFIG[environment].APPLICATION_ROOT)

# Initialize Swagger
SWAGGER_CONFIG["specs"][0]["route"] = SWAGGER_CONFIG["specs"][0]["route"].format(
application_root=app.config["APPLICATION_ROOT"]
)
SWAGGER_CONFIG["static_url_path"] = SWAGGER_CONFIG["static_url_path"].format(
application_root=app.config["APPLICATION_ROOT"]
)
SWAGGER_CONFIG["specs_route"] = SWAGGER_CONFIG["specs_route"].format(
application_root=app.config["APPLICATION_ROOT"]
)
SWAGGER_CONFIG["basePath"] = SWAGGER_CONFIG["basePath"].format(
application_root=app.config["APPLICATION_ROOT"]
)
Swagger(app, config=SWAGGER_CONFIG)
application = app.app
application.config.from_object(CONFIG[environment])
db.init_app(application)

# Initialize Blueprints
app.register_blueprint(views_blueprint)
app.register_blueprint(healthcheck_blueprint)
application.register_blueprint(healthcheck_blueprint)

# Inject Modules
# Inject Modules
if not app.config["TESTING"] and not app.config["DEBUG"]:
if not application.config["TESTING"] and not application.config["DEBUG"]:
log_handler = logging.StreamHandler()
formatter = CustomJsonFormatter('(timestamp) (level) (name) (module) (funcName) (lineno) (message)')
formatter.add_service_name(app.config["APP_NAME"])
tracer = TracerModule(app)
formatter.add_service_name(application.config["APP_NAME"])
tracer = TracerModule(application)
injector = Injector([tracer])
FlaskInjector(app=app, injector=injector)
FlaskInjector(app=application, injector=injector)
formatter.add_trace_span(tracer.tracer)
log_handler.setFormatter(formatter)
app.logger.addHandler(log_handler)
app.logger.setLevel(logging.INFO)
application.logger.addHandler(log_handler)
application.logger.setLevel(logging.INFO)

with app.test_request_context():
with application.test_request_context():
db.create_all()
return app, db

return application, db
89 changes: 89 additions & 0 deletions project/swagger/swagger.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
---
swagger: "2.0"
info:
description: "This is a sample server Color server. You can find out more about Swagger at [http://swagger.io](http://swagger.io) or on [irc.freenode.net, #swagger](http://swagger.io/irc/). For this sample, you can use the api key `special-key` to test the authorization filters."
version: "1.0.0"
title: "Swagger Color list"
termsOfService: "http://swagger.io/terms/"
contact:
email: "apiteam@swagger.io"
license:
name: "Apache 2.0"
url: "http://www.apache.org/licenses/LICENSE-2.0.html"
tags:
- name: "colors"
description: "Everything about your colors"
externalDocs:
description: "Find out more"
url: "http://swagger.io"
- name: "store"
description: "Example endpoint list of colors"
- name: "user"
description: "Operations about user"
externalDocs:
description: "Find out more about our store"
url: "http://swagger.io"
schemes:
- "http"
paths:
/:
post:
tags:
- "colors"
summary: "Example endpoint return create a color"
description: ""
operationId: "create_view"
consumes:
- "application/json"
produces:
- "application/json"
parameters:
- in: "body"
name: "name"
description: "Pet object that needs to be added to the store"
required: true
schema:
$ref: "#/definitions/Color"
responses:
200:
description: "The color created"
schema:
$ref: '#/definitions/Color'
405:
description: "Invalid input"
x-swagger-router-controller: "project.views.views"
get:
tags:
- "colors"
summary: "Example endpoint return a list of colors by palette"
description: ""
operationId: "list_view"
consumes:
- "application/json"
produces:
- "application/json"
responses:
200:
description: "A list of colors (may be filtered by palette)"
schema:
$ref: '#/definitions/Color'
400:
description: "Invalid ID supplied"
404:
description: "Pet not found"
405:
description: "Validation exception"
x-swagger-router-controller: "project.views.views"
definitions:
Color:
type: "object"
properties:
id:
type: "string"
timestamp:
type: "string"
name:
type: "string"
externalDocs:
description: "Find out more about Swagger"
url: "http://swagger.io"
6 changes: 5 additions & 1 deletion project/tests/test_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,10 @@ def test_list_view(self):

def test_create_view(self):
name = "blue"
response = self.client.post('{base_url}/'.format(base_url=self.base_url), data={"name": name})
response = self.client.post('{base_url}/'.format(
base_url=self.base_url),
data=json.dumps(dict(name=name)),
content_type='application/json'
)
self.assertEqual(response.status_code, 200)
self.assertEqual(_format_response(response.data)["name"], name)
8 changes: 1 addition & 7 deletions project/views/__init__.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,2 @@
# coding=utf-8
from __future__ import unicode_literals, print_function, absolute_import, division

from flask import Blueprint

views_bp = Blueprint('views', __name__, static_url_path='/static')

from project.views import views
from __future__ import unicode_literals, print_function, absolute_import, division

0 comments on commit b245cfc

Please sign in to comment.