From 0370b26f3e88886052dca3c73cc7beaa59d24ead Mon Sep 17 00:00:00 2001 From: kaiyou Date: Mon, 6 May 2019 14:06:25 +0200 Subject: [PATCH] Initial commit --- core/base/libs/socrate/LICENSE.md | 21 ++++++++++ core/base/libs/socrate/MANIFEST.in | 2 + core/base/libs/socrate/README.md | 24 +++++++++++ core/base/libs/socrate/setup.py | 24 +++++++++++ core/base/libs/socrate/socrate/__init__.py | 0 core/base/libs/socrate/socrate/conf.py | 46 ++++++++++++++++++++++ core/base/libs/socrate/socrate/system.py | 20 ++++++++++ 7 files changed, 137 insertions(+) create mode 100644 core/base/libs/socrate/LICENSE.md create mode 100644 core/base/libs/socrate/MANIFEST.in create mode 100644 core/base/libs/socrate/README.md create mode 100644 core/base/libs/socrate/setup.py create mode 100644 core/base/libs/socrate/socrate/__init__.py create mode 100644 core/base/libs/socrate/socrate/conf.py create mode 100644 core/base/libs/socrate/socrate/system.py diff --git a/core/base/libs/socrate/LICENSE.md b/core/base/libs/socrate/LICENSE.md new file mode 100644 index 00000000..d360537d --- /dev/null +++ b/core/base/libs/socrate/LICENSE.md @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2019 Mailu + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/core/base/libs/socrate/MANIFEST.in b/core/base/libs/socrate/MANIFEST.in new file mode 100644 index 00000000..c28ab72d --- /dev/null +++ b/core/base/libs/socrate/MANIFEST.in @@ -0,0 +1,2 @@ +include README.md +include LICENSE.md diff --git a/core/base/libs/socrate/README.md b/core/base/libs/socrate/README.md new file mode 100644 index 00000000..9b65a83b --- /dev/null +++ b/core/base/libs/socrate/README.md @@ -0,0 +1,24 @@ +Socrate is a simple Python module providing a set of utility functions for +Python daemon applications. + +The scope includes: +- configuration utilities (configuration parsing, etc.) +- system utilities (access to DNS, stats, etc.) + +Setup +====== + +Socrate is available on Pypi, simpy run: + +``` +pip install socrate +``` + + +Contributing +============ + +Podop is free software, open to suggestions and contributions. All +components are free software and compatible with the MIT license. All +the code is placed under the MIT license. + diff --git a/core/base/libs/socrate/setup.py b/core/base/libs/socrate/setup.py new file mode 100644 index 00000000..827fc6e0 --- /dev/null +++ b/core/base/libs/socrate/setup.py @@ -0,0 +1,24 @@ +#!/usr/bin/env python + +from distutils.core import setup + +with open("README.md", "r") as fh: + long_description = fh.read() + +setup( + name="socrate", + version="0.1", + description="Socrate daemon utilities", + long_description=long_description, + long_description_content_type="text/markdown", + author="Pierre Jaury", + author_email="pierre@jaury.eu", + url="https://github.com/mailu/socrate.git", + packages=["socrate"], + include_package_data=True, + install_requires=[ + "jinja2", + "importlib", + "tenacity" + ] +) diff --git a/core/base/libs/socrate/socrate/__init__.py b/core/base/libs/socrate/socrate/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/core/base/libs/socrate/socrate/conf.py b/core/base/libs/socrate/socrate/conf.py new file mode 100644 index 00000000..5ccde54d --- /dev/null +++ b/core/base/libs/socrate/socrate/conf.py @@ -0,0 +1,46 @@ +import jinja2 +import importlib + + +def jinja(source, environ, destination=None): + """ Render a Jinja configuration file + """ + with open(source, "r") as template: + result = jinja2.Template(template.read()).render(environ) + if destination is not None: + with open(destination, "w") as handle: + handle.write(result) + return result + + +def merge(*objects): + """ Merge simple python objects, which only consist of + strings, integers, bools, lists and dicts + """ + mode = type(objects[0]) + if not all(type(obj) is mode for obj in objects): + raise ValueError("Cannot merge mixed typed objects") + if len(objects) == 1: + return objects[0] + elif mode is dict: + return { + key: merge(*[obj[key] for obj in objects if key in obj]) + for obj in objects for key in obj.keys() + } + elif mode is list: + return sum(objects) + else: + raise ValueError("Cannot merge objects of type {}: {}".format( + mode, objects)) + + +def resolve_function(function, cache={}): + """ Resolve a fully qualified function name in Python, and caches + the result + """ + if function not in cache: + module, name = function.rsplit(".", 1) + cache[function] = getattr(importlib.import_module(module), name) + return cache[function] + + diff --git a/core/base/libs/socrate/socrate/system.py b/core/base/libs/socrate/socrate/system.py new file mode 100644 index 00000000..64a87d15 --- /dev/null +++ b/core/base/libs/socrate/socrate/system.py @@ -0,0 +1,20 @@ +import socket +import tenacity + + +@retry(stop=tenacity.stop_after_attempt(100), + wait=tenacity.wait_random(min=2, max=5)) +def resolve_hostname(hostname): + """ This function uses system DNS to resolve a hostname. + It is capable of retrying in case the host is not immediately available + """ + return socket.gethostbyname(hostname) + + +def resolve_address(address): + """ This function is identical to ``resolve_host`` but also supports + resolving an address, i.e. including a port. + """ + hostname, *rest = address.resplit(":", 1) + ip_address = resolve_hostname(hostname) + return ip_address + "".join(":" + port for port in rest)