Merge branch 'ckuehl_python_package'
This commit is contained in:
commit
6f6814e91b
17 changed files with 328 additions and 124 deletions
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -1,3 +1,5 @@
|
|||
dumb-init
|
||||
dist/
|
||||
*.deb
|
||||
*.egg-info
|
||||
.tox
|
||||
|
|
26
.pre-commit-config.yaml
Normal file
26
.pre-commit-config.yaml
Normal 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
1
MANIFEST.in
Normal file
|
@ -0,0 +1 @@
|
|||
include dumb-init.c
|
59
Makefile
59
Makefile
|
@ -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)
|
||||
|
|
|
@ -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
2
debian/control
vendored
|
@ -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
3
debian/rules
vendored
|
@ -4,3 +4,6 @@
|
|||
|
||||
override_dh_builddeb:
|
||||
dh_builddeb -- -Zgzip
|
||||
|
||||
override_dh_auto_test:
|
||||
./test ./dumb-init
|
||||
|
|
107
setup.py
Normal file
107
setup.py
Normal 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
19
test
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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."
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
11
tox.ini
Normal 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}
|
Loading…
Reference in a new issue