Put tmpdir chown into a try/finally
When stuff goes wrong in the images we miss chowning the tempdir back to the original uid so we get a double exception. But it in a finally. If only we had deterministic destructors ... Change-Id: Ide62c5bd6eee824f40005a7628b8dba65544f428
This commit is contained in:
parent
19463f937d
commit
9b9c7a099d
|
@ -174,99 +174,105 @@ def build(args):
|
||||||
with tempfile.TemporaryDirectory(
|
with tempfile.TemporaryDirectory(
|
||||||
dir=os.path.abspath(os.curdir)
|
dir=os.path.abspath(os.curdir)
|
||||||
) as tmpdir:
|
) as tmpdir:
|
||||||
# Pass in the directory into ~/.cache/pip so that the built wheel
|
try:
|
||||||
# cache will persist into the next container. The real wheel cache
|
# Pass in the directory into ~/.cache/pip so that the built wheel
|
||||||
# will go there- but we'll also put our built wheel into place there.
|
# cache will persist into the next container. The real wheel cache
|
||||||
tmp_volume = "{tmpdir}:/root/.cache/pip".format(tmpdir=tmpdir)
|
# will go there but we'll also put our built wheel there.
|
||||||
|
tmp_volume = "{tmpdir}:/root/.cache/pip".format(tmpdir=tmpdir)
|
||||||
|
|
||||||
# Make temporary container that installs all deps to build wheel
|
# Make temporary container that installs all deps to build wheel
|
||||||
# This container also needs git installed for pbr
|
# This container also needs git installed for pbr
|
||||||
log.info("Build wheels in python-base container")
|
log.info("Build wheels in python-base container")
|
||||||
with docker_container("python-base", volumes=[tmp_volume]) as cont:
|
with docker_container("python-base", volumes=[tmp_volume]) as cont:
|
||||||
# Make sure wheel cache dir is owned by container user
|
# Make sure wheel cache dir is owned by container user
|
||||||
cont.run("chown -R $(whoami) /root/.cache/pip")
|
cont.run("chown -R $(whoami) /root/.cache/pip")
|
||||||
|
|
||||||
# Add the compile dependencies
|
# Add the compile dependencies
|
||||||
cont.run("apk add {compile_packages} git".format(
|
cont.run("apk add {compile_packages} git".format(
|
||||||
compile_packages=compile_packages))
|
compile_packages=compile_packages))
|
||||||
|
|
||||||
# Build a wheel so that we have an install target.
|
# Build a wheel so that we have an install target.
|
||||||
# pip install . in the container context with the mounted
|
# pip install . in the container context with the mounted
|
||||||
# source dir gets ... exciting.
|
# source dir gets ... exciting.
|
||||||
cont.run("python setup.py bdist_wheel -d /root/.cache/pip")
|
cont.run("python setup.py bdist_wheel -d /root/.cache/pip")
|
||||||
|
|
||||||
# Install with all container-related extras so that we populate
|
# Install with all container-related extras so that we populate
|
||||||
# the wheel cache as needed.
|
# the wheel cache as needed.
|
||||||
cont.run(
|
|
||||||
"pip install"
|
|
||||||
" $(echo /root/.cache/pip/*.whl)[{base},{scripts}]".format(
|
|
||||||
base=info.base_container.replace('-', '_'),
|
|
||||||
scripts=','.join(info.scripts).replace('-', '_')))
|
|
||||||
|
|
||||||
# Build the final base container. Use dumb-init as the entrypoint so
|
|
||||||
# that signals and subprocesses work properly.
|
|
||||||
log.info("Build base container")
|
|
||||||
with docker_container(
|
|
||||||
"python-base",
|
|
||||||
tag=info.base_container,
|
|
||||||
prefix=args.prefix,
|
|
||||||
volumes=[tmp_volume],
|
|
||||||
comment='ENTRYPOINT ["/usr/bin/dumb-init", "--"]',
|
|
||||||
) as cont:
|
|
||||||
try:
|
|
||||||
cont.run(
|
|
||||||
"apk add {packages} dumb-init".format(packages=packages)
|
|
||||||
)
|
|
||||||
cont.run(
|
cont.run(
|
||||||
"pip install"
|
"pip install"
|
||||||
" $(echo /root/.cache/pip/*.whl)[{base}]".format(
|
" $(echo /root/.cache/pip/*.whl)[{base},{scripts}]".format(
|
||||||
base=info.base_container.replace('-', '_')))
|
base=info.base_container.replace('-', '_'),
|
||||||
if args.mirror:
|
scripts=','.join(info.scripts).replace('-', '_')))
|
||||||
cont.run(
|
|
||||||
"sed -i 's,{old},{new}' /etc/apk/repositories".format(
|
|
||||||
old=args.mirror,
|
|
||||||
new=ALPINE_MIRROR_BASE))
|
|
||||||
# chown wheel cache back so the temp dir can delete it
|
|
||||||
cont.run("chown -R {uid} /root/.cache/pip".format(
|
|
||||||
uid=os.getuid()))
|
|
||||||
except Exception as e:
|
|
||||||
print(e.stdout)
|
|
||||||
raise
|
|
||||||
|
|
||||||
# Build a container for each program.
|
# Build the final base container. Use dumb-init as the entrypoint
|
||||||
# In the simple-case, it's just an entrypoint commit setting CMD.
|
# so that signals and subprocesses work properly.
|
||||||
# If a Dockerfile exists for the program, use it instead.
|
log.info("Build base container")
|
||||||
# Such a Dockerfile should use:
|
with docker_container(
|
||||||
# FROM {{ base_container }}-base
|
"python-base",
|
||||||
# This is useful for things like zuul-executor where the full story is
|
tag=info.base_container,
|
||||||
# not possible to express otherwise.
|
prefix=args.prefix,
|
||||||
for script in info.scripts:
|
volumes=[tmp_volume],
|
||||||
dockerfile = "Dockerfile.{script}".format(script=script)
|
comment='ENTRYPOINT ["/usr/bin/dumb-init", "--"]',
|
||||||
if os.path.exists(dockerfile):
|
) as cont:
|
||||||
log.info(
|
try:
|
||||||
"Building container for {script} from Dockerfile".format(
|
cont.run(
|
||||||
script=script))
|
"apk add {packages} dumb-init".format(
|
||||||
sh.docker.build("-f", dockerfile, "-t", script, ".")
|
packages=packages)
|
||||||
else:
|
)
|
||||||
log.info(
|
|
||||||
"Building container for {script}".format(script=script))
|
|
||||||
with docker_container(
|
|
||||||
info.base_container,
|
|
||||||
tag=script,
|
|
||||||
prefix=args.prefix,
|
|
||||||
volumes=[tmp_volume],
|
|
||||||
comment='CMD ["/usr/local/bin/{script}"]'.format(
|
|
||||||
script=script
|
|
||||||
),
|
|
||||||
) as cont:
|
|
||||||
cont.run(
|
cont.run(
|
||||||
"pip install"
|
"pip install"
|
||||||
" $(echo /root/.cache/pip/*.whl)[{script}]".format(
|
" $(echo /root/.cache/pip/*.whl)[{base}]".format(
|
||||||
script=script.replace('-', '_')))
|
base=info.base_container.replace('-', '_')))
|
||||||
|
if args.mirror:
|
||||||
|
cont.run(
|
||||||
|
"sed -i 's,{old},{new}'"
|
||||||
|
" /etc/apk/repositories".format(
|
||||||
|
old=args.mirror,
|
||||||
|
new=ALPINE_MIRROR_BASE))
|
||||||
|
# chown wheel cache back so the temp dir can delete it
|
||||||
|
cont.run("chown -R {uid} /root/.cache/pip".format(
|
||||||
|
uid=os.getuid()))
|
||||||
|
except Exception as e:
|
||||||
|
print(e.stdout)
|
||||||
|
raise
|
||||||
|
|
||||||
# chown wheel cache back so the temp dir can delete it
|
# Build a container for each program.
|
||||||
with docker_container(
|
# In the simple-case, it's just an entrypoint commit setting CMD.
|
||||||
"python-base",
|
# If a Dockerfile exists for the program, use it instead.
|
||||||
volumes=[tmp_volume],
|
# Such a Dockerfile should use:
|
||||||
) as cont:
|
# FROM {{ base_container }}-base
|
||||||
cont.run("chown -R {uid} /root/.cache/pip".format(uid=os.getuid()))
|
# This is useful for things like zuul-executor where the full
|
||||||
|
# story is not possible to express otherwise.
|
||||||
|
for script in info.scripts:
|
||||||
|
dockerfile = "Dockerfile.{script}".format(script=script)
|
||||||
|
if os.path.exists(dockerfile):
|
||||||
|
log.info(
|
||||||
|
"Building container for {script} from"
|
||||||
|
" Dockerfile".format(script=script))
|
||||||
|
sh.docker.build("-f", dockerfile, "-t", script, ".")
|
||||||
|
else:
|
||||||
|
log.info(
|
||||||
|
"Building container for {script}".format(
|
||||||
|
script=script))
|
||||||
|
with docker_container(
|
||||||
|
info.base_container,
|
||||||
|
tag=script,
|
||||||
|
prefix=args.prefix,
|
||||||
|
volumes=[tmp_volume],
|
||||||
|
comment='CMD ["/usr/local/bin/{script}"]'.format(
|
||||||
|
script=script
|
||||||
|
),
|
||||||
|
) as cont:
|
||||||
|
cont.run(
|
||||||
|
"pip install"
|
||||||
|
" $(echo /root/.cache/pip/*.whl)[{script}]".format(
|
||||||
|
script=script.replace('-', '_')))
|
||||||
|
|
||||||
|
finally:
|
||||||
|
# chown wheel cache back so the temp dir can delete it
|
||||||
|
with docker_container(
|
||||||
|
"python-base",
|
||||||
|
volumes=[tmp_volume],
|
||||||
|
) as cont:
|
||||||
|
cont.run(
|
||||||
|
"chown -R {uid} /root/.cache/pip".format(uid=os.getuid()))
|
||||||
|
|
Loading…
Reference in New Issue