Skip to content

Commit

Permalink
Refactor config. Issue #75 (#78)
Browse files Browse the repository at this point in the history
* Refactor config

* Fix flake8

* Disabled services with key "enabled" without remove code block

* Fix pylint error
  • Loading branch information
avara1986 committed Dec 15, 2019
1 parent e8db8d8 commit c3b63f8
Show file tree
Hide file tree
Showing 32 changed files with 293 additions and 239 deletions.
29 changes: 15 additions & 14 deletions examples/microservice_configuration/config.yml
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
pyms:
requests:
data: ""
swagger:
path: ""
file: "swagger.yaml"
ms:
DEBUG: true
TESTING: false
APP_NAME: "Python Microservice"
APPLICATION_ROOT: ""
request_variable_test: "this is a test"
MyVar: "this is MyVar"
test1: "ttest1"
test2: "ttest2"
services:
requests:
data: ""
swagger:
path: ""
file: "swagger.yaml"
config:
DEBUG: true
TESTING: false
APP_NAME: "Python Microservice"
APPLICATION_ROOT: ""
request_variable_test: "this is a test"
MyVar: "this is MyVar"
test1: "ttest1"
test2: "ttest2"
2 changes: 1 addition & 1 deletion examples/microservice_requests/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
from pyms.flask.app import Microservice

ms = Microservice(service="my-ms", path=__file__)
ms = Microservice(path=__file__)
21 changes: 11 additions & 10 deletions examples/microservice_requests/config.yml
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
pyms:
requests:
data: ""
swagger:
path: ""
file: "swagger.yaml"
my-ms:
DEBUG: true
TESTING: false
APP_NAME: "Python Microservice"
APPLICATION_ROOT: ""
services:
requests:
data: ""
swagger:
path: ""
file: "swagger.yaml"
config:
DEBUG: true
TESTING: false
APP_NAME: "Python Microservice"
APPLICATION_ROOT: ""
19 changes: 10 additions & 9 deletions examples/microservice_swagger/config.yml
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
pyms:
swagger:
path: ""
file: "swagger.yaml"
url: "ws-doc/"
my-ms:
DEBUG: true
TESTING: false
APP_NAME: "Python Microservice"
APPLICATION_ROOT: ""
services:
swagger:
path: ""
file: "swagger.yaml"
url: "ws-doc/"
config:
DEBUG: true
TESTING: false
APP_NAME: "Python Microservice"
APPLICATION_ROOT: ""
2 changes: 1 addition & 1 deletion examples/microservice_swagger/main.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from pyms.flask.app import Microservice

ms = Microservice(service="my-ms", path=__file__)
ms = Microservice(path=__file__)
app = ms.create_app()

if __name__ == '__main__':
Expand Down
2 changes: 1 addition & 1 deletion examples/microservice_tracer/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
from pyms.flask.app import Microservice

ms = Microservice(service="my-ms", path=__file__)
ms = Microservice(path=__file__)
30 changes: 16 additions & 14 deletions examples/microservice_tracer/config.yml
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
pyms:
requests:
data: ""
swagger:
path: ""
file: "swagger.yaml"
tracer:
client: "jaeger"
host: "localhost"
component_name: "Python Microservice"
my-ms:
DEBUG: true
TESTING: false
APP_NAME: "Python Microservice"
APPLICATION_ROOT: ""
services:
metrics: true
requests:
data: ""
swagger:
path: ""
file: "swagger.yaml"
tracer:
client: "jaeger"
host: "localhost"
component_name: "Python Microservice"
config:
DEBUG: true
TESTING: false
APP_NAME: "Python Microservice"
APPLICATION_ROOT: ""
15 changes: 8 additions & 7 deletions examples/mininum_microservice/config.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
my-minimal-microservice:
DEBUG: true
TESTING: false
SWAGGER: true
APP_NAME: business-glossary
APPLICATION_ROOT : ""
SECRET_KEY: "gjr39dkjn344_!67#"
pyms:
config:
DEBUG: true
TESTING: false
SWAGGER: true
APP_NAME: business-glossary
APPLICATION_ROOT : ""
SECRET_KEY: "gjr39dkjn344_!67#"
4 changes: 4 additions & 0 deletions examples/mininum_microservice_docker/config-docker.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
pyms:
config:
app_name: "Python Microservice"
environment: "I'm running in docker"
3 changes: 0 additions & 3 deletions examples/mininum_microservice_docker/config.-docker.yml

This file was deleted.

7 changes: 4 additions & 3 deletions examples/mininum_microservice_docker/config.yml
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
my-minimal-microservice:
APP_NAME: "Python Microservice"
environment: "I'm running in a local machine"
pyms:
config:
app_name: "Python Microservice"
environment: "I'm running in a local machine"
14 changes: 13 additions & 1 deletion pyms/config/confile.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,16 @@ def __init__(self, *args, **kwargs):
"""
Get configuration from a dictionary(variable `config`), from path (variable `path`) or from
environment with the constant `CONFIGMAP_FILE`
Set the configuration as upper case to inject the keys in flask config. Flask search for uppercase keys in
`app.config.from_object`
```python
if key.isupper():
self[key] = getattr(obj, key)
```
"""
self.empty_init = kwargs.get("empty_init", False)
config = kwargs.get("config")
uppercase = kwargs.get("uppercase", True)
if config is None:
config = self._get_conf_from_file(kwargs.get("path")) or self._get_conf_from_env()

Expand All @@ -38,7 +45,12 @@ def __init__(self, *args, **kwargs):
raise ConfigDoesNotFoundException("Configuration file not found")

config = dict(self.normalize_config(config))
_ = [setattr(self, k, v) for k, v in config.items()]
for k, v in config.items():
setattr(self, k, v)
# Flask search for uppercase keys
if uppercase:
setattr(self, k.upper(), v)

super(ConfFile, self).__init__(config)

def normalize_config(self, config):
Expand Down
5 changes: 3 additions & 2 deletions pyms/constants.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
CONFIGMAP_FILE_ENVIRONMENT = "CONFIGMAP_FILE"
SERVICE_ENVIRONMENT = "CONFIGMAP_SERVICE"

LOGGER_NAME = "pyms"

SERVICE_BASE = "pyms"
CONFIG_BASE = "pyms.config"

SERVICE_BASE = "pyms.services"
24 changes: 12 additions & 12 deletions pyms/flask/app/create_app.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
from flask_opentracing import FlaskTracing

from pyms.config import get_conf
from pyms.constants import LOGGER_NAME, SERVICE_ENVIRONMENT
from pyms.constants import LOGGER_NAME, CONFIG_BASE
from pyms.flask.healthcheck import healthcheck_blueprint
from pyms.flask.services.driver import ServicesManager
from pyms.logger import CustomJsonFormatter
Expand Down Expand Up @@ -70,15 +70,16 @@ def example():
```yaml
pyms:
requests: true
swagger:
path: ""
file: "swagger.yaml"
my-ms:
DEBUG: true
TESTING: false
APP_NAME: "Python Microservice"
APPLICATION_ROOT: ""
services:
requests: true
swagger:
path: ""
file: "swagger.yaml"
config:
DEBUG: true
TESTING: false
APP_NAME: "Python Microservice"
APPLICATION_ROOT: ""
```
Services are libraries, resources and extensions added to the Microservice in the configuration file.
Expand All @@ -96,9 +97,8 @@ def example():
_singleton = True

def __init__(self, *args, **kwargs):
self.service = kwargs.get("service", os.environ.get(SERVICE_ENVIRONMENT, "ms"))
self.path = os.path.dirname(kwargs.get("path", __file__))
self.config = get_conf(service=self.service, memoize=self._singleton)
self.config = get_conf(service=CONFIG_BASE, memoize=self._singleton)
self.init_services()

def init_services(self) -> None:
Expand Down
28 changes: 19 additions & 9 deletions pyms/flask/services/driver.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import logging
from typing import Text, Tuple

from pyms.config import get_conf, ConfFile
from pyms.constants import SERVICE_BASE, LOGGER_NAME
from pyms.utils import import_from
from pyms.utils.utils import get_service_name

logger = logging.getLogger(LOGGER_NAME)

Expand Down Expand Up @@ -32,16 +34,20 @@ class DriverService:
"""
service = ""
config = None
enabled = True

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

def __getattr__(self, attr, *args, **kwargs):
config_attribute = getattr(self.config, attr)
return config_attribute if config_attribute == "" or config_attribute != {} else self.default_values.get(attr,
None)

def is_enabled(self):
return self.enabled

def exists_config(self):
return self.config is not None and isinstance(self.config, ConfFile)

Expand All @@ -52,14 +58,18 @@ class ServicesManager:
"""
service = SERVICE_BASE

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 __init__(self):
self.config = get_conf(service=self.service, empty_init=True, memoize=False, uppercase=False)

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_services(self, memoize: bool) -> Tuple[Text, DriverService]:
for k in self.config.__dict__.keys():
if k.islower() and k not in ['empty_init', ]:
service = self.get_service(k, memoize=memoize)
if service.is_enabled():
yield (k, service)

def get_service(self, service, *args, **kwargs):
@staticmethod
def get_service(service: Text, *args, **kwargs) -> DriverService:
service_object = import_from("pyms.flask.services.{}".format(service), "Service")
logger.debug("Init service {}".format(service))
return service_object(service=self.service, *args, **kwargs)
return service_object(*args, **kwargs)
4 changes: 2 additions & 2 deletions pyms/flask/services/metrics.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,8 @@ def after_request(response):
class Service(DriverService):
service = "metrics"

def __init__(self, service, *args, **kwargs):
super().__init__(service, *args, **kwargs)
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.metrics_blueprint = Blueprint("metrics", __name__)
self.serve_metrics()

Expand Down
3 changes: 2 additions & 1 deletion pyms/flask/services/tracer.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
from pyms.constants import LOGGER_NAME
from pyms.flask.services.driver import DriverService
from pyms.utils import check_package_exists, import_package, import_from
from pyms.utils.utils import get_service_name

logger = logging.getLogger(LOGGER_NAME)

Expand Down Expand Up @@ -67,7 +68,7 @@ def init_jaeger_tracer(self):
'reporting_host': self.host
}
}
metrics_config = get_conf(service="pyms.metrics", empty_init=True, memoize=False)
metrics_config = get_conf(service=get_service_name(service="metrics"), empty_init=True, memoize=False)
metrics = ""
if metrics_config:
metrics = PrometheusMetricsFactory()
Expand Down
9 changes: 7 additions & 2 deletions pyms/utils/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,26 @@
import importlib.util
from typing import Union, Text

from pyms.constants import SERVICE_BASE
from pyms.exceptions import PackageNotExists


def import_from(module: Text, name: Text):

module = __import__(module, fromlist=[name])
return getattr(module, name)


def get_service_name(service_base=SERVICE_BASE, service=""):
return ".".join([service_base, service])


def import_package(package: Text):
return importlib.import_module(package)


def check_package_exists(package_name: Text) -> Union[Exception, bool]:
spec = importlib.util.find_spec(package_name)
if spec is None:
raise PackageNotExists("{package} is not installed. try with pip install -U {package}".format(package=package_name))
raise PackageNotExists(
"{package} is not installed. try with pip install -U {package}".format(package=package_name))
return True

0 comments on commit c3b63f8

Please sign in to comment.