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
2 changes: 1 addition & 1 deletion examples/microservice_configuration/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ pyms:
swagger:
path: ""
file: "swagger.yaml"
my-configure-microservice:
ms:
DEBUG: true
TESTING: false
APP_NAME: "Python Microservice"
Expand Down
1 change: 1 addition & 0 deletions examples/microservice_swagger/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ pyms:
swagger:
path: ""
file: "swagger.yaml"
url: "ws-doc/"
my-ms:
DEBUG: true
TESTING: false
Expand Down
4 changes: 0 additions & 4 deletions pyms/config/confile.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,6 @@ def __init__(self, *args, **kwargs):
else:
raise ConfigDoesNotFoundException("Configuration file not found")

logger.debug("[CONF] INIT: Settings {kwargs}".format(
kwargs=kwargs,
))

config = dict(self.normalize_config(config))
_ = [setattr(self, k, v) for k, v in config.items()]
super(ConfFile, self).__init__(config)
Expand Down
15 changes: 2 additions & 13 deletions pyms/flask/app/create_app.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
import os
from typing import Text

import connexion
from flask import Flask
from flask_opentracing import FlaskTracing

Expand Down Expand Up @@ -50,7 +49,7 @@ def __init__(self, *args, **kwargs):

def init_services(self):
service_manager = ServicesManager()
for service_name, service in service_manager.get_services():
for service_name, service in service_manager.get_services(memoize=self._singleton):
setattr(self, service_name, service)

def init_libs(self):
Expand Down Expand Up @@ -81,17 +80,7 @@ def init_logger(self):

def init_app(self) -> Flask:
if self._exists_service("swagger"):
check_package_exists("connexion")
app = connexion.App(__name__, specification_dir=os.path.join(self.path, self.swagger.path))
app.add_api(
self.swagger.file,
arguments={'title': self.config.APP_NAME},
base_path=self.config.APPLICATION_ROOT
)

# Invert the objects, instead connexion with a Flask object, a Flask object with
application = app.app
application.connexion_app = app
application = self.swagger.init_app(config=self.config, path=self.path)
else:
check_package_exists("flask")
application = Flask(__name__, static_folder=os.path.join(self.path, 'static'),
Expand Down
6 changes: 3 additions & 3 deletions pyms/flask/services/driver.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ class DriverService:

def __init__(self, service, *args, **kwargs):
self.service = ".".join([service, self.service])
self.config = get_conf(service=self.service, empty_init=True)
self.config = get_conf(service=self.service, empty_init=True, memoize=kwargs.get("memoize", True))
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@miguelgrubin this was the problem 😉


def __getattr__(self, attr, *args, **kwargs):
config_attribute = getattr(self.config, attr)
Expand All @@ -31,8 +31,8 @@ def __init__(self, service=None):
self.service = (service if service else SERVICE_BASE)
self.config = get_conf(service=self.service, empty_init=True, memoize=False)

def get_services(self):
return ((k, self.get_service(k)) for k in self.config.__dict__.keys() if k not in ['empty_init', ])
def get_services(self, memoize):
return ((k, self.get_service(k, memoize=memoize)) for k in self.config.__dict__.keys() if k not in ['empty_init', ])

def get_service(self, service, *args, **kwargs):
service_object = import_from("pyms.flask.services.{}".format(service), "Service")
Expand Down
26 changes: 9 additions & 17 deletions pyms/flask/services/requests.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@

DEFAULT_RETRIES = 3

DEFAULTstatus_retries = (500, 502, 504)
DEFAULT_STATUS_RETRIES = (500, 502, 504)


def retry(f):
Expand All @@ -41,20 +41,12 @@ def wrapper(*args, **kwargs):
class Service(DriverService):
service = "requests"
default_values = {
"data": ""
"data": "",
"retries": DEFAULT_RETRIES,
"status_retries": DEFAULT_STATUS_RETRIES,
"propagate_headers": False,
}
tracer = None
retries = DEFAULT_RETRIES
status_retries = DEFAULTstatus_retries
_propagate_headers = False

def __init__(self, service, *args, **kwargs):
"""Initialization for trace headers propagation"""
super().__init__(service, *args, **kwargs)
if self.exists_config():
self.retries = self.config.retries or DEFAULT_RETRIES
self.status_retries = self.config.status_retries or DEFAULTstatus_retries
self._propagate_headers = self.config.propagate_headers

def requests(self, session: requests.Session):
"""
Expand Down Expand Up @@ -94,7 +86,7 @@ def insert_trace_headers(headers: dict) -> dict:
return headers

@staticmethod
def propagate_headers(headers: dict) -> dict:
def set_propagate_headers(headers: dict) -> dict:
for k, v in request.headers:
if not headers.get(k):
headers.update({k: v})
Expand All @@ -112,7 +104,7 @@ def _get_headers(self, headers, propagate_headers=False):
headers = {}

if self._propagate_headers or propagate_headers:
headers = self.propagate_headers(headers)
headers = self.set_propagate_headers(headers)
return headers

@staticmethod
Expand All @@ -137,8 +129,8 @@ def parse_response(self, response):

try:
data = response.json()
if self.config.data:
data = data.get(self.config.data, {})
if self.data:
data = data.get(self.data, {})
return data
except ValueError:
logger.warning("Response.content is not a valid json {}".format(response.content))
Expand Down
23 changes: 22 additions & 1 deletion pyms/flask/services/swagger.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,33 @@
import os

import connexion

from pyms.flask.services.driver import DriverService
from pyms.utils import check_package_exists

SWAGGER_PATH = "swagger"
SWAGGER_FILE = "swagger.yaml"
SWAGGER_URL = "ui/"


class Service(DriverService):
service = "swagger"
default_values = {
"path": SWAGGER_PATH,
"file": SWAGGER_FILE
"file": SWAGGER_FILE,
"url": SWAGGER_URL
}

def init_app(self, config, path):
check_package_exists("connexion")
app = connexion.App(__name__, specification_dir=os.path.join(path, self.path))
app.add_api(
self.file,
arguments={'title': config.APP_NAME},
base_path=config.APPLICATION_ROOT,
options={"swagger_url": self.url}
)
# Invert the objects, instead connexion with a Flask object, a Flask object with
application = app.app
application.connexion_app = app
return application
8 changes: 8 additions & 0 deletions tests/common.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
from pyms.flask.app import Microservice

class MyMicroserviceNoSingleton(Microservice):
_singleton = False


class MyMicroservice(Microservice):
pass
14 changes: 14 additions & 0 deletions tests/config-tests-flask-swagger.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
pyms:
swagger:
path: ""
file: "swagger.yaml"
my-ms:
DEBUG: true
TESTING: true
APP_NAME: "Python Microservice With Flask"
APPLICATION_ROOT: /
test_var: general
subservice1:
test: input
subservice2:
test: output
10 changes: 10 additions & 0 deletions tests/config-tests-swagger.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
pyms:
swagger:
path: ""
file: "swagger.yaml"
url: "ws-doc/"
my-ms:
DEBUG: true
TESTING: true
APP_NAME: "Python Microservice Swagger"
APPLICATION_ROOT: /
56 changes: 37 additions & 19 deletions tests/test_flask.py
Original file line number Diff line number Diff line change
@@ -1,27 +1,19 @@
import os
import unittest
from unittest import mock

import pytest
from flask import current_app

from pyms.constants import CONFIGMAP_FILE_ENVIRONMENT, SERVICE_ENVIRONMENT
from pyms.flask.app import Microservice, config
from tests.common import MyMicroserviceNoSingleton, MyMicroservice


def home():
current_app.logger.info("start request")
return "OK"


class MyMicroserviceNoSingleton(Microservice):
_singleton = False


class MyMicroservice(Microservice):
pass


class HomeWithFlaskTests(unittest.TestCase):
"""
Tests for healthcheack endpoints
Expand All @@ -30,7 +22,7 @@ class HomeWithFlaskTests(unittest.TestCase):
def setUp(self):
os.environ[CONFIGMAP_FILE_ENVIRONMENT] = os.path.join(os.path.dirname(os.path.abspath(__file__)),
"config-tests-flask.yml")
ms = MyMicroserviceNoSingleton(service="my-ms", path=__file__)
ms = MyMicroserviceNoSingleton(service="my-ms", path=__file__, override_instance=True)
self.app = ms.create_app()
self.client = self.app.test_client()
self.assertEqual("Python Microservice With Flask", self.app.config["APP_NAME"])
Expand All @@ -44,6 +36,32 @@ def test_healthcheck(self):
self.assertEqual(b"OK", response.data)
self.assertEqual(200, response.status_code)

def test_swagger(self):
response = self.client.get('/ui/')
self.assertEqual(404, response.status_code)


class FlaskWithSwaggerTests(unittest.TestCase):
"""
Tests for healthcheack endpoints
"""

def setUp(self):
os.environ[CONFIGMAP_FILE_ENVIRONMENT] = os.path.join(os.path.dirname(os.path.abspath(__file__)),
"config-tests-flask-swagger.yml")
ms = MyMicroserviceNoSingleton(service="my-ms", path=__file__, override_instance=True)
self.app = ms.create_app()
self.client = self.app.test_client()
self.assertEqual("Python Microservice With Flask", self.app.config["APP_NAME"])

def test_healthcheck(self):
response = self.client.get('/healthcheck')
self.assertEqual(b"OK", response.data)
self.assertEqual(200, response.status_code)

def test_swagger(self):
response = self.client.get('/ui/')
self.assertEqual(200, response.status_code)


class MicroserviceTest(unittest.TestCase):
Expand Down Expand Up @@ -84,19 +102,19 @@ def test_config_singleton(self):

@pytest.mark.parametrize("payload, configfile, status_code", [
(
"Python Microservice",
"config-tests.yml",
200
"Python Microservice",
"config-tests.yml",
200
),
(
"Python Microservice With Flask",
"config-tests-flask.yml",
404
"Python Microservice With Flask",
"config-tests-flask.yml",
404
),
(
"Python Microservice With Flask and Lightstep",
"config-tests-flask-trace-lightstep.yml",
200
"Python Microservice With Flask and Lightstep",
"config-tests-flask-trace-lightstep.yml",
200
)
])
def test_configfiles(payload, configfile, status_code):
Expand Down
Loading