wip
parent
1e3ec13ee5
commit
31df5d7327
@ -0,0 +1,53 @@
|
||||
# Entrypoint configuration example
|
||||
|
||||
# This entry should reflect CMD in Dockerfile
|
||||
command: git
|
||||
|
||||
# This is a list with some subcommands to handle
|
||||
# when CMD is not `git` here.
|
||||
# By default, all args started with hyphen are handled.
|
||||
subcommands:
|
||||
- "-*"
|
||||
- clone
|
||||
- init
|
||||
- ls-files
|
||||
# etc...
|
||||
|
||||
# User and group to run the cmd.
|
||||
# Can be name or uid/gid.
|
||||
# Affect only command handled.
|
||||
# Dockerfile USER value by default.
|
||||
user: 1000
|
||||
group: 1000
|
||||
|
||||
# These files should exist (ADD or COPY)
|
||||
# and should be jinja templated.
|
||||
config_files:
|
||||
- /etc/gitconfig
|
||||
- .ssh/config
|
||||
- .ssh/id_rsa
|
||||
|
||||
# These environment variables will be wiped before
|
||||
# exec command to keep them secret
|
||||
secret_env:
|
||||
- SSHKEY
|
||||
|
||||
# Links are handled here
|
||||
# Port, name, protocol or env variable can be used to identify the links
|
||||
# Raise an error if the link could not be identified
|
||||
links:
|
||||
'ssh':
|
||||
port: 22
|
||||
name: 'ssh*'
|
||||
protocol: tcp
|
||||
|
||||
# Commands to run before applying configuration
|
||||
pre_conf_commands:
|
||||
- echo something useless
|
||||
|
||||
# commands to run after applying configuration
|
||||
post_conf_commads:
|
||||
- echo something even useless
|
||||
|
||||
# Enable debug to debug
|
||||
debug: true
|
@ -1,4 +1,4 @@
|
||||
#! /usr/bin/env python
|
||||
#!/usr/bin/env python
|
||||
|
||||
"""
|
||||
DockerLinks a kiss class which help to get links info in a docker
|
@ -0,0 +1,204 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
"""
|
||||
Smart docker-entrypoint
|
||||
"""
|
||||
|
||||
import fnmatch
|
||||
import os
|
||||
from grp import getgrnam
|
||||
from io import open
|
||||
from pwd import getpwnam
|
||||
|
||||
from six import string_types
|
||||
from twiggy import levels, log, quickSetup
|
||||
|
||||
from docker_links import DockerLinks
|
||||
from pyyaml import Loader, load
|
||||
|
||||
|
||||
class Link(object):
|
||||
|
||||
"""Link object"""
|
||||
|
||||
def __init__(self, ip, env, port, protocol, names):
|
||||
self.ip = ip
|
||||
self.env = env
|
||||
self.port = port
|
||||
self.protocol = protocol
|
||||
self.uri = '{protocol}://{ip}:{port}'.format(
|
||||
protocol=protocol,
|
||||
ip=ip,
|
||||
port=port,
|
||||
)
|
||||
self.names = tuple(names)
|
||||
|
||||
|
||||
class Links(object):
|
||||
|
||||
"""Links embeder"""
|
||||
|
||||
_links = []
|
||||
_conf = None
|
||||
|
||||
def __init__(self, links={}, conf=None):
|
||||
if len(links) is 0:
|
||||
pass
|
||||
|
||||
for ip, link in links.links.items():
|
||||
for port, protocol in link["ports"].items():
|
||||
self._links.append(Link(ip=ip,
|
||||
env=link['environment'],
|
||||
port=port,
|
||||
protocol=protocol['protocol'],
|
||||
names=link['names']))
|
||||
|
||||
self._conf = conf
|
||||
|
||||
def _get_link(self, name):
|
||||
conf = self._conf[name]
|
||||
links = self._links
|
||||
for link in links:
|
||||
if 'port' in conf and link.port is not conf['port']:
|
||||
links.pop(link)
|
||||
continue
|
||||
if 'name' in conf \
|
||||
and len(fnmatch.filter(link.names, conf['name'])) is 0:
|
||||
links.pop(link)
|
||||
continue
|
||||
if 'protocol' in conf and link.protocol is not conf['protocol']:
|
||||
links.pop(link)
|
||||
|
||||
return tuple(links)
|
||||
|
||||
@classmethod
|
||||
def _add_name(cls, name):
|
||||
setattr(cls, name, property(lambda self: self._get_link(name)))
|
||||
|
||||
@property
|
||||
def all(self):
|
||||
"""all returns tuple of all Link objects"""
|
||||
return tuple(self._links)
|
||||
|
||||
|
||||
class Config(object):
|
||||
|
||||
"""Get entrypoint config"""
|
||||
|
||||
# Config file should always be in WORKDIR and named
|
||||
# entrypoint-config.yml
|
||||
_config_file = 'entrypoint-config.yml'
|
||||
|
||||
_config = {}
|
||||
|
||||
def _return_item_lst(self, item):
|
||||
"""Return item as a list"""
|
||||
if item in self._config:
|
||||
if isinstance(self._config[item], string_types):
|
||||
return [self._config[item]]
|
||||
return self._config[item]
|
||||
return []
|
||||
|
||||
def __init__(self):
|
||||
if not os.path.isfile(self._config_file):
|
||||
return
|
||||
try:
|
||||
with open(self._config_file) as f:
|
||||
self._config = load(stream=f, Loader=Loader)
|
||||
except Exception as err:
|
||||
# TODO: logger
|
||||
print(err)
|
||||
|
||||
@property
|
||||
def as_config(self):
|
||||
"Has config file provided."
|
||||
return len(self._config) is not 0
|
||||
|
||||
@property
|
||||
def command(self):
|
||||
"Main command to run."
|
||||
if 'command' in self._config:
|
||||
return self._config['command']
|
||||
elif 'cmd' in self._config:
|
||||
return self._config['cmd']
|
||||
|
||||
@property
|
||||
def subcommands(self):
|
||||
"""Subcommands to handle as arguments."""
|
||||
return self._return_item_lst('subcommands')
|
||||
|
||||
@property
|
||||
def user(self):
|
||||
"Unix user or uid to run command."
|
||||
if 'user' in self._config:
|
||||
if isinstance(self._config['user'], int):
|
||||
return self._config['user']
|
||||
return getpwnam(name=self._config['user']).pw_uid
|
||||
return os.getuid()
|
||||
|
||||
@property
|
||||
def group(self):
|
||||
"Unix group or gid to run command."
|
||||
if 'group' in self._config:
|
||||
if isinstance(self._config['user'], int):
|
||||
return self._config['user']
|
||||
return getgrnam(name=self._config['user']).pw_gid
|
||||
return os.getgid()
|
||||
|
||||
@property
|
||||
def config_files(self):
|
||||
"List of template config files."
|
||||
return self._return_item_lst('config_files')
|
||||
|
||||
@property
|
||||
def secret_env(self):
|
||||
"""Environment variables to delete before running command."""
|
||||
return self._return_item_lst('secret_env')
|
||||
|
||||
@property
|
||||
def links(self):
|
||||
"""Links configs."""
|
||||
links = DockerLinks()
|
||||
if 'links' not in self._config:
|
||||
return Links(links=links)
|
||||
links = Links(links=links, config=self._config['links'])
|
||||
for name in self._config['links']:
|
||||
links._add_name(name)
|
||||
return links
|
||||
|
||||
@property
|
||||
def pre_conf_command(self):
|
||||
"""Return Exec object of preconf command"""
|
||||
if 'pre_conf_command' in self._config:
|
||||
return self._set_exec(self._config['pre_conf_command'])
|
||||
|
||||
@property
|
||||
def post_conf_command(self):
|
||||
"""Return Exec object of preconf command"""
|
||||
if 'post_conf_command' in self._config:
|
||||
return self._set_exec(self._config['post_conf_command'])
|
||||
|
||||
@property
|
||||
def debug(self):
|
||||
"""Enable debug logs."""
|
||||
if 'debug' in self._config:
|
||||
return bool(self._config['debug'])
|
||||
return False
|
||||
|
||||
|
||||
class Entrypoint(object):
|
||||
|
||||
"""Entrypoint class."""
|
||||
|
||||
def _set_logguer(self):
|
||||
quickSetup(min_level=levels.INFO)
|
||||
self.log = log.name('entrypoint')
|
||||
|
||||
def __init__(self):
|
||||
self._set_logguer()
|
||||
try:
|
||||
self.config = Config()
|
||||
except Exception as err:
|
||||
self.log.error(err)
|
||||
if self.config.debug:
|
||||
quickSetup(min_level=levels.DEBUG)
|
Loading…
Reference in New Issue