Skip to content

Commit

Permalink
Removing multiple options to instantiate Image class
Browse files Browse the repository at this point in the history
This commit does following,
1. Modifies the Image class to be instantiated
with a generic repotag property
2. Removes the ImageID property
3. Modifies the tests appropriately

Resolved: #747

Signed-off-by: mukultaneja <[email protected]>
  • Loading branch information
mukultaneja authored and Nisha K committed Jun 29, 2020
1 parent fd147bf commit abf6e91
Show file tree
Hide file tree
Showing 6 changed files with 37 additions and 68 deletions.
72 changes: 24 additions & 48 deletions tern/classes/docker_image.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,35 +24,31 @@ class DockerImage(Image):
history: a list of commands used to create the filesystem layers
to_dict: return a dict representation of the object
'''
def __init__(self, repotag=None, image_id=None):
'''Initialize using repotag and image_id'''
super().__init__(image_id)
self.__repotag = repotag
def __init__(self, repotag=None):
'''Initialize using repotag'''
super().__init__(repotag)
self.__repotags = []
self.__history = None
if self.repotag is not None:
# parse the repotag
repo_dict = general.parse_image_string(self.__repotag)
self._name = repo_dict.get('name')
self._tag = repo_dict.get('tag')
self.set_checksum(
repo_dict.get('digest_type'), repo_dict.get('digest'))
if not self.checksum and general.check_tar(repotag) is False:
# if there is no checksum, get the digest type
docker_image = container.check_image(self.__repotag)
# this object could be representing an image built from
# a Dockerfile, so it may not have a digest
# so check for that condition
if docker_image.attrs['RepoDigests']:
image_name_digest = container.get_image_digest(
docker_image)
repo_dict = general.parse_image_string(image_name_digest)
self.set_checksum(
repo_dict.get('digest_type'), repo_dict.get('digest'))

@property
def repotag(self):
return self.__repotag
if self.repotag is None:
raise NameError("Image object initialized with no repotag")

# parse the repotag
repo_dict = general.parse_image_string(self._repotag)
self._name = repo_dict.get('name')
self._tag = repo_dict.get('tag')
self.set_checksum(
repo_dict.get('digest_type'), repo_dict.get('digest'))
if not self.checksum and general.check_tar(repotag) is False:
# if there is no checksum, get the digest type
docker_image = container.check_image(self._repotag)
# this object could be representing an image built from
# a Dockerfile, so it may not have a digest
# so check for that condition
if docker_image.attrs['RepoDigests']:
image_name_digest = container.get_image_digest(docker_image)
repo_dict = general.parse_image_string(image_name_digest)
self.set_checksum(
repo_dict.get('digest_type'), repo_dict.get('digest'))

@property
def repotags(self):
Expand All @@ -68,18 +64,6 @@ def to_dict(self, template=None):
di_dict = super().to_dict(template)
return di_dict

def get_image_option(self):
'''Check to see which value was used to init the image object
Return the value that was used. If neither one was used raise
NameError. If both were used return the id'''
if self.repotag is not None and self.image_id is not None:
return self.image_id
if self.repotag is not None:
return self.repotag
if self.image_id is not None:
return self.image_id
raise NameError("Image object initialized with no repotag or ID")

def get_image_manifest(self):
'''Assuming that there is a temp folder with a manifest.json of
an image inside, get a dict of the manifest.json file'''
Expand All @@ -100,12 +84,6 @@ def get_image_config_file(self, manifest):
'''Given the manifest, return the config file'''
return manifest[0].get('Config')

def get_image_id(self, manifest):
'''Given the manifest, return the image id
This happens to be the config file's sha256sum'''
config_file = self.get_image_config_file(manifest)
return config_file.split('.')[0]

def get_image_repotags(self, manifest):
'''Given the manifest, return the list of image tag strings'''
return manifest[0].get('RepoTags')
Expand Down Expand Up @@ -163,10 +141,8 @@ def set_layer_created_by(self):
def load_image(self):
'''Load image metadata using docker commands'''
try:
option = self.get_image_option()
container.extract_image_metadata(option)
container.extract_image_metadata(self.repotag)
self._manifest = self.get_image_manifest()
self._image_id = self.get_image_id(self._manifest)
self.__repotags = self.get_image_repotags(self._manifest)
self._config = self.get_image_config(self._manifest)
self.__history = self.get_image_history(self._config)
Expand Down
12 changes: 6 additions & 6 deletions tern/classes/image.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,9 @@ class Image:
add_checksums: add new checksums in the existing list of the checksums
to_dict: return a python dictionary representation of the image
'''
def __init__(self, image_id=None):
'''Either initialize using id'''
self._image_id = image_id
def __init__(self, repotag=None):
'''Initialize using the image's repo name and tag string'''
self._repotag = repotag
self._name = ''
self._tag = ''
self._manifest = {}
Expand All @@ -44,8 +44,8 @@ def manifest(self):
return self._manifest

@property
def image_id(self):
return self._image_id
def repotag(self):
return self._repotag

@property
def config(self):
Expand Down Expand Up @@ -170,7 +170,7 @@ def get_human_readable_id(self):
'''Some reports like SPDX want a unique name for the full image
and this is currently not supported by any image tool. So using
a combination of image id, name and tag instead'''
name = self.image_id[:10]
name = self.repotag[:10]
if self.name:
name = name + '-{}'.format(self.name)
if self.tag:
Expand Down
7 changes: 0 additions & 7 deletions tests/test_class_docker_image.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,6 @@ def setUp(self):
'a9a20752aa1ad7582c667704fda9f00'
'4cc4bfd8601fac7f2656c7567bb4')
# constants for this image
self.image_id = ('acb194ad84d0f9734e794fbbdbb65fb'
'7db6eda83f33e9e817bcc75b1bdd99f5e')
self.layer = ('c1c3a87012e7ff5791b31e94515b661'
'cdf06f6d5dc2f9a6245eda8774d257a13')
self.no_layers = 1
Expand Down Expand Up @@ -76,7 +74,6 @@ def testInstance(self):
self.assertTrue(self.image.checksum, '20b32a9a20752aa1ad7582c66'
'7704fda9f004cc4bfd8601fac7'
'f2656c7567bb4')
self.assertFalse(self.image.image_id)
self.assertFalse(self.image.manifest)
self.assertFalse(self.image.repotags)
self.assertFalse(self.image.config)
Expand All @@ -98,16 +95,12 @@ def testInstance(self):

def testLoadImage(self):
self.image.load_image()
self.assertEqual(self.image.image_id, self.image_id)
self.assertEqual(self.image.layers[0].diff_id, self.layer)
self.assertEqual(len(self.image.layers), self.no_layers)
self.assertEqual(self.image.layers[0].created_by, self.created_by)
self.assertEqual(self.image.layers[0].checksum_type, 'sha256')
self.assertEqual(self.image.layers[0].checksum, self.layer)

def testGetImageOption(self):
self.assertEqual(self.image.get_image_option(), self.image.repotag)

def testGetLayerDiffIds(self):
self.image.load_image()
self.assertEqual(len(self.image.get_layer_diff_ids()), self.no_layers)
Expand Down
8 changes: 4 additions & 4 deletions tests/test_class_image.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ def tearDown(self):
del self.image3

def testInstance(self):
self.assertEqual(self.image1.image_id, '1234abcd')
self.assertEqual(self.image1.repotag, '1234abcd')
self.assertFalse(self.image1.name)
self.assertFalse(self.image1.manifest)
self.assertFalse(self.image1.tag)
Expand All @@ -35,7 +35,7 @@ def testInstance(self):
self.assertIsInstance(self.image1.origins, Origins)

def testLoadImage(self):
self.assertEqual(self.image2.image_id, '5678efgh')
self.assertEqual(self.image2.repotag, '5678efgh')
self.assertFalse(self.image2.layers)
self.assertFalse(self.image2.name)
self.assertFalse(self.image2.tag)
Expand All @@ -57,7 +57,7 @@ def testGetLayerObject(self):
def testToDict(self):
self.image2.load_image()
a_dict = self.image2.to_dict()
self.assertEqual(a_dict['image_id'], '5678efgh')
self.assertEqual(a_dict['repotag'], '5678efgh')
self.assertEqual(len(a_dict['layers']), 1)
self.assertEqual(len(a_dict['layers'][0]['packages']), 2)

Expand All @@ -68,7 +68,7 @@ def testToDictTemplate(self):
dict1 = self.image2.to_dict(template1)
dict2 = self.image2.to_dict(template2)
self.assertEqual(len(dict1.keys()), 2)
self.assertEqual(dict1['image.id'], '5678efgh')
self.assertEqual(dict1['image.repotag'], '5678efgh')
self.assertEqual(len(dict1['image.layers']), 1)
self.assertEqual(len(dict2.keys()), 3)
self.assertFalse(dict2['notes'])
Expand Down
2 changes: 1 addition & 1 deletion tests/test_class_template.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ def testImageLayer(self):

def testImage(self):
mapping = self.template1.image()
self.assertEqual(mapping['image_id'], 'image.id')
self.assertEqual(mapping['repotag'], 'image.repotag')
self.assertEqual(mapping['layers'], 'image.layers')

def testNotice(self):
Expand Down
4 changes: 2 additions & 2 deletions tests/test_fixtures.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ def image_layer(self):
'files': 'layer.files'}

def image(self):
return {'image_id': 'image.id',
return {'repotag': 'image.repotag',
'layers': 'image.layers'}


Expand Down Expand Up @@ -80,7 +80,7 @@ def image_layer(self):
return mapping

def image(self):
mapping = {'image_id': 'image.id',
mapping = {'repotag': 'image.repotag',
'layers': 'image.layers'}
# we update the mapping with another defined mapping
mapping.update(self.origins())
Expand Down

0 comments on commit abf6e91

Please sign in to comment.