pull/1/head
Christophe Mehay 9 years ago
parent 1e3ec13ee5
commit 31df5d7327

@ -1,6 +1,6 @@
# Python docker_links
# py_docker_links
Python docker_links is a kiss python module which helps to list
py_docker_links is a kiss python module which helps to list
linked containers inner containers.
You can use it with `ENTRYPOINT` script to generate configuration.

@ -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…
Cancel
Save