Merge branch 'ckuehl_python_package'

This commit is contained in:
Chris Kuehl 2015-08-11 15:29:22 -07:00
commit 6f6814e91b
17 changed files with 328 additions and 124 deletions

2
.gitignore vendored
View file

@ -1,3 +1,5 @@
dumb-init
dist/
*.deb
*.egg-info
.tox

26
.pre-commit-config.yaml Normal file
View file

@ -0,0 +1,26 @@
- repo: https://github.com/pre-commit/pre-commit-hooks.git
sha: 003e43251aea1da33f2072f2365ec8b9ceaae070
hooks:
- id: autopep8-wrapper
- id: check-added-large-files
- id: check-docstring-first
- id: check-json
- id: check-merge-conflict
- id: check-xml
- id: check-yaml
- id: debug-statements
- id: detect-private-key
- id: double-quote-string-fixer
- id: end-of-file-fixer
- id: flake8
- id: name-tests-test
- id: requirements-txt-fixer
- id: trailing-whitespace
- repo: https://github.com/asottile/reorder_python_imports.git
sha: 3d86483455ab5bd06cc1069fdd5ac57be5463f10
hooks:
- id: reorder-python-imports
- repo: https://github.com/Lucas-C/pre-commit-hooks.git
sha: 181a63c511691da58116fa19a7241956018660bc
hooks:
- id: remove-tabs

1
MANIFEST.in Normal file
View file

@ -0,0 +1 @@
include dumb-init.c

View file

@ -1,13 +1,31 @@
DOCKER_TEST := sh -c 'dpkg -i /mnt/dist/*.deb && cd /mnt && ./test'
DOCKER_RUN_TEST := docker run -v $(PWD):/mnt:ro
DOCKER_DEB_TEST := sh -euxc ' \
apt-get update \
&& apt-get install -y --no-install-recommends procps \
&& dpkg -i /mnt/dist/*.deb \
&& cd /mnt \
&& ./test \
'
DOCKER_PYTHON_TEST := sh -uexc ' \
apt-get update \
&& apt-get install -y --no-install-recommends python-pip build-essential procps \
&& pip install -vv /mnt \
&& cd /mnt \
&& ./test \
'
.PHONY: build
build:
$(CC) -static -Wall -Werror -o dumb-init dumb-init.c
.PHONY: clean
clean:
clean: clean-tox
rm -rf dumb-init dist/ *.deb
.PHONY: clean-tox
clean-tox:
rm -rf .tox
.PHONY: builddeb
builddeb:
debuild -us -uc -b
@ -22,24 +40,31 @@ builddeb-docker: docker-image
docker-image:
docker build -t dumb-init-build .
.PHONY: test
test:
tox
.PHONY: install-hooks
install-hooks:
tox -e pre-commit -- install -f --install-hooks
.PHONY: itest itest_lucid itest_precise itest_trusty itest_wheezy itest_jessie itest_stretch
itest: itest_lucid itest_precise itest_trusty itest_wheezy itest_jessie itest_stretch
itest_lucid: builddeb-docker
docker run -v $(PWD):/mnt:ro ubuntu:lucid \
sh -ec "apt-get -y install timeout; $(DOCKER_TEST)"
itest_lucid: _itest-ubuntu-lucid
itest_precise: _itest-ubuntu-precise
itest_trusty: _itest-ubuntu-trusty
itest_wheezy: _itest-debian-wheezy
itest_jessie: _itest-debian-jessie
itest_stretch: _itest-debian-stretch
itest_precise: builddeb-docker
docker run -v $(PWD):/mnt:ro ubuntu:precise $(DOCKER_TEST)
_itest-%: _itest_deb-% _itest_python-%
@true
itest_trusty: builddeb-docker
docker run -v $(PWD):/mnt:ro ubuntu:trusty $(DOCKER_TEST)
_itest_python-%:
$(eval DOCKER_IMG := $(shell echo $@ | cut -d- -f2 | sed 's/-/:/'))
$(DOCKER_RUN_TEST) $(DOCKER_IMG) $(DOCKER_PYTHON_TEST)
itest_wheezy: builddeb-docker
docker run -v $(PWD):/mnt:ro debian:wheezy $(DOCKER_TEST)
itest_jessie: builddeb-docker
docker run -v $(PWD):/mnt:ro debian:jessie $(DOCKER_TEST)
itest_stretch: builddeb-docker
docker run -v $(PWD):/mnt:ro debian:stretch $(DOCKER_TEST)
_itest_deb-%:
$(eval DOCKER_IMG := $(shell echo $@ | cut -d- -f2 | sed 's/-/:/'))
$(DOCKER_RUN_TEST) $(DOCKER_IMG) $(DOCKER_DEB_TEST)

View file

@ -60,6 +60,14 @@ If you don't have an internal apt server, you can use `dpkg -i` to install the
(mounting a directory or `wget`-ing it are some options).
### Option 3: Installing from PyPI
dumb-init can be installed [from PyPI](https://pypi.python.org/pypi/dumb-init)
using pip. Since dumb-init is written in C, you'll want to first install gcc
(on Debian/Ubuntu, `apt-get install gcc` is sufficient), then just `pip install
dumb-init`.
## Usage
Once installed inside your Docker container, simply prefix your commands with

2
debian/control vendored
View file

@ -2,7 +2,7 @@ Source: dumb-init
Section: utils
Priority: extra
Maintainer: Chris Kuehl <ckuehl@yelp.com>
Build-Depends: debhelper (>= 7), gcc, fakeroot
Build-Depends: debhelper (>= 7), gcc, fakeroot, procps
Standards-Version: 3.9.6
Package: dumb-init

3
debian/rules vendored
View file

@ -4,3 +4,6 @@
override_dh_builddeb:
dh_builddeb -- -Zgzip
override_dh_auto_test:
./test ./dumb-init

107
setup.py Normal file
View file

@ -0,0 +1,107 @@
import os.path
from distutils.command.build import build as orig_build
from distutils.core import Command
from setuptools import Distribution
from setuptools import Extension
from setuptools import setup
from setuptools.command.install import install as orig_install
class ExeDistribution(Distribution):
c_executables = ()
class build(orig_build):
sub_commands = orig_build.sub_commands + [
('build_cexe', None),
]
class install(orig_install):
sub_commands = orig_install.sub_commands + [
('install_cexe', None),
]
class install_cexe(Command):
description = 'install C executables'
outfiles = ()
def initialize_options(self):
self.build_dir = self.install_dir = None
def finalize_options(self):
# this initializes attributes based on other commands' attributes
self.set_undefined_options('build', ('build_scripts', 'build_dir'))
self.set_undefined_options(
'install', ('install_scripts', 'install_dir'))
def run(self):
self.outfiles = self.copy_tree(self.build_dir, self.install_dir)
def get_outputs(self):
return self.outfiles
class build_cexe(Command):
description = 'build C executables'
def initialize_options(self):
self.build_scripts = None
self.build_temp = None
def finalize_options(self):
self.set_undefined_options(
'build',
('build_scripts', 'build_scripts'),
('build_temp', 'build_temp'),
)
def run(self):
# stolen and simplified from distutils.command.build_ext
from distutils.ccompiler import new_compiler
compiler = new_compiler(verbose=True)
for exe in self.distribution.c_executables:
objects = compiler.compile(
exe.sources,
output_dir=self.build_temp,
)
compiler.link_executable(
objects,
exe.name,
output_dir=self.build_scripts,
extra_postargs=exe.extra_link_args,
)
def get_outputs(self):
return [
os.path.join(self.build_scripts, exe.name)
for exe in self.distribution.c_executables
]
setup(
name='dumb-init',
description='Simple wrapper script which proxies signals to a child',
version='0.0.2',
author='Yelp',
platforms='linux',
c_executables=[
Extension(
'dumb-init',
['dumb-init.c'],
extra_link_args=['-static'],
),
],
cmdclass={
'build': build,
'build_cexe': build_cexe,
'install': install,
'install_cexe': install_cexe,
},
distclass=ExeDistribution,
)

19
test
View file

@ -1,8 +1,19 @@
#!/bin/sh -eux
#!/bin/bash -eux
if [ "$#" -eq 1 ]; then
dumb_init_bin=$(readlink -f "$1")
else
dumb_init_bin=$(which dumb-init) || {
echo "Couldn't find dumb-init on your path, exiting."
exit 1
}
fi
echo "Running with dumb-init at '$dumb_init_bin'"
run_tests() {
./test-proxies-signals
./test-exit-status
./test-help-message
./test-proxies-signals "$dumb_init_bin"
./test-exit-status "$dumb_init_bin"
./test-help-message "$dumb_init_bin"
}
cd tests

View file

@ -1,4 +1,4 @@
#!/bin/sh -eu
#!/bin/bash -eux
# Print received signals into a file, one per line
file="$1"
@ -10,5 +10,6 @@ done
echo 'ready' > "$file"
# loop forever
echo 'loop forever...'
set +x
while :; do true; done

View file

@ -1,7 +1,9 @@
#!/bin/sh -u
#!/bin/bash -eux
dumb_init="$1"
# dumb-init should exit with the same exit status as the process it launches.
for i in $(seq 0 255); do
status=$(dumb-init sh -c "exit $i"; echo $?)
status=$($dumb_init sh -c "exit $i"; echo $?)
if [ "$status" -ne "$i" ]; then
echo "Error: Expected exit status $i, got $status."

View file

@ -1,11 +1,13 @@
#!/bin/sh -u
#!/bin/bash -eux
# dumb-init should say something useful when called with no arguments, and exit
# nonzero.
status=$(dumb-init > /dev/null 2>&1; echo $?)
dumb_init="$1"
status=$($dumb_init > /dev/null 2>&1; echo $?)
if [ "$status" -ne 0 ]; then
msg=$(dumb-init 2>&1 || true)
msg=$($dumb_init 2>&1 || true)
msg_len=${#msg}
if [ "$msg_len" -le 50 ]; then

View file

@ -1,5 +1,6 @@
#!/bin/sh -eum
#!/bin/bash -euxm
# dumb-init should proxy all possible signals to the child process.
dumb_init="$1"
# Try sending all signals via dumb-init to our `print-signals` script, ensure
# they were all received.
@ -11,7 +12,7 @@ fifo=$(mktemp -u)
mkfifo -m 600 "$fifo"
read_cmd="timeout 1 head -n1 $fifo"
dumb-init ./lib/print-signals "$fifo" &
$dumb_init ./lib/print-signals "$fifo" &
pid="$!"
# Wait for `print-signals` to indicate it's ready.
@ -37,5 +38,9 @@ done
# Turn off job monitoring so we don't get a spurious "[1] + Killed" printed
set +m
kill -9 "$pid"
# $pid is the PID of the dumb-init process. Since print-signals ignores all
# signals, we need to `kill -9` it. If we just `kill -9` the dumb-init process,
# `print-signals` will still be running. So we instead kill children of the
# dumb-init process.
pkill -9 -P "$pid"
rm "$fifo"

11
tox.ini Normal file
View file

@ -0,0 +1,11 @@
[tox]
envlist = py27,py34
[testenv]
deps = pre-commit>=0.5.0
commands =
./test
pre-commit run --all-files
[testenv:pre-commit]
commands = pre-commit {posargs}