Skip to content

Commit

Permalink
Merge pull request #96 from python-microservices/fix/connexion_path
Browse files Browse the repository at this point in the history
Fix connexion issue #1135
  • Loading branch information
alexppg committed Mar 13, 2020
2 parents 3495104 + 646f059 commit f70cc26
Show file tree
Hide file tree
Showing 9 changed files with 162 additions and 27 deletions.
35 changes: 18 additions & 17 deletions pyms/flask/services/driver.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,24 +13,25 @@ class DriverService:
"""All services must inherit from this class. This set the configuration. If we have got his config file:
```
pyms:
metrics: true
requests:
data: data
swagger:
path: ""
file: "swagger.yaml"
tracer:
client: "jaeger"
host: "localhost"
component_name: "Python Microservice"
my-ms:
DEBUG: true
TESTING: true
services:
metrics: true
requests:
data: data
swagger:
path: ""
file: "swagger.yaml"
tracer:
client: "jaeger"
host: "localhost"
component_name: "Python Microservice"
config:
DEBUG: true
TESTING: true
```
* `pyms` block is the default key to load in the pyms.flask.app.create_app.Microservice class.
* `metrics`: is set as the service `pyms.metrics`
* `swagger`: is set as the service `pyms.swagger`
* `tracer`: is set as the service `pyms.tracer`
* `pyms.services` block is the default key to load in the pyms.flask.app.create_app.Microservice class.
* `metrics`: is set as the service `pyms.services.metrics`
* `swagger`: is set as the service `pyms.services.swagger`
* `tracer`: is set as the service `pyms.services.tracer`
"""
service = ""
config = None
Expand Down
3 changes: 3 additions & 0 deletions pyms/flask/services/metrics.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,9 @@ def after_request(response):


class Service(DriverService):
"""
Adds [Prometheus](https://prometheus.io/) metrics using the [Prometheus Client Library](https://github.com/prometheus/client_python).
"""
service = "metrics"

def __init__(self, *args, **kwargs):
Expand Down
5 changes: 5 additions & 0 deletions pyms/flask/services/requests.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,11 @@ def wrapper(*args, **kwargs):


class Service(DriverService):
"""
Extend the [requests library](http://docs.python-requests.org/en/master/) with trace headers and parsing JSON objects.
Encapsulate common rest operations between business services propagating trace headers if set up.
All default values keys are created as class attributes in `DriverService`
"""
service = "requests"
default_values = {
"data": "",
Expand Down
51 changes: 43 additions & 8 deletions pyms/flask/services/swagger.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,10 @@ class Service(DriverService):
* **file:** The name of you swagger yaml file. The default value is `swagger.yaml`
* **url:** The url where swagger run in your server. The default value is `/ui/`.
* **project_dir:** Relative path of the project folder to automatic routing,
see [this link for more info](https://github.com/zalando/connexion#automatic-routing). The default value is `project`
see [this link for more info](https://github.com/zalando/connexion#automatic-routing).
The default value is `project`
All default values keys are created as class attributes in `DriverService`
"""
service = "swagger"
default_values = {
Expand All @@ -29,16 +32,48 @@ class Service(DriverService):
}

def init_app(self, config, path):
"""
Initialize Connexion App. See more info in [Connexion Github](https://github.com/zalando/connexion)
:param config: The Flask configuration defined in the config.yaml:
```yaml
pyms:
services:
requests: true
swagger:
path: ""
file: "swagger.yaml"
config: <!--
DEBUG: true
TESTING: false
APP_NAME: "Python Microservice"
APPLICATION_ROOT: ""
```
:param path: The current path where is instantiated Microservice class:
```
Microservice(path=__file__)
^^^^--- This param
```
:return: Flask
"""
check_package_exists("connexion")
specification_dir = self.path
if not os.path.isabs(self.path):
specification_dir = os.path.join(path, self.path)

app = connexion.App(__name__,
specification_dir=os.path.join(path, self.path),
specification_dir=specification_dir,
resolver=RestyResolver(self.project_dir))
app.add_api(
self.file,
arguments={'title': config.APP_NAME},
base_path=config.APPLICATION_ROOT,
options={"swagger_url": self.url}
)

params = {
"specification": self.file,
"arguments": {'title': config.APP_NAME},
"options": {"swagger_url": self.url},
}
# Fix Connexion issue https://github.com/zalando/connexion/issues/1135
if config.APPLICATION_ROOT and config.APPLICATION_ROOT != "/":
params["base_path"] = config.APPLICATION_ROOT

app.add_api(**params)
# Invert the objects, instead connexion with a Flask object, a Flask object with
application = app.app
application.connexion_app = app
Expand Down
4 changes: 4 additions & 0 deletions pyms/flask/services/tracer.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,10 @@ def inject_span_in_headers(headers):


class Service(DriverService):
"""
Add trace to all executions with [opentracing](https://github.com/opentracing-contrib/python-flask).
All default values keys are created as class attributes in `DriverService`
"""
service = "tracer"
default_values = {
"client": DEFAULT_CLIENT,
Expand Down
2 changes: 1 addition & 1 deletion tests/config-tests-swagger.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,4 @@ pyms:
DEBUG: true
TESTING: true
APP_NAME: "Python Microservice Swagger"
APPLICATION_ROOT: /
APPLICATION_ROOT: "/test-api-path"
13 changes: 13 additions & 0 deletions tests/config-tests-swagger_no_abs_path.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
pyms:
services:
metrics:
enabled: false
swagger:
path: "swagger_for_tests"
file: "swagger.yaml"
url: "ws-doc2/"
config:
DEBUG: true
TESTING: true
APP_NAME: "Python Microservice Swagger2"
APPLICATION_ROOT: "/test-api-path2"
48 changes: 48 additions & 0 deletions tests/swagger_for_tests/swagger.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
---
swagger: "2.0"
info:
description: "This is a sample server Test server"
version: "1.0.0"
title: "Swagger Test 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:
/no-abs-path:
get:
tags:
- "test"
summary: "Example endpoint"
description: ""
operationId: "home"
consumes:
- "application/json"
produces:
- "application/json"
responses:
200:
description: "Example"
405:
description: "Invalid input"
x-swagger-router-controller: "tests.test_flask"
externalDocs:
description: "Find out more about Swagger"
url: "http://swagger.io"
28 changes: 27 additions & 1 deletion tests/test_swagger.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,5 +21,31 @@ def setUp(self):
self.assertEqual("Python Microservice Swagger", self.app.config["APP_NAME"])

def test_default(self):
response = self.client.get('/ws-doc/')
response = self.client.get('/test-api-path/ws-doc/')
self.assertEqual(200, response.status_code)

def test_home(self):
response = self.client.get('/test-api-path/')
self.assertEqual(200, response.status_code)


class SwaggerNoAbsPathTests(unittest.TestCase):
"""Test common rest operations wrapper.
"""

BASE_DIR = os.path.dirname(os.path.abspath(__file__))

def setUp(self):
os.environ[CONFIGMAP_FILE_ENVIRONMENT] = os.path.join(self.BASE_DIR, "config-tests-swagger_no_abs_path.yml")
ms = MyMicroserviceNoSingleton(path=__file__)
self.app = ms.create_app()
self.client = self.app.test_client()
self.assertEqual("Python Microservice Swagger2", self.app.config["APP_NAME"])

def test_default(self):
response = self.client.get('/test-api-path2/ws-doc2/')
self.assertEqual(200, response.status_code)

def test_home(self):
response = self.client.get('/test-api-path2/no-abs-path')
self.assertEqual(200, response.status_code)

0 comments on commit f70cc26

Please sign in to comment.