Skip to content

Commit

Permalink
merge: Fix overlayfs mount location
Browse files Browse the repository at this point in the history
This merge pulls in the fix for #498 

Changes to move the working directory where the overlayfs
mounts occur to a hidden folder in the user's home directory
didn't take into account the Docker use case. Overlayfs mounts
do not work within a running container. These changes move
the cache.yml file and the working directory (temp) into the
container's volume mount. This leaves open the possibility of
mounted filesystems remaining mounted if anything were to go
wrong.

Signed-off-by: Nisha K <nishak@vmware.com>
  • Loading branch information
Nisha K authored Dec 3, 2019
2 parents a7f4dbf + e6e6605 commit 4333368
Show file tree
Hide file tree
Showing 9 changed files with 56 additions and 27 deletions.
4 changes: 2 additions & 2 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ RUN tdnf remove -y toybox && tdnf install -y tar findutils attr util-linux pytho
RUN pip3 install --upgrade pip && pip3 install tern

# make a mounting directory
RUN mkdir temp
RUN mkdir hostmount

ENTRYPOINT ["tern", "-b"]
ENTRYPOINT ["tern", "-b", "/hostmount"]
CMD ["-h"]
22 changes: 22 additions & 0 deletions ci/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# Copyright (c) 2019 VMware, Inc. All Rights Reserved.
# SPDX-License-Identifier: BSD-2-Clause

FROM photon:3.0

# install system dependencies
# photon:3.0 comes with toybox which conflicts with some dependencies needed for tern to work, so uninstalling
# toybox first
RUN tdnf remove -y toybox && tdnf install -y tar findutils attr util-linux python3 python3-pip python3-setuptools git

# install pip
RUN pip3 install --upgrade pip

# install tern with latest changes
COPY dist/tern-*.tar.gz .
RUN pip install tern-*.tar.gz

# make a mounting directory
RUN mkdir hostmount

ENTRYPOINT ["tern", "-b", "/hostmount"]
CMD ["-h"]
3 changes: 2 additions & 1 deletion ci/test_files_touched.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,8 @@
re.compile('requirements.txt'): ['tern -l report -i photon:3.0'],
# Dockerfile
re.compile('Dockerfile'): [
'docker build -t ternd .',
'python3 setup.py sdist && '
'docker build -t ternd -f ci/Dockerfile . && '
'./docker_run.sh workdir ternd "report -i golang:alpine"'],
# Files under tern directory
re.compile('tern/__init__.py|tern/__main__.py'):
Expand Down
2 changes: 1 addition & 1 deletion docker_run.sh
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,4 @@
# Example: ./docker_run.sh workdir ternd "report -i golang:alpine"

mkdir -p $1
docker run --privileged -v /var/run/docker.sock:/var/run/docker.sock --mount type=bind,source=$PWD/$1,target=/temp $2 $3
docker run --privileged -v /var/run/docker.sock:/var/run/docker.sock --mount type=bind,source=$PWD/$1,target=/hostmount $2 $3
9 changes: 6 additions & 3 deletions tern/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
from tern.utils import cache
from tern.utils import constants
from tern.utils import general
from tern.utils import rootfs
from tern.report import errors


Expand Down Expand Up @@ -69,6 +70,8 @@ def create_top_dir():

def do_main(args):
'''Execute according to subcommands'''
# set bind mount location if working in a container
rootfs.set_mount_dir(args.bind_mount)
# create working directory
create_top_dir()
if args.log_stream:
Expand Down Expand Up @@ -115,9 +118,9 @@ def main():
parser.add_argument('-k', '--keep-wd', action='store_true',
help="Keep the working directory after execution."
" Useful when debugging container images")
parser.add_argument('-b', '--bind-mount', action='store_true',
help="Treat working directory as a bind mount."
" Needed when running from within a container")
parser.add_argument('-b', '--bind-mount', metavar='BIND_DIR',
help="Absolute path to bind mount target. Needed"
" when running from within a container.")
parser.add_argument('-r', '--redo', action='store_true',
help="Repopulate the cache for found layers")
# sys.version gives more information than we care to print
Expand Down
4 changes: 2 additions & 2 deletions tern/analyze/docker/run.py
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ def execute_docker_image(args):
logger.debug('Teardown...')
report.teardown()
if not args.keep_wd:
report.clean_working_dir(args.bind_mount)
report.clean_working_dir()


def execute_dockerfile(args):
Expand Down Expand Up @@ -161,4 +161,4 @@ def execute_dockerfile(args):
logger.debug('Teardown...')
report.teardown()
if not args.keep_wd:
report.clean_working_dir(args.bind_mount)
report.clean_working_dir()
14 changes: 2 additions & 12 deletions tern/report/report.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,22 +77,12 @@ def clean_image_tars(image_obj):
rootfs.root_command(rootfs.remove, fspath)


def clean_working_dir(bind_mount):
def clean_working_dir():
'''Clean up the working directory
If bind_mount is true then leave the upper level directory'''
path = rootfs.get_working_dir()
if os.path.exists(path):
if bind_mount:
# clean whatever is in temp_folder without removing the folder
inodes = os.listdir(path)
for inode in inodes:
dir_path = os.path.join(path, inode)
if os.path.isdir(dir_path):
shutil.rmtree(dir_path)
else:
os.remove(dir_path)
else:
shutil.rmtree(path)
shutil.rmtree(path)


def load_base_image():
Expand Down
10 changes: 5 additions & 5 deletions tern/utils/cache.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
import os
import yaml
from tern.utils.constants import cache_file
from tern.utils.general import get_top_dir
from tern.utils import rootfs

# known base image database
cache = {}
Expand All @@ -30,10 +30,10 @@ def load():
global cache

# Do not try to populate the cache if there is no cache available
if not os.path.exists(os.path.join(get_top_dir(), cache_file)):
if not os.path.exists(os.path.join(rootfs.mount_dir, cache_file)):
return

with open(os.path.join(get_top_dir(), cache_file)) as f:
with open(os.path.join(rootfs.mount_dir, cache_file)) as f:
cache = yaml.safe_load(f)


Expand Down Expand Up @@ -69,7 +69,7 @@ def add_layer(layer_obj):

def save():
'''Save the cache to the cache file'''
with open(os.path.join(get_top_dir(), cache_file), 'w') as f:
with open(os.path.join(rootfs.mount_dir, cache_file), 'w') as f:
yaml.dump(cache, f, default_flow_style=False)


Expand All @@ -86,5 +86,5 @@ def clear():
'''Empty the cache - don't use unless you really have to'''
global cache
cache = {}
with open(os.path.join(get_top_dir(), cache_file), 'w') as f:
with open(os.path.join(rootfs.mount_dir, cache_file), 'w') as f:
yaml.dump(cache, f, default_flow_style=False)
15 changes: 14 additions & 1 deletion tern/utils/rootfs.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@
mount_dev = ['mount', '-o', 'bind', '/dev']
unmount = ['umount']

mount_dir = None

# enable host DNS settings
host_dns = ['cp', constants.resolv_path]

Expand All @@ -43,6 +45,17 @@
logger = logging.getLogger(constants.logger_name)


def set_mount_dir(bind=None):
'''Set mount directory according to --bind-mount CLI option (or lack
thereof). The mount_dir value is used to set the working directory
properly in get_working_dir().'''
global mount_dir
if bind:
mount_dir = bind
else:
mount_dir = general.get_top_dir()


def root_command(command, *extra):
'''Invoke a shell command as root or using sudo. The command is a
list of shell command words'''
Expand Down Expand Up @@ -105,7 +118,7 @@ def check_tar_members(tar_file):
def get_working_dir():
'''General purpose utility to return the absolute path of the working
directory'''
return os.path.join(general.get_top_dir(), constants.temp_folder)
return os.path.join(mount_dir, constants.temp_folder)


def get_untar_dir(layer_tarfile):
Expand Down

0 comments on commit 4333368

Please sign in to comment.