Skip to content
This repository was archived by the owner on Oct 10, 2020. It is now read-only.
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 0 additions & 6 deletions Atomic/backends/_docker.py
Original file line number Diff line number Diff line change
Expand Up @@ -399,8 +399,6 @@ def uninstall(self, iobject, name=None, **kwargs):
if cmd:
return util.check_call(cmd, env=atomic.cmd_env())

# Delete the entry in the install data
util.InstallData.delete_by_id(iobject.id, ignore=ignore)
return self.delete_image(iobject.image, force=args.force)


Expand Down Expand Up @@ -457,10 +455,6 @@ def add_string_or_list_to_list(list_item, value):
else:
return self._start(iobject, args, atomic)

if iobject.get_label('INSTALL') and not args.ignore and not util.InstallData.image_installed(iobject):
raise ValueError("The image '{}' appears to have not been installed and has an INSTALL label. You "
"should install this image first. Re-run with --ignore to bypass this "
"error.".format(iobject.name or iobject.image))
# The object is an image
command = []
if iobject.run_command:
Expand Down
5 changes: 0 additions & 5 deletions Atomic/install.py
Original file line number Diff line number Diff line change
Expand Up @@ -135,11 +135,6 @@ def install(self):
name = img_obj.fq_name
except RegistryInspectError:
name = img_obj.input_name
install_data = {}
install_data[name] = {'id': img_obj.id,
'install_date': strftime("%Y-%m-%d %H:%M:%S", gmtime())
}
util.InstallData.write_install_data(install_data)
return util.check_call(cmd)

@staticmethod
Expand Down
115 changes: 1 addition & 114 deletions Atomic/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import json
import subprocess
import collections
from contextlib import contextmanager
from fnmatch import fnmatch as matches
import os
import selinux
Expand All @@ -31,10 +32,6 @@
ATOMIC_CONF = os.environ.get('ATOMIC_CONF', '/etc/atomic.conf')
ATOMIC_CONFD = os.environ.get('ATOMIC_CONFD', '/etc/atomic.d/')
ATOMIC_LIBEXEC = os.environ.get('ATOMIC_LIBEXEC', '/usr/libexec/atomic')
ATOMIC_VAR_LIB = os.environ.get('ATOMIC_VAR_LIB', '/var/lib/atomic')
if not os.path.exists(ATOMIC_VAR_LIB):
os.makedirs(ATOMIC_VAR_LIB)
ATOMIC_INSTALL_JSON = os.environ.get('ATOMIC_INSTALL_JSON', os.path.join(ATOMIC_VAR_LIB, 'install.json'))

GOMTREE_PATH = "/usr/bin/gomtree"
BWRAP_OCI_PATH = "/usr/bin/bwrap-oci"
Expand Down Expand Up @@ -761,116 +758,6 @@ def load_scan_result_file(file_name):
return json.loads(open(os.path.join(file_name), "r").read())


def file_lock(func):
lock_file_name = "{}.lock".format(os.path.join(os.path.dirname(ATOMIC_INSTALL_JSON), "." + os.path.basename(ATOMIC_INSTALL_JSON)))

# Create the temporary lockfile if it doesn't exist
if not os.path.exists(lock_file_name):
open(lock_file_name, 'a').close()

install_data_file = open(lock_file_name, "r")

def get_lock():
'''
Obtains a read-only file lock on the install data
:return:
'''
time_out = 0
f_lock = False
while time_out < 10.5: # Ten second attempt to get a lock
try:
fcntl.flock(install_data_file, fcntl.LOCK_EX | fcntl.LOCK_NB)
f_lock = True
break
except IOError:
time.sleep(.5)
time_out += .5
if not f_lock:
raise ValueError("Unable to get file lock for {}".format(ATOMIC_INSTALL_JSON))

def release_lock():
fcntl.flock(install_data_file, fcntl.LOCK_UN)

def wrapper(*args, **kwargs):
get_lock()
ret = func(*args, **kwargs)
release_lock()
return ret

return wrapper


class InstallData(object):
if not os.path.exists(ATOMIC_INSTALL_JSON):
open(ATOMIC_INSTALL_JSON, 'a').close()

install_file_handle = open(ATOMIC_INSTALL_JSON, 'r')

@staticmethod
def _read_install_data(file_handle):
try:
return json.loads(file_handle.read())
except ValueError:
return {}

@classmethod
def _write_install_data(cls, new_data):
install_data = cls._read_install_data(cls.install_file_handle)
for x in new_data:
install_data[x] = new_data[x]
temp_file = tempfile.NamedTemporaryFile(mode='w', delete=False)
json.dump(install_data, temp_file)
temp_file.close()
shutil.move(temp_file.name, ATOMIC_INSTALL_JSON)

@classmethod
@file_lock
def read_install_data(cls):
if os.path.exists(ATOMIC_INSTALL_JSON):
read_data = cls._read_install_data(cls.install_file_handle)
return read_data
return {}

@classmethod
@file_lock
def write_install_data(cls, new_data):
cls._write_install_data(new_data)

@classmethod
def get_install_name_by_id(cls, iid, install_data=None):
if not install_data:
install_data = cls._read_install_data(cls.install_file_handle)
for installed_image in install_data:
if install_data[installed_image]['id'] == iid:
return installed_image
raise ValueError("Unable to find {} in installed image data ({}). Re-run command with -i to ignore".format(id, ATOMIC_INSTALL_JSON))

@classmethod
@file_lock
def delete_by_id(cls, iid, ignore=False):
install_data = cls._read_install_data(cls.install_file_handle)
try:
id_key = InstallData.get_install_name_by_id(iid, install_data=install_data)
except ValueError as e:
if not ignore:
raise ValueError(str(e))
return
del install_data[id_key]
return cls._write_install_data(install_data)

@classmethod
def image_installed(cls, img_object):
install_data = cls.read_install_data()
if install_data.get(img_object.id, None):
return True
if install_data.get(img_object.input_name, None):
return True
if install_data.get(img_object.name, None):
return True
if install_data.get(img_object.image, None):
return True
return False

class Decompose(object):
"""
Class for decomposing an input string in its respective parts like registry,
Expand Down
88 changes: 0 additions & 88 deletions tests/unit/test_util.py
Original file line number Diff line number Diff line change
Expand Up @@ -155,93 +155,5 @@ def reset_data(cls):
def grow_data(cls, var_name, name):
cls.install_data[name] = getattr(cls, var_name)

local_centos_inspect = {'Id': '16e9fdecc1febc87fb1ca09271009cf5f28eb8d4aec5515922ef298c145a6726', 'RepoDigests': ['docker.io/centos@sha256:7793b39617b28c6cd35774c00383b89a1265f3abf6efcaf0b8f4aafe4e0662d2'], 'Parent': '', 'GraphDriver': {'Name': 'devicemapper', 'Data': {'DeviceSize': '10737418240', 'DeviceName': 'docker-253:2-5900125-3fb5b406e6a53142129237c9e2c3a1ce8b6cf269b5f8071fcd62107c41544cd2', 'DeviceId': '779'}}, 'Created': '2016-08-30T18:20:19.39890162Z', 'Comment': '', 'DockerVersion': '1.12.1', 'VirtualSize': 210208812, 'Author': 'The CentOS Project <cloud-ops@centos.org> - ami_creator', 'Os': 'linux', 'RootFS': {'Type': 'layers', 'Layers': ['5fa0fa02637842ab1ddc8b3a17b86691c87c87d20800e6a95a113343f6ffd84c']}, 'Container': 'a5b0819aa82c224095e1a18e9df0776a7b38d32bacca073f054723b65fb54f0e', 'Architecture': 'amd64', 'RepoTags': ['docker.io/centos:centos7.0.1406'], 'Config': {'Labels': {}, 'Entrypoint': None, 'StdinOnce': False, 'OnBuild': None, 'Env': ['PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin'], 'Volumes': None, 'Cmd': None, 'User': '', 'AttachStdin': False, 'AttachStderr': False, 'AttachStdout': False, 'WorkingDir': '', 'Tty': False, 'Image': '20ae10d641a0af6f25ceaa75fdcf591d171e3c521a54a3f3a2868b602d735e11', 'Hostname': 'a5b0819aa82c', 'Domainname': '', 'OpenStdin': False}, 'Size': 210208812, 'ContainerConfig': {'Labels': {}, 'Entrypoint': None, 'StdinOnce': False, 'OnBuild': None, 'Env': ['PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin'], 'Volumes': None, 'Cmd': ['/bin/sh', '-c', '#(nop) ADD file:6a409eac27f0c7e04393da096dbeff01b929405e79b15222a0dc06a2084d3df3 in / '], 'User': '', 'AttachStdin': False, 'AttachStderr': False, 'AttachStdout': False, 'WorkingDir': '', 'Tty': False, 'Image': '20ae10d641a0af6f25ceaa75fdcf591d171e3c521a54a3f3a2868b602d735e11', 'Hostname': 'a5b0819aa82c', 'Domainname': '', 'OpenStdin': False}}
rhel_docker_inspect = {u'Comment': u'', u'Container': u'', u'DockerVersion': u'1.9.1', u'Parent': u'', u'Created': u'2016-10-26T12:02:33.368772Z', u'Config': {u'Tty': False, u'Cmd': [u'/bin/bash'], u'Volumes': None, u'Domainname': u'', u'WorkingDir': u'', u'Image': u'f6f6121b053b2312688c87d3a1d32d06a984dc01d2ea7738508a50581cddb6b4', u'Hostname': u'', u'StdinOnce': False, u'Labels': {u'com.redhat.component': u'rhel-server-docker', u'authoritative-source-url': u'registry.access.redhat.com', u'distribution-scope': u'public', u'Vendor': u'Red Hat, Inc.', u'Name': u'rhel7/rhel', u'Build_Host': u'rcm-img01.build.eng.bos.redhat.com', u'vcs-type': u'git', u'name': u'rhel7/rhel', u'vcs-ref': u'7eeaf203cf909c2c056fba7066db9c1073a28d97', u'release': u'45', u'Version': u'7.3', u'Architecture': u'x86_64', u'version': u'7.3', u'Release': u'45', u'vendor': u'Red Hat, Inc.', u'BZComponent': u'rhel-server-docker', u'build-date': u'2016-10-26T07:54:17.037911Z', u'com.redhat.build-host': u'ip-10-29-120-48.ec2.internal', u'architecture': u'x86_64'}, u'AttachStdin': False, u'User': u'', u'Env': [u'PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin', u'container=docker'], u'Entrypoint': None, u'OnBuild': [], u'AttachStderr': False, u'AttachStdout': False, u'OpenStdin': False}, u'Author': u'Red Hat, Inc.', u'GraphDriver': {u'Data': {u'DeviceName': u'docker-253:2-5900125-a2bce97a4fd7ea12dce9865caa461ead8d1caf51ef452aba2f1b9d98efdf968f', u'DeviceSize': u'10737418240', u'DeviceId': u'623'}, u'Name': u'devicemapper'}, u'VirtualSize': 192508958, u'Os': u'linux', u'Architecture': u'amd64', u'RootFS': {u'Layers': [u'34d3e0e77091d9d51c6f70a7a7a4f7536aab214a55e02a8923af8f80cbe60d30', u'ccd6fc81ec49bd45f04db699401eb149b1945bb7292476b390ebdcdd7d975697'], u'Type': u'layers'}, u'ContainerConfig': {u'Tty': False, u'Cmd': None, u'Volumes': None, u'Domainname': u'', u'WorkingDir': u'', u'Image': u'', u'Hostname': u'', u'StdinOnce': False, u'Labels': None, u'AttachStdin': False, u'User': u'', u'Env': None, u'Entrypoint': None, u'OnBuild': None, u'AttachStderr': False, u'AttachStdout': False, u'OpenStdin': False}, u'Size': 192508958, u'RepoDigests': [u'registry.access.redhat.com/rhel7@sha256:da8a3e9297da7ccd1948366103d13c45b7e77489382351a777a7326004b63a21'], u'Id': u'f98706e16e41e56c4beaeea9fa77cd00fe35693635ed274f128876713afc0a1e', u'RepoTags': [u'registry.access.redhat.com/rhel7:latest']}


@unittest.skipIf(no_mock, "Mock not found")
class InstallData(unittest.TestCase):

class Args():
def __init__(self):
self.storage = None
self.debug = False
self.name = None
self.image = None

@patch('Atomic.util.InstallData.read_install_data', new=MockIO.read_mock)
@patch('Atomic.util.InstallData._read_install_data', new=MockIO.read_mock)
@patch('Atomic.util.InstallData.write_install_data', new=MockIO.write_mock)
def test_read(self):
MockIO.reset_data()
self.assertEqual(util.InstallData.read_install_data(), MockIO.install_data)

@patch('Atomic.util.InstallData.read_install_data', new=MockIO.read_mock)
@patch('Atomic.util.InstallData._read_install_data', new=MockIO.read_mock)
@patch('Atomic.util.InstallData.write_install_data', new=MockIO.write_mock)
def test_write(self):
MockIO.reset_data()
install_data = util.InstallData.read_install_data()
install_data['docker.io/library/centos:latest'] = MockIO.new_data_fq
util.InstallData.write_install_data(install_data)
self.assertTrue('docker.io/library/centos:latest' in util.InstallData.read_install_data())

@patch('Atomic.util.InstallData.read_install_data', new=MockIO.read_mock)
@patch('Atomic.util.InstallData._read_install_data', new=MockIO.read_mock)
@patch('Atomic.util.InstallData.write_install_data', new=MockIO.write_mock)
def test_get_install_name_by_id(self):
MockIO.reset_data()
MockIO.grow_data('new_data_fq', 'docker.io/library/centos:latest')
self.assertEqual(util.InstallData.get_install_name_by_id('16e9fdecc1febc87fb1ca09271009cf5f28eb8d4aec5515922ef298c145a6726', install_data=MockIO.install_data), 'docker.io/library/centos:latest')

@patch('Atomic.util.InstallData.read_install_data', new=MockIO.read_mock)
@patch('Atomic.util.InstallData._read_install_data', new=MockIO.read_mock)
@patch('Atomic.util.InstallData.write_install_data', new=MockIO.write_mock)
def test_fail_get_install_name_by_id(self):
MockIO.reset_data()
self.assertRaises(ValueError, util.InstallData.get_install_name_by_id, 1, MockIO.install_data)

@patch('Atomic.util.InstallData.read_install_data', new=MockIO.read_mock)
@patch('Atomic.util.InstallData._read_install_data', new=MockIO.read_mock)
@patch('Atomic.util.InstallData.write_install_data', new=MockIO.write_mock)
def test_image_installed_name(self):
MockIO.reset_data()
MockIO.grow_data('new_data_fq', 'docker.io/library/centos:latest')
args = self.Args()
args.storage = 'docker'
args.image = 'docker.io/library/centos:latest'
db = DockerBackend()
db._inspect_image = MagicMock(return_value=local_centos_inspect)
local_image_object = db.inspect_image(args.image)
self.assertTrue(util.InstallData.image_installed(local_image_object))

@patch('Atomic.util.InstallData.read_install_data', new=MockIO.read_mock)
@patch('Atomic.util.InstallData._read_install_data', new=MockIO.read_mock)
@patch('Atomic.util.InstallData.write_install_data', new=MockIO.write_mock)
def test_image_installed_id(self):
MockIO.reset_data()
MockIO.grow_data('new_data_fq', '16e9fdecc1febc87fb1ca09271009cf5f28eb8d4aec5515922ef298c145a6726')
args = self.Args()
args.storage = 'docker'
args.image = 'docker.io/library/centos:latest'
db = DockerBackend()
db._inspect_image = MagicMock(return_value=local_centos_inspect)
local_image_object = db.inspect_image(args.image)
self.assertTrue(util.InstallData.image_installed(local_image_object))

@patch('Atomic.util.InstallData.read_install_data', new=MockIO.read_mock)
@patch('Atomic.util.InstallData._read_install_data', new=MockIO.read_mock)
@patch('Atomic.util.InstallData.write_install_data', new=MockIO.write_mock)
def test_image_not_installed(self):
MockIO.reset_data()
args = self.Args()
args.storage = 'docker'
args.image = 'registry.access.redhat.com/rhel7'
db = DockerBackend()
db._inspect_image = MagicMock(return_value=rhel_docker_inspect)
local_image_object = db.inspect_image(args.image)
self.assertFalse(util.InstallData.image_installed(local_image_object))


if __name__ == '__main__':
unittest.main()