8000 Merge pull request #96 from python-microservices/fix/connexion_path · python-microservices/pyms@13412d4 · GitHub
[go: up one dir, main page]

Skip to content

Commit 13412d4

Browse files
alexppgavara1986
authored andcommitted
Merge pull request #96 from python-microservices/fix/connexion_path
Fix connexion issue #1135
1 parent 3495104 commit 13412d4

File tree

9 files changed

+162
-27
lines changed

9 files changed

+162
-27
lines changed

pyms/flask/services/driver.py

Lines changed: 18 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -13,24 +13,25 @@ class DriverService:
1313
"""All services must inherit from this class. This set the configuration. If we have got his config file:
1414
```
1515
pyms:
16-
metrics: true
17-
requests:
18-
data: data
19-
swagger:
20-
path: ""
21-
file: "swagger.yaml"
22-
tracer:
23-
client: "jaeger"
24-
host: "localhost"
25-
component_name: "Python Microservice"
26-
my-ms:
27-
DEBUG: true
28-
TESTING: true
16+
services:
17+
metrics: true
18+
requests:
19+
data: data
20+
swagger:
21+
path: ""
22+
file: "swagger.yaml"
23+
tracer:
24+
client: "jaeger"
25+
host: "localhost"
26+
component_name: "Python Microservice"
27+
config:
28+
DEBUG: true
29+
TESTING: true
2930
```
30-
* `pyms` block is the default key to load in the pyms.flask.app.create_app.Microservice class.
31-
* `metrics`: is set as the service `pyms.metrics`
32-
* `swagger`: is set as the service `pyms.swagger`
33-
* `tracer`: is set as the service `pyms.tracer`
31+
* `pyms.services` block is the default key to load in the pyms.flask.app.create_app.Microservice class.
32+
* `metrics`: is set as the service `pyms.services.metrics`
33+
* `swagger`: is set as the service `pyms.services.swagger`
34+
* `tracer`: is set as the service `pyms.services.tracer`
3435
"""
3536
service = ""
3637
config = None

pyms/flask/services/metrics.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,9 @@ def after_request(response):
3535

3636

3737
class Service(DriverService):
38+
"""
39+
Adds [Prometheus](https://prometheus.io/) metrics using the [Prometheus Client Library](https://github.com/prometheus/client_python).
40+
"""
3841
service = "metrics"
3942

4043
def __init__(self, *args, **kwargs):

pyms/flask/services/requests.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,11 @@ def wrapper(*args, **kwargs):
3939

4040

4141
class Service(DriverService):
42+
"""
43+
Extend the [requests library](http://docs.python-requests.org/en/master/) with trace headers and parsing JSON objects.
44+
Encapsulate common rest operations between business services propagating trace headers if set up.
45+
All default values keys are created as class attributes in `DriverService`
46+
"""
4247
service = "requests"
4348
default_values = {
4449
"data": "",

pyms/flask/services/swagger.py

Lines changed: 43 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,10 @@ class Service(DriverService):
1818
* **file:** The name of you swagger yaml file. The default value is `swagger.yaml`
1919
* **url:** The url where swagger run in your server. The default value is `/ui/`.
2020
* **project_dir:** Relative path of the project folder to automatic routing,
21-
see [this link for more info](https://github.com/zalando/connexion#automatic-routing). The default value is `project`
21+
see [this link for more info](https://github.com/zalando/connexion#automatic-routing).
22+
The default value is `project`
23+
24+
All default values keys are created as class attributes in `DriverService`
2225
"""
2326
service = "swagger"
2427
default_values = {
@@ -29,16 +32,48 @@ class Service(DriverService):
2932
}
3033

3134
def init_app(self, config, path):
35+
"""
36+
Initialize Connexion App. See more info in [Connexion Github](https://github.com/zalando/connexion)
37+
:param config: The Flask configuration defined in the config.yaml:
38+
```yaml
39+
pyms:
40+
services:
41+
requests: true
42+
swagger:
43+
path: ""
44+
file: "swagger.yaml"
45+
config: <!--
46+
DEBUG: true
47+
TESTING: false
48+
APP_NAME: "Python Microservice"
49+
APPLICATION_ROOT: ""
50+
```
51+
:param path: The current path where is instantiated Microservice class:
52+
```
53+
Microservice(path=__file__)
54+
^^^^--- This param
55+
```
56+
:return: Flask
57+
"""
3258
check_package_exists("connexion")
59+
specification_dir = self.path
60+
if not os.path.isabs(self.path):
61+
specification_dir = os.path.join(path, self.path)
62+
3363
app = connexion.App(__name__,
34-
specification_dir=os.path.join(path, self.path),
64+
specification_dir=specification_dir,
3565
resolver=RestyResolver(self.project_dir))
36-
app.add_api(
37-
self.file,
38-
arguments={'title': config.APP_NAME},
39-
base_path=config.APPLICATION_ROOT,
40-
options={"swagger_url": self.url}
41-
)
66+
67+
params = {
68+
"specification": self.file,
69+
"arguments": {'title': config.APP_NAME},
70+
"options": {"swagger_url": self.url},
71+
}
72+
# Fix Connexion issue https://github.com/zalando/connexion/issues/1135
73+
if config.APPLICATION_ROOT and config.APPLICATION_ROOT != "/":
74+
params["base_path"] = config.APPLICATION_ROOT
75+
76+
app.add_api(**params)
4277
# Invert the objects, instead connexion with a Flask object, a Flask object with
4378
application = app.app
4479
application.connexion_app = app

pyms/flask/services/tracer.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,10 @@ def inject_span_in_headers(headers):
3838

3939

4040
class Service(DriverService):
41+
"""
42+
Add trace to all executions with [opentracing](https://github.com/opentracing-contrib/python-flask).
43+
All default values keys are created as class attributes in `DriverService`
44+
"""
4145
service = "tracer"
4246
default_values = {
4347
"client": DEFAULT_CLIENT,

tests/config-tests-swagger.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,4 +10,4 @@ pyms:
1010
DEBUG: true
1111
TESTING: true
1212
APP_NAME: "Python Microservice Swagger"
13-
APPLICATION_ROOT: /
13+
APPLICATION_ROOT: "/test-api-path"
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
pyms:
2+
services:
3+
metrics:
4+
enabled: false
5+
swagger:
6+
path: "swagger_for_tests"
7+
file: "swagger.yaml"
8+
url: "ws-doc2/"
9+
config:
10+
DEBUG: true
11+
TESTING: true
12+
APP_NAME: "Python Microservice Swagger2"
13+
APPLICATION_ROOT: "/test-api-path2"

tests/swagger_for_tests/swagger.yaml

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
---
2+
swagger: "2.0"
3+
info:
4+
description: "This is a sample server Test server"
5+
version: "1.0.0"
6+
title: "Swagger Test list"
7+
termsOfService: "http://swagger.io/terms/"
8+
contact:
9+
email: "apiteam@swagger.io"
10+
license:
11+
name: "Apache 2.0"
12+
url: "http://www.apache.org/licenses/LICENSE-2.0.html"
13+
tags:
14+
- name: "colors"
15+
description: "Everything about your colors"
16+
externalDocs:
17+
description: "Find out more"
18+
url: "http://swagger.io"
19+
- name: "store"
20+
description: "Example endpoint list of colors"
21+
- name: "user"
22+
description: "Operations about user"
23+
externalDocs:
24+
description: "Find out more about our store"
25+
url: "http://swagger.io"
26+
schemes:
27+
- "http"
28+
paths:
29+
/no-abs-path:
30+
get:
31+
tags:
32+
- "test"
33+
summary: "Example endpoint"
34+
description: ""
35+
operationId: "home"
36+
consumes:
37+
- "application/json"
38+
produces:
39+
- "application/json"
40+
responses:
41+
200:
42+
description: "Example"
43+
405:
44+
description: "Invalid input"
45+
x-swagger-router-controller: "tests.test_flask"
46+
externalDocs:
47+
description: "Find out more about Swagger"
48+
url: "http://swagger.io"

tests/test_swagger.py

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,5 +21,31 @@ def setUp(self):
2121
self.assertEqual("Python Microservice Swagger", self.app.config["APP_NAME"])
2222

2323
def test_default(self):
24-
response = self.client.get('/ws-doc/')
24+
response = self.client.get('/test-api-path/ws-doc/')
25+
self.assertEqual(200, response.status_code)
26+
27+
def test_home(self):
28+
response = self.client.get('/test-api-path/')
29+
self.assertEqual(200, response.status_code)
30+
31+
32+
class SwaggerNoAbsPathTests(unittest.TestCase):
33+
"""Test common rest operations wrapper.
34+
"""
35+
36+
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
37+
38+
def setUp(self):
39+
os.environ[CONFIGMAP_FILE_ENVIRONMENT] = os.path.join(self.BASE_DIR, "config-tests-swagger_no_abs_path.yml")
40+
ms = MyMicroserviceNoSingleton(path=__file__)
41+
self.app = ms.create_app()
42+
self.client = self.app.test_client()
43+
self.assertEqual("Python Microservice Swagger2", self.app.config["APP_NAME"])
44+
45+
def test_default(self):
46+
response = self.client.get('/test-api-path2/ws-doc2/')
47+
self.assertEqual(200, response.status_code)
48+
49+
def test_home(self):
50+
response = self.client.get('/test-api-path2/no-abs-path')
2551
self.assertEqual(200, response.status_code)

0 commit comments

Comments
 (0)
0