mirror of
https://github.com/outbackdingo/patroni.git
synced 2026-08-25 14:53:37 +00:00
Attempt to make single binary build with pyinstaller
This commit is contained in:
committed by
Dmytro Aleksandrov
parent
5b9411b9da
commit
e86cf9a722
@@ -6,6 +6,7 @@ data/*
|
|||||||
.coverage
|
.coverage
|
||||||
.eggs/
|
.eggs/
|
||||||
build/
|
build/
|
||||||
|
dist/
|
||||||
coverage.xml
|
coverage.xml
|
||||||
junit.xml
|
junit.xml
|
||||||
pgpass
|
pgpass
|
||||||
|
|||||||
Executable
+5
@@ -0,0 +1,5 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
set -e
|
||||||
|
|
||||||
|
pip install --ignore-installed -r requirements-bin.txt
|
||||||
|
pyinstaller --clean --onefile patroni.spec
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
# -*- mode: python -*-
|
||||||
|
|
||||||
|
block_cipher = None
|
||||||
|
|
||||||
|
|
||||||
|
a = Analysis(['patroni/__main__.py', 'patroni/dcs/consul.py', 'patroni/dcs/etcd.py', 'patroni/dcs/exhibitor.py', 'patroni/dcs/zookeeper.py'],
|
||||||
|
pathex=[],
|
||||||
|
binaries=None,
|
||||||
|
datas=None,
|
||||||
|
hiddenimports=['patroni.dcs.consul', 'patroni.dcs.etcd', 'patroni.dcs.exhibitor', 'patroni.dcs.zookeeper'],
|
||||||
|
hookspath=[],
|
||||||
|
runtime_hooks=[],
|
||||||
|
excludes=[],
|
||||||
|
win_no_prefer_redirects=False,
|
||||||
|
win_private_assemblies=False,
|
||||||
|
cipher=block_cipher)
|
||||||
|
|
||||||
|
pyz = PYZ(a.pure, a.zipped_data, cipher=block_cipher)
|
||||||
|
|
||||||
|
exe = EXE(pyz,
|
||||||
|
a.scripts,
|
||||||
|
a.binaries,
|
||||||
|
a.zipfiles,
|
||||||
|
a.datas,
|
||||||
|
name='patroni',
|
||||||
|
debug=False,
|
||||||
|
strip=False,
|
||||||
|
upx=True,
|
||||||
|
console=True)
|
||||||
+1
-1
@@ -64,7 +64,7 @@ class Config(object):
|
|||||||
print('Usage: {0} config.yml'.format(sys.argv[0]))
|
print('Usage: {0} config.yml'.format(sys.argv[0]))
|
||||||
print('\tPatroni may also read the configuration from the {0} environment variable'.
|
print('\tPatroni may also read the configuration from the {0} environment variable'.
|
||||||
format(self.PATRONI_CONFIG_VARIABLE))
|
format(self.PATRONI_CONFIG_VARIABLE))
|
||||||
exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
self.__effective_configuration = self._build_effective_configuration({}, self._local_configuration)
|
self.__effective_configuration = self._build_effective_configuration({}, self._local_configuration)
|
||||||
self._data_dir = self.__effective_configuration['postgresql']['data_dir']
|
self._data_dir = self.__effective_configuration['postgresql']['data_dir']
|
||||||
|
|||||||
+27
-14
@@ -6,6 +6,7 @@ import json
|
|||||||
import os
|
import os
|
||||||
import pkgutil
|
import pkgutil
|
||||||
import six
|
import six
|
||||||
|
import sys
|
||||||
|
|
||||||
from collections import namedtuple
|
from collections import namedtuple
|
||||||
from patroni.exceptions import PatroniException
|
from patroni.exceptions import PatroniException
|
||||||
@@ -31,22 +32,34 @@ def parse_connection_string(value):
|
|||||||
return conn_url, api_url
|
return conn_url, api_url
|
||||||
|
|
||||||
|
|
||||||
|
def dcs_modules():
|
||||||
|
"""Get names of DCS modules, depending on execution environment. If being packaged with PyInstaller,
|
||||||
|
modules aren't discoverable dynamically by scanning source directory. Thus, when running in bundle,
|
||||||
|
a predefined list of dcs modules is returned. See:
|
||||||
|
https://pyinstaller.readthedocs.io/en/stable/runtime-information.html#run-time-information"""
|
||||||
|
|
||||||
|
if getattr(sys, 'frozen', False):
|
||||||
|
return ['consul', 'etcd', 'zookeeper', 'exhibitor']
|
||||||
|
else:
|
||||||
|
module_names = (name for _, name, is_pkg in pkgutil.iter_modules([os.path.dirname(__file__)]) if not is_pkg)
|
||||||
|
return module_names
|
||||||
|
|
||||||
|
|
||||||
def get_dcs(config):
|
def get_dcs(config):
|
||||||
available_implementations = set()
|
available_implementations = set()
|
||||||
for _, module_name, is_pkg in pkgutil.iter_modules([os.path.dirname(__file__)]):
|
for module_name in dcs_modules():
|
||||||
if not is_pkg:
|
module = importlib.import_module(__package__ + '.' + module_name)
|
||||||
module = importlib.import_module(__package__ + '.' + module_name)
|
for name in filter(lambda name: not name.startswith('__'), dir(module)): # iterate through module content
|
||||||
for name in filter(lambda name: not name.startswith('__'), dir(module)): # iterate through module content
|
value = getattr(module, name)
|
||||||
value = getattr(module, name)
|
name = name.lower()
|
||||||
name = name.lower()
|
# try to find implementation of AbstractDCS interface, class name must match with module_name
|
||||||
# try to find implementation of AbstractDCS interface, class name must match with module_name
|
if inspect.isclass(value) and issubclass(value, AbstractDCS) and name == module_name:
|
||||||
if inspect.isclass(value) and issubclass(value, AbstractDCS) and name == module_name:
|
available_implementations.add(name)
|
||||||
available_implementations.add(name)
|
if name in config: # which has configuration section in the config file
|
||||||
if name in config: # which has configuration section in the config file
|
# propagate some parameters
|
||||||
# propagate some parameters
|
config[name].update({p: config[p] for p in ('namespace', 'name', 'scope',
|
||||||
config[name].update({p: config[p] for p in ('namespace', 'name', 'scope',
|
'loop_wait', 'ttl', 'retry_timeout') if p in config})
|
||||||
'loop_wait', 'ttl', 'retry_timeout') if p in config})
|
return value(config[name])
|
||||||
return value(config[name])
|
|
||||||
raise PatroniException("""Can not find suitable configuration of distributed configuration store
|
raise PatroniException("""Can not find suitable configuration of distributed configuration store
|
||||||
Available implementations: """ + ', '.join(available_implementations))
|
Available implementations: """ + ', '.join(available_implementations))
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,2 @@
|
|||||||
|
setuptools==19.2
|
||||||
|
pyinstaller
|
||||||
Reference in New Issue
Block a user